From 9628c7e52006fe248978d9a926e161696987f5c5 Mon Sep 17 00:00:00 2001 From: Neil Hansen <51208969+neilyio@users.noreply.github.com> Date: Sun, 7 Apr 2024 13:38:47 -0500 Subject: Fix empty output in csv_vectors example (#89) --- examples/csv_vectors.rs | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/examples/csv_vectors.rs b/examples/csv_vectors.rs index 78ed6af..9d5e0ea 100644 --- a/examples/csv_vectors.rs +++ b/examples/csv_vectors.rs @@ -3,9 +3,7 @@ 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, PartialEq, Deserialize, Serialize)] @@ -35,21 +33,25 @@ fn deserialize_sequence() { fn from_csv<'de, D, T>(deserializer: D) -> Result, D::Error> where D: serde::Deserializer<'de>, - T: DeserializeOwned, + T: DeserializeOwned + std::str::FromStr, + ::Err: std::fmt::Debug, { deserializer.deserialize_str(CSVVecVisitor::::default()) } /// Visits a string value of the form "v1,v2,v3" into a vector of bytes Vec -struct CSVVecVisitor(std::marker::PhantomData); +struct CSVVecVisitor(std::marker::PhantomData); -impl Default for CSVVecVisitor { +impl Default for CSVVecVisitor { fn default() -> Self { CSVVecVisitor(std::marker::PhantomData) } } -impl<'de, T: DeserializeOwned> serde::de::Visitor<'de> for CSVVecVisitor { +impl<'de, T: DeserializeOwned + std::str::FromStr> serde::de::Visitor<'de> for CSVVecVisitor +where + ::Err: std::fmt::Debug, // handle the parse error in a generic way +{ type Value = Vec; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -60,12 +62,31 @@ impl<'de, T: DeserializeOwned> serde::de::Visitor<'de> for CSVVecVisitor { 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::() + .map_err(|_| E::custom("Failed to parse field"))?, + ); + } + } + Err(e) => { + return Err(E::custom(format!( + "could not deserialize sequence value: {:?}", + e + ))); + } + } } Ok(output) -- cgit v1.2.3