summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Hansen <51208969+neilyio@users.noreply.github.com>2024-04-07 13:38:47 -0500
committerGitHub <noreply@github.com>2024-04-07 13:38:47 -0500
commit9628c7e52006fe248978d9a926e161696987f5c5 (patch)
tree0296339ea5e23b9aa26e83d7147e86dd51005886
parent17528729b51578c034cec5efd8599535076a8dd3 (diff)
Fix empty output in csv_vectors example (#89)
-rw-r--r--examples/csv_vectors.rs43
1 files 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<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<'de, T: DeserializeOwned + std::str::FromStr> serde::de::Visitor<'de> 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 {
@@ -60,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)