Skip to content

Commit

Permalink
Merge pull request #3 from baoyachi/hashset
Browse files Browse the repository at this point in the history
Supports multiple std::collections types
  • Loading branch information
baoyachi authored Jul 23, 2023
2 parents 6b1b027 + c3fdc22 commit 1d22b23
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "serde_trim"
version = "0.4.0"
authors = ["baoyachi <[email protected]>"]
edition = "2021"
description = "serde deserialize_with String trim"
description = "serde deserialize_with String trim.Supports multiple std::collections types"
keywords = ["serde", "serde_trim", "deserialize_trim", "deserialize_with", "serde_json"]
readme = "README.md"
categories = ["encoding"]
Expand Down
69 changes: 68 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,24 @@

## Support trim
* `String`
* `Option<String>`
* `Vec<String>`
* `BTreeSet<String>`
* `Option<String>`
* `HashSet<String>`
* `VecDeque<String>`
* `LinkedList<String>`
* `BinaryHeap<String>`

Supports multiple [std::collections](https://doc.rust-lang.org/stable/std/collections/) types



## how to use
```rust
use serde_derive::Deserialize;
use serde_trim::*;
use std::collections::*;

fn main() {
#[derive(Deserialize)]
struct Foo {
Expand Down Expand Up @@ -72,5 +83,61 @@ fn main() {
"rust".into(),
]);
assert_eq!(foo.name, expected);

#[derive(Deserialize)]
struct HashSetFoo {
#[serde(deserialize_with = "hashset_string_trim")]
name: HashSet<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<HashSetFoo>(json).unwrap();
let expected: HashSet<String> = HashSet::from_iter([
"".into(),
"foo".into(),
"b ar".into(),
"hello".into(),
"rust".into(),
]);
assert_eq!(foo.name, expected);

#[derive(Deserialize)]
struct VecDequeFoo {
#[serde(deserialize_with = "vecdeque_string_trim")]
name: VecDeque<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<VecDequeFoo>(json).unwrap();
assert_eq!(foo.name, vec!["", "foo", "b ar", "hello", "rust"]);

#[derive(Deserialize)]
struct LinkedListFoo {
#[serde(deserialize_with = "linkedlist_string_trim")]
name: LinkedList<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<LinkedListFoo>(json).unwrap();
assert_eq!(
foo.name,
LinkedList::from_iter([
"".into(),
"foo".into(),
"b ar".into(),
"hello".into(),
"rust".into(),
])
);

#[derive(Deserialize)]
struct BinaryHeapFoo {
#[serde(deserialize_with = "binaryheap_string_trim")]
name: BinaryHeap<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<BinaryHeapFoo>(json).unwrap();
assert_eq!(
foo.name.into_vec(),
vec!["rust", "hello", "b ar", "", "foo"]
);
}

```
221 changes: 151 additions & 70 deletions lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::BTreeSet;
use std::collections::*;

use serde::{de, Deserialize};
pub use trim_in_place::*;
Expand All @@ -12,17 +12,6 @@ where
Ok(de_string)
}

pub fn vec_string_trim<'de, D>(d: D) -> Result<Vec<String>, D::Error>
where
D: de::Deserializer<'de>,
{
let de_string: Vec<String> = Vec::<String>::deserialize(d)?
.into_iter()
.map(|mut x| x.trim_in_place().to_string())
.collect();
Ok(de_string)
}

pub fn option_string_trim<'de, D>(d: D) -> Result<Option<String>, D::Error>
where
D: de::Deserializer<'de>,
Expand All @@ -36,79 +25,171 @@ where
Ok(de_string)
}

pub fn btreeset_string_trim<'de, D>(d: D) -> Result<BTreeSet<String>, D::Error>
macro_rules! iter_trim {
($fn_name:ident,$t:ty) => {
pub fn $fn_name<'de, D>(d: D) -> Result<$t, D::Error>
where
D: de::Deserializer<'de>,
{
collection_trim(d)
}
};
}

iter_trim!(btreeset_string_trim, BTreeSet<String>);
iter_trim!(vec_string_trim, Vec<String>);
iter_trim!(hashset_string_trim, HashSet<String>);
iter_trim!(vecdeque_string_trim, VecDeque<String>);
iter_trim!(linkedlist_string_trim, LinkedList<String>);
iter_trim!(binaryheap_string_trim, BinaryHeap<String>);

fn collection_trim<'de, C, D, S>(d: D) -> Result<C, D::Error>
where
S: TrimInPlace,
C: Deserialize<'de> + IntoIterator<Item = S> + FromIterator<String>,
D: de::Deserializer<'de>,
{
let de_string: BTreeSet<String> = BTreeSet::<String>::deserialize(d)?
let de_string: C = C::deserialize(d)?
.into_iter()
.map(|mut x| x.trim_in_place().to_string())
.collect();
Ok(de_string)
}

#[test]
fn test_vec_string_trim() {
#[derive(Deserialize)]
struct VecFoo {
#[serde(deserialize_with = "vec_string_trim")]
name: Vec<String>,
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_string_trim() {
#[derive(Deserialize)]
struct Foo {
#[serde(deserialize_with = "string_trim")]
name: String,
}
let json = r#"{"name":" "}"#;
let foo = serde_json::from_str::<Foo>(json).unwrap();
assert_eq!(foo.name, "");
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<VecFoo>(json).unwrap();
assert_eq!(foo.name, vec!["", "foo", "b ar", "hello", "rust"]);
}

#[test]
fn test_string_trim() {
#[derive(Deserialize)]
struct Foo {
#[serde(deserialize_with = "string_trim")]
name: String,
#[test]
fn test_option_string_trim() {
#[derive(Deserialize)]
struct OptionFoo {
#[serde(deserialize_with = "option_string_trim")]
name: Option<String>,
}
let json = r#"{"name":" "}"#;
let foo = serde_json::from_str::<OptionFoo>(json).unwrap();
assert_eq!(foo.name, None);

#[derive(Deserialize)]
struct OptionBar {
#[serde(default, deserialize_with = "option_string_trim")]
name: Option<String>,
addr: String,
}
let json = r#"{"addr":"ABC"}"#;
let foo = serde_json::from_str::<OptionBar>(json).unwrap();
assert_eq!(foo.name, None);
assert_eq!(foo.addr, "ABC");
}
let json = r#"{"name":" "}"#;
let foo = serde_json::from_str::<Foo>(json).unwrap();
assert_eq!(foo.name, "");
}

#[test]
fn test_option_string_trim() {
#[derive(Deserialize)]
struct OptionFoo {
#[serde(deserialize_with = "option_string_trim")]
name: Option<String>,
#[test]
fn test_vec_string_trim() {
#[derive(Deserialize)]
struct VecFoo {
#[serde(deserialize_with = "vec_string_trim")]
name: Vec<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<VecFoo>(json).unwrap();
assert_eq!(foo.name, vec!["", "foo", "b ar", "hello", "rust"]);
}
let json = r#"{"name":" "}"#;
let foo = serde_json::from_str::<OptionFoo>(json).unwrap();
assert_eq!(foo.name, None);

#[derive(Deserialize)]
struct OptionBar {
#[serde(default, deserialize_with = "option_string_trim")]
name: Option<String>,
addr: String,

#[test]
fn test_btreeset_string_trim() {
#[derive(Deserialize)]
struct BTreeSetFoo {
#[serde(deserialize_with = "btreeset_string_trim")]
name: BTreeSet<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<BTreeSetFoo>(json).unwrap();
let expected: BTreeSet<String> = BTreeSet::from_iter([
"".into(),
"foo".into(),
"b ar".into(),
"hello".into(),
"rust".into(),
]);
assert_eq!(foo.name, expected);
}
let json = r#"{"addr":"ABC"}"#;
let foo = serde_json::from_str::<OptionBar>(json).unwrap();
assert_eq!(foo.name, None);
assert_eq!(foo.addr, "ABC");
}

#[test]
fn test_btreeset_string_trim() {
#[derive(Deserialize)]
struct BTreeSetFoo {
#[serde(deserialize_with = "btreeset_string_trim")]
name: BTreeSet<String>,
#[test]
fn test_hashset_string_trim() {
#[derive(Deserialize)]
struct HashSetFoo {
#[serde(deserialize_with = "hashset_string_trim")]
name: HashSet<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"," rust"]}"#;
let foo = serde_json::from_str::<HashSetFoo>(json).unwrap();
let expected: HashSet<String> = HashSet::from_iter([
"".into(),
"foo".into(),
"b ar".into(),
"hello".into(),
"rust".into(),
]);
assert_eq!(foo.name, expected);
}

#[test]
fn test_vecdeque_string_trim() {
#[derive(Deserialize)]
struct VecDequeFoo {
#[serde(deserialize_with = "vecdeque_string_trim")]
name: VecDeque<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<VecDequeFoo>(json).unwrap();
assert_eq!(foo.name, vec!["", "foo", "b ar", "hello", "rust"]);
}

#[test]
fn test_linkedlist_string_trim() {
#[derive(Deserialize)]
struct LinkedListFoo {
#[serde(deserialize_with = "linkedlist_string_trim")]
name: LinkedList<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<LinkedListFoo>(json).unwrap();
assert_eq!(
foo.name,
LinkedList::from_iter([
"".into(),
"foo".into(),
"b ar".into(),
"hello".into(),
"rust".into(),
])
);
}

#[test]
fn test_binaryheap_string_trim() {
#[derive(Deserialize)]
struct BinaryHeapFoo {
#[serde(deserialize_with = "binaryheap_string_trim")]
name: BinaryHeap<String>,
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<BinaryHeapFoo>(json).unwrap();
assert_eq!(
foo.name.into_vec(),
vec!["rust", "hello", "b ar", "", "foo"]
);
}
let json = r#"{"name":[" ","foo","b ar","hello "," rust"]}"#;
let foo = serde_json::from_str::<BTreeSetFoo>(json).unwrap();
let expected: BTreeSet<String> = BTreeSet::from_iter([
"".into(),
"foo".into(),
"b ar".into(),
"hello".into(),
"rust".into(),
]);
assert_eq!(foo.name, expected);
}

0 comments on commit 1d22b23

Please sign in to comment.