diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/csv_vectors.rs | 56 | ||||
| -rw-r--r-- | examples/introduction.rs | 2 | 
2 files changed, 45 insertions, 13 deletions
diff --git a/examples/csv_vectors.rs b/examples/csv_vectors.rs index c193c64..2e44566 100644 --- a/examples/csv_vectors.rs +++ b/examples/csv_vectors.rs @@ -3,12 +3,10 @@ extern crate serde;  #[macro_use]  extern crate serde_derive;  extern crate serde_qs as qs; -  use serde::de::DeserializeOwned; -  use std::default::Default; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Deserialize, Serialize)]  struct Query {      #[serde(deserialize_with = "from_csv")]      r: Vec<u8>, @@ -21,24 +19,39 @@ fn main() {      println!("{:?}", q);  } +#[test] +fn deserialize_sequence() { +    let q = "s=12&r=1,2,3"; +    let q: Query = qs::from_str(q).unwrap(); +    let expected = Query { +        r: vec![1, 2, 3], +        s: 12, +    }; +    assert_eq!(q, expected); +} +  fn from_csv<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>  where      D: serde::Deserializer<'de>, -    T: DeserializeOwned, +    T: DeserializeOwned + std::str::FromStr, +    <T as std::str::FromStr>::Err: std::fmt::Debug,  {      deserializer.deserialize_str(CSVVecVisitor::<T>::default())  }  /// Visits a string value of the form "v1,v2,v3" into a vector of bytes Vec<u8> -struct CSVVecVisitor<T: DeserializeOwned>(std::marker::PhantomData<T>); +struct CSVVecVisitor<T: DeserializeOwned + std::str::FromStr>(std::marker::PhantomData<T>); -impl<T: DeserializeOwned> Default for CSVVecVisitor<T> { +impl<T: DeserializeOwned + std::str::FromStr> Default for CSVVecVisitor<T> {      fn default() -> Self {          CSVVecVisitor(std::marker::PhantomData)      }  } -impl<'de, T: DeserializeOwned> serde::de::Visitor<'de> for CSVVecVisitor<T> { +impl<T: DeserializeOwned + std::str::FromStr> serde::de::Visitor<'_> for CSVVecVisitor<T> +where +    <T as std::str::FromStr>::Err: std::fmt::Debug, // handle the parse error in a generic way +{      type Value = Vec<T>;      fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -49,12 +62,31 @@ impl<'de, T: DeserializeOwned> serde::de::Visitor<'de> for CSVVecVisitor<T> {      where          E: serde::de::Error,      { +        // Treat the comma-separated string as a single record in a CSV. +        let mut rdr = csv::ReaderBuilder::new() +            .has_headers(false) +            .from_reader(s.as_bytes()); + +        // Try to get the record and collect its values into a vector.          let mut output = Vec::new(); -        let mut items = csv::Reader::from_reader(s.as_bytes()); -        for res in items.deserialize() { -            let item: T = res -                .map_err(|e| E::custom(format!("could not deserialize sequence value: {:?}", e)))?; -            output.push(item); +        for result in rdr.records() { +            match result { +                Ok(record) => { +                    for field in record.iter() { +                        output.push( +                            field +                                .parse::<T>() +                                .map_err(|_| E::custom("Failed to parse field"))?, +                        ); +                    } +                } +                Err(e) => { +                    return Err(E::custom(format!( +                        "could not deserialize sequence value: {:?}", +                        e +                    ))); +                } +            }          }          Ok(output) diff --git a/examples/introduction.rs b/examples/introduction.rs index 10e7a8b..bf4c508 100644 --- a/examples/introduction.rs +++ b/examples/introduction.rs @@ -101,7 +101,7 @@ fn main() {          "user_ids[3]=4",      ]; -    let mut rng = rand::thread_rng(); +    let mut rng = rand::rng();      for _ in 0..10 {          let mut acc = String::new();          inputs.shuffle(&mut rng);  | 
