#! [allow(
// clippy is broken and shows wrong warnings
// clippy on stable does not know yet about the lint name
unknown_lints,
// https://github.com/rust-lang/rust-clippy/issues/8867
clippy::derive_partial_eq_without_eq,
)]
extern crate alloc;
mod collections;
mod default_on;
mod enum_map;
mod frominto;
mod key_value_map;
mod map_tuple_list;
mod pickfirst;
mod serde_as_macro;
mod serde_conv;
mod time;
#[ path =
"../utils.rs" ]
mod utils;
use crate ::utils::*;
use alloc::{
collections::{BTreeMap, BTreeSet, LinkedList, VecDeque},
rc::{Rc, Weak
as RcWeak},
sync::{Arc, Weak
as ArcWeak},
};
use core::cell::{Cell, RefCell};
use expect_test::expect;
use serde::{Deserialize, Serialize};
use serde_with::{
formats::{CommaSeparator, Flexible, Strict},
serde_as, BoolFromInt, BytesOrString, DisplayFromStr, Map, NoneAsEmptyString, OneOrMan
y, Same,
Seq, StringWithSeparator,
};
use std::{
collections::HashMap,
sync::{Mutex, RwLock},
};
#[ test]
fn test_basic_wrappers() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SBox(#[ serde_as(as = "Box<DisplayFromStr>" )] Box <u32>);
is_equal(SBox(Box ::new(123 )), expect![[r#" "123" "#]]);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SRc(#[ serde_as(as = "Rc<DisplayFromStr>" )] Rc<u32>);
is_equal(SRc(Rc::new(123 )), expect![[r#" "123" "#]]);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize)]
struct SRcWeak(#[ serde_as(as = "RcWeak<DisplayFromStr>" )] RcWeak<u32>);
check_serialization(SRcWeak(RcWeak::new()), expect![[r#" null"#]]);
let s: SRcWeak = serde_json::from_str("null" ).unwrap();
assert!(s.0 .upgrade().is_none());
let s: SRcWeak = serde_json::from_str("\" 123 \"" ).unwrap();
assert!(s.0 .upgrade().is_none());
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SArc(#[ serde_as(as = "Arc<DisplayFromStr>" )] Arc<u32>);
is_equal(SArc(Arc::new(123 )), expect![[r#" "123" "#]]);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize)]
struct SArcWeak(#[ serde_as(as = "ArcWeak<DisplayFromStr>" )] ArcWeak<u32>);
check_serialization(SArcWeak(ArcWeak::new()), expect![[r#" null"#]]);
let s: SArcWeak = serde_json::from_str("null" ).unwrap();
assert!(s.0 .upgrade().is_none());
let s: SArcWeak = serde_json::from_str("\" 123 \"" ).unwrap();
assert!(s.0 .upgrade().is_none());
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SCell(#[ serde_as(as = "Cell<DisplayFromStr>" )] Cell<u32>);
is_equal(SCell(Cell::new(123 )), expect![[r#" "123" "#]]);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SRefCell(#[ serde_as(as = "RefCell<DisplayFromStr>" )] RefCell<u32>);
is_equal(SRefCell(RefCell::new(123 )), expect![[r#" "123" "#]]);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize)]
struct SMutex(#[ serde_as(as = "Mutex<DisplayFromStr>" )] Mutex<u32>);
check_serialization(SMutex(Mutex::new(123 )), expect![[r#" "123" "#]]);
let s: SMutex = serde_json::from_str("\" 123 \"" ).unwrap();
assert_eq!(*s.0 .lock().unwrap(), 123 );
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize)]
struct SRwLock(#[ serde_as(as = "RwLock<DisplayFromStr>" )] RwLock<u32>);
let expected = expect![[r#" "123" "#]];
check_serialization(SRwLock(RwLock::new(123 )), expected);
let s: SRwLock = serde_json::from_str("\" 123 \"" ).unwrap();
assert_eq!(*s.0 .read().unwrap(), 123 );
}
#[ test]
fn test_option() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S(#[ serde_as(as = "_" )] Option<u32>);
is_equal(S(None), expect![[r#" null"#]]);
is_equal(S(Some(9 )), expect![[r#" 9 "#]]);
check_error_deserialization::<S>(
r#" {}"#,
expect![[r#" invalid type : map, expected u32 at line 1 column 0 "#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct Struct {
#[ serde_as(as = "_" )]
value: Option<u32>,
}
check_error_deserialization::<Struct >(
r#" {}"#,
expect![[r#" missing field `value` at line 1 column 2 "#]],
);
}
#[ test]
fn test_result() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S(
#[ serde_as(as = "Result<StringWithSeparator<CommaSeparator, u32>, DisplayFromStr>" )]
Result<Vec<u32>, u32>,
);
is_equal(
S(Ok(vec![1 , 2 , 3 ])),
expect![[r#"
{
"Ok" : "1,2,3"
}"#]],
);
is_equal(
S(Err(9 )),
expect![[r#"
{
"Err" : "9"
}"#]],
);
check_error_deserialization::<S>(r#" {}"#, expect![[r#" expected value at line 1 column 2 "#]]);
}
#[ test]
fn test_display_fromstr() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S(#[ serde_as(as = "DisplayFromStr" )] u32);
is_equal(S(123 ), expect![[r#" "123" "#]]);
}
#[ test]
fn test_tuples() {
use std::net::IpAddr;
let ip = "1.2.3.4" .parse().unwrap();
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S1(#[ serde_as(as = "(DisplayFromStr,)" )] (u32,));
is_equal(
S1((1 ,)),
expect![[r#"
[
"1"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2a(#[ serde_as(as = "(DisplayFromStr, DisplayFromStr)" )] (u32, IpAddr));
is_equal(
S2a((555 _888 , ip)),
expect![[r#"
[
"555888" ,
"1.2.3.4"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2b(#[ serde_as(as = "(_, DisplayFromStr)" )] (u32, IpAddr));
is_equal(
S2b((987 , ip)),
expect![[r#"
[
987 ,
"1.2.3.4"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2c(#[ serde_as(as = "(Same, DisplayFromStr)" )] (u32, IpAddr));
is_equal(
S2c((987 , ip)),
expect![[r#"
[
987 ,
"1.2.3.4"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S6(
#[ serde_as(as = "(Same, Same, Same, Same, Same, Same)" )] (u8, u16, u32, i8, i16, i32),
);
is_equal(
S6((8 , 16 , 32 , -8 , 16 , -32 )),
expect![[r#"
[
8 ,
16 ,
32 ,
-8 ,
16 ,
-32
]"#]],
);
}
#[ test]
fn test_arrays() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S0(#[ serde_as(as = "[DisplayFromStr; 0]" )] [u32; 0 ]);
is_equal(S0([]), expect![[r#" []"#]]);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S1(#[ serde_as(as = "[DisplayFromStr; 1]" )] [u32; 1 ]);
is_equal(
S1([1 ]),
expect![[r#"
[
"1"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2(#[ serde_as(as = "[Same; 2]" )] [u32; 2 ]);
is_equal(
S2([11 , 22 ]),
expect![[r#"
[
11 ,
22
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S32(#[ serde_as(as = "[Same; 32]" )] [u32; 32 ]);
is_equal(
S32([
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 ,
24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 ,
]),
expect![[r#"
[
0 ,
1 ,
2 ,
3 ,
4 ,
5 ,
6 ,
7 ,
8 ,
9 ,
10 ,
11 ,
12 ,
13 ,
14 ,
15 ,
16 ,
17 ,
18 ,
19 ,
20 ,
21 ,
22 ,
23 ,
24 ,
25 ,
26 ,
27 ,
28 ,
29 ,
30 ,
31
]"#]],
);
}
#[ test]
fn test_sequence_like_types() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S1(#[ serde_as(as = "Box<[Same]>" )] Box <[u32]>);
is_equal(
S1(vec![1 , 2 , 3 , 99 ].into()),
expect![[r#"
[
1 ,
2 ,
3 ,
99
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2(#[ serde_as(as = "BTreeSet<Same>" )] BTreeSet<u32>);
is_equal(
S2(vec![1 , 2 , 3 , 99 ].into_iter().collect()),
expect![[r#"
[
1 ,
2 ,
3 ,
99
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S3(#[ serde_as(as = "LinkedList<Same>" )] LinkedList<u32>);
is_equal(
S3(vec![1 , 2 , 3 , 99 ].into_iter().collect()),
expect![[r#"
[
1 ,
2 ,
3 ,
99
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S4(#[ serde_as(as = "Vec<Same>" )] Vec<u32>);
is_equal(
S4(vec![1 , 2 , 3 , 99 ]),
expect![[r#"
[
1 ,
2 ,
3 ,
99
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S5(#[ serde_as(as = "VecDeque<Same>" )] VecDeque<u32>);
is_equal(
S5(vec![1 , 2 , 3 , 99 ].into()),
expect![[r#"
[
1 ,
2 ,
3 ,
99
]"#]],
);
}
#[ test]
fn test_none_as_empty_string() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S(#[ serde_as(as = "NoneAsEmptyString" )] Option<String>);
is_equal(S(None), expect![[r#" "" "#]]);
is_equal(S(Some("Hello" .to_string())), expect![[r#" "Hello" "#]]);
}
#[ test]
fn test_bytes_or_string() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S(#[ serde_as(as = "BytesOrString" )] Vec<u8>);
is_equal(
S(vec![1 , 2 , 3 ]),
expect![[r#"
[
1 ,
2 ,
3
]"#]],
);
check_deserialization(S(vec![72 , 101 , 108 , 108 , 111 ]), r#" "Hello" "#);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SVec(#[ serde_as(as = "Vec<BytesOrString>" )] Vec<Vec<u8>>);
is_equal(
SVec(vec![vec![1 , 2 , 3 ]]),
expect![[r#"
[
[
1 ,
2 ,
3
]
]"#]],
);
check_deserialization(
SVec(vec![
vec![72 , 101 , 108 , 108 , 111 ],
vec![87 , 111 , 114 , 108 , 100 ],
vec![1 , 2 , 3 ],
]),
r#" ["Hello" ,"World" ,[1 ,2 ,3 ]]"#,
);
}
#[ test]
fn string_with_separator() {
use serde_with::{
formats::{CommaSeparator, SpaceSeparator},
StringWithSeparator,
};
#[ serde_as]
#[ derive(Deserialize, Serialize)]
struct A {
#[ serde_as(as = "StringWithSeparator::<SpaceSeparator, String>" )]
tags: Vec<String>,
#[ serde_as(as = "StringWithSeparator::<CommaSeparator, String>" )]
// more_tags: Vec<String>,
more_tags: BTreeSet<String>,
}
let v: A = serde_json::from_str(
r## "{
"tags" : "#hello #world" ,
"more_tags" : "foo,bar,bar"
}"##,
)
.unwrap();
assert_eq!(vec!["#hello" , "#world" ], v.tags);
assert_eq!(2 , v.more_tags.len());
let x = A {
tags: vec!["1" .to_string(), "2" .to_string(), "3" .to_string()],
more_tags: Default::default(),
};
assert_eq!(
r#" {"tags" :"1 2 3" ,"more_tags" :"" }"#,
serde_json::to_string(&x).unwrap()
);
}
#[ test]
fn test_vec_skip_error() {
use serde_with::VecSkipError;
#[ serde_as]
#[ derive(Debug, PartialEq, Deserialize, Serialize)]
struct S {
tag: String,
#[ serde_as(as = "VecSkipError<_>" )]
values: Vec<u8>,
}
check_deserialization(
S {
tag: "type" .into(),
values: vec![0 , 1 ],
},
r#" {"tag" :"type" ,"values" :[0 , "str" , 1 , [10 , 11 ], -2 , {}, 300 ]}"#,
);
is_equal(
S {
tag: "round-trip" .into(),
values: vec![0 , 255 ],
},
expect![[r#"
{
"tag" : "round-trip" ,
"values" : [
0 ,
255
]
}"#]],
);
}
#[ test]
fn test_serialize_reference() {
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S1<'a>(#[serde_as(as = "Vec<DisplayFromStr>")] &' a Vec<u32>);
check_serialization(
S1(&vec![1 , 2 ]),
expect![[r#"
[
"1" ,
"2"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S1a<'a>(#[serde_as(as = "&Vec<DisplayFromStr>")] &' a Vec<u32>);
check_serialization(
S1(&vec![1 , 2 ]),
expect![[r#"
[
"1" ,
"2"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S1Mut<'a>(#[serde_as(as = "Vec<DisplayFromStr>")] &' a mut Vec<u32>);
check_serialization(
S1(&vec![1 , 2 ]),
expect![[r#"
[
"1" ,
"2"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S1aMut<'a>(#[serde_as(as = "&mut Vec<DisplayFromStr>")] &' a mut Vec<u32>);
check_serialization(
S1(&vec![1 , 2 ]),
expect![[r#"
[
"1" ,
"2"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S2<'a>(#[serde_as(as = "&[DisplayFromStr]")] &' a [u32]);
check_serialization(
S2(&[1 , 2 ]),
expect![[r#"
[
"1" ,
"2"
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S3<'a>(
#[ serde_as(as = "&BTreeMap<DisplayFromStr, DisplayFromStr>" )] &'a BTreeMap<bool, u32>,
);
let bmap = vec![(false , 123 ), (true , 456 )].into_iter().collect();
check_serialization(
S3(&bmap),
expect![[r#"
{
"false" : "123" ,
"true" : "456"
}"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S4<'a>(#[serde_as(as = "&Vec<(_, DisplayFromStr)>")] &' a BTreeMap<bool, u32>);
let bmap = vec![(false , 123 ), (true , 456 )].into_iter().collect();
check_serialization(
S4(&bmap),
expect![[r#"
[
[
false ,
"123"
],
[
true ,
"456"
]
]"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize)]
struct S5<'a>(
#[ serde_as(as = "&BTreeMap<DisplayFromStr, &Vec<(_, _)>>" )]
&'a Vec<(u32, &' a BTreeMap<bool, String>)>,
);
let bmap0 = vec![(false , "123" .to_string()), (true , "456" .to_string())]
.into_iter()
.collect();
let bmap1 = vec![(true , "Hello" .to_string()), (false , "World" .to_string())]
.into_iter()
.collect();
let vec = vec![(111 , &bmap0), (999 , &bmap1)];
check_serialization(
S5(&vec),
expect![[r#"
{
"111" : [
[
false ,
"123"
],
[
true ,
"456"
]
],
"999" : [
[
false ,
"World"
],
[
true ,
"Hello"
]
]
}"#]],
);
}
#[ test]
fn test_big_arrays() {
// Single Big Array
#[ serde_as]
#[ derive(Debug, PartialEq, Serialize, Deserialize)]
struct S1(#[ serde_as(as = "[_; 64]" )] [u8; 64 ]);
is_equal_compact(
S1([0 ; 64 ]),
expect![[
r#" [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ]"#
]],
);
// Too few entries
check_error_deserialization::<S1>(
r#" [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ]"#,
expect![[r#" invalid length 14 , expected an array of size 64 at line 1 column 29 "#]],
);
// Too many entries
check_error_deserialization::<S1>(
r#" [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ]"#,
expect![[r#" trailing characters at line 1 column 130 "#]],
);
// Single Big Array
#[ serde_as]
#[ derive(Debug, PartialEq, Serialize, Deserialize)]
struct S2(#[ serde_as(as = "[DisplayFromStr; 40]" )] [u8; 40 ]);
is_equal_compact(
S2([0 ; 40 ]),
expect![[
r#" ["0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" ]"#
]],
);
// Nested Big Arrays
#[ serde_as]
#[ derive(Debug, PartialEq, Serialize, Deserialize)]
struct S3(#[ serde_as(as = "[[_; 34]; 33]" )] [[u8; 34 ]; 33 ]);
is_equal_compact(
S3([[0 ; 34 ]; 33 ]),
expect![[
r#" [[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ],[0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ]]"#
]],
);
}
#[ test]
fn test_bytes() {
// The test case is copied from
// https://github.com/serde-rs/bytes/blob/cbae606b9dc225fc094b031cc84eac9493da2058/tests/test_derive.rs
// Original code by @dtolnay
use alloc::borrow::Cow;
use serde_test::{assert_de_tokens, assert_tokens, Token};
use serde_with::Bytes;
#[ serde_as]
#[ derive(Serialize, Deserialize, PartialEq, Debug)]
struct Test<'a> {
#[ serde_as(as = "Bytes" )]
array: [u8; 52 ],
#[ serde_as(as = "Bytes" )]
slice: &'a [u8],
#[ serde_as(as = "Bytes" )]
vec: Vec<u8>,
#[ serde_as(as = "Bytes" )]
cow_slice: Cow<'a, [u8]>,
#[ serde_as(as = "Box<Bytes>" )]
boxed_array: Box <[u8; 52 ]>,
#[ serde_as(as = "Bytes" )]
boxed_array2: Box <[u8; 52 ]>,
#[ serde_as(as = "Bytes" )]
boxed_slice: Box <[u8]>,
#[ serde_as(as = "Option<Bytes>" )]
opt_slice: Option<&'a [u8]>,
#[ serde_as(as = "Option<Bytes>" )]
opt_vec: Option<Vec<u8>>,
#[ serde_as(as = "Option<Bytes>" )]
opt_cow_slice: Option<Cow<'a, [u8]>>,
}
let test = Test {
array: *b"ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ,
slice: b"..." ,
vec: b"..." .to_vec(),
cow_slice: Cow::Borrowed(b"..." ),
boxed_array: Box ::new(*b"ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
boxed_array2: Box ::new(*b"ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
boxed_slice: b"..." .to_vec().into_boxed_slice(),
opt_slice: Some(b"..." ),
opt_vec: Some(b"..." .to_vec()),
opt_cow_slice: Some(Cow::Borrowed(b"..." )),
};
assert_tokens(
&test,
&[
Token::Struct {
name: "Test" ,
len: 10 ,
},
Token::Str("array" ),
Token::BorrowedBytes(b"ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
Token::Str("slice" ),
Token::BorrowedBytes(b"..." ),
Token::Str("vec" ),
Token::Bytes(b"..." ),
Token::Str("cow_slice" ),
Token::BorrowedBytes(b"..." ),
Token::Str("boxed_array" ),
Token::BorrowedBytes(b"ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
Token::Str("boxed_array2" ),
Token::BorrowedBytes(b"ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
Token::Str("boxed_slice" ),
Token::Bytes(b"..." ),
Token::Str("opt_slice" ),
Token::Some,
Token::BorrowedBytes(b"..." ),
Token::Str("opt_vec" ),
Token::Some,
Token::Bytes(b"..." ),
Token::Str("opt_cow_slice" ),
Token::Some,
Token::BorrowedBytes(b"..." ),
Token::StructEnd,
],
);
// Test string deserialization
assert_de_tokens(
&test,
&[
Token::Struct {
name: "Test" ,
len: 10 ,
},
Token::Str("array" ),
Token::BorrowedStr("ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
Token::Str("slice" ),
Token::BorrowedStr("..." ),
Token::Str("vec" ),
Token::Bytes(b"..." ),
Token::Str("cow_slice" ),
Token::BorrowedStr("..." ),
Token::Str("boxed_array" ),
Token::BorrowedStr("ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
Token::Str("boxed_array2" ),
Token::BorrowedStr("ABCDEFGHIJKLMNOPQRSTUVWXZYabcdefghijklmnopqrstuvwxyz" ),
Token::Str("boxed_slice" ),
Token::Bytes(b"..." ),
Token::Str("opt_slice" ),
Token::Some,
Token::BorrowedStr("..." ),
Token::Str("opt_vec" ),
Token::Some,
Token::Bytes(b"..." ),
Token::Str("opt_cow_slice" ),
Token::Some,
Token::BorrowedStr("..." ),
Token::StructEnd,
],
);
}
#[ test]
fn test_one_or_many_prefer_one() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S1Vec(#[ serde_as(as = "OneOrMany<_>" )] Vec<u32>);
// Normal
is_equal(S1Vec(vec![]), expect![[r#" []"#]]);
is_equal(S1Vec(vec![1 ]), expect![[r#" 1 "#]]);
is_equal(
S1Vec(vec![1 , 2 , 3 ]),
expect![[r#"
[
1 ,
2 ,
3
]"#]],
);
check_deserialization(S1Vec(vec![1 ]), r#" 1 "#);
check_deserialization(S1Vec(vec![1 ]), r#" [1 ]"#);
check_error_deserialization::<S1Vec>(
r#" {}"#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid type : map, expected u32
Many: invalid type : map, expected a sequence"#]],
);
check_error_deserialization::<S1Vec>(
r#" "xx" "#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid type : string "xx" , expected u32
Many: invalid type : string "xx" , expected a sequence"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2Vec(#[ serde_as(as = "OneOrMany<DisplayFromStr>" )] Vec<u32>);
// Normal
is_equal(S2Vec(vec![]), expect![[r#" []"#]]);
is_equal(S2Vec(vec![1 ]), expect![[r#" "1" "#]]);
is_equal(
S2Vec(vec![1 , 2 , 3 ]),
expect![[r#"
[
"1" ,
"2" ,
"3"
]"#]],
);
check_deserialization(S2Vec(vec![1 ]), r#" "1" "#);
check_deserialization(S2Vec(vec![1 ]), r#" ["1" ]"#);
check_error_deserialization::<S2Vec>(
r#" {}"#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid type : map, expected a string
Many: invalid type : map, expected a sequence"#]],
);
check_error_deserialization::<S2Vec>(
r#" "xx" "#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid digit found in string
Many: invalid type : string "xx" , expected a sequence"#]],
);
}
#[ test]
fn test_one_or_many_prefer_many() {
use serde_with::formats::PreferMany;
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S1Vec(#[ serde_as(as = "OneOrMany<_, PreferMany>" )] Vec<u32>);
// Normal
is_equal(S1Vec(vec![]), expect![[r#" []"#]]);
is_equal(
S1Vec(vec![1 ]),
expect![[r#"
[
1
]"#]],
);
is_equal(
S1Vec(vec![1 , 2 , 3 ]),
expect![[r#"
[
1 ,
2 ,
3
]"#]],
);
check_deserialization(S1Vec(vec![1 ]), r#" 1 "#);
check_deserialization(S1Vec(vec![1 ]), r#" [1 ]"#);
check_error_deserialization::<S1Vec>(
r#" {}"#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid type : map, expected u32
Many: invalid type : map, expected a sequence"#]],
);
check_error_deserialization::<S1Vec>(
r#" "xx" "#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid type : string "xx" , expected u32
Many: invalid type : string "xx" , expected a sequence"#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2Vec(#[ serde_as(as = "OneOrMany<DisplayFromStr, PreferMany>" )] Vec<u32>);
// Normal
is_equal(S2Vec(vec![]), expect![[r#" []"#]]);
is_equal(
S2Vec(vec![1 ]),
expect![[r#"
[
"1"
]"#]],
);
is_equal(
S2Vec(vec![1 , 2 , 3 ]),
expect![[r#"
[
"1" ,
"2" ,
"3"
]"#]],
);
check_deserialization(S2Vec(vec![1 ]), r#" "1" "#);
check_deserialization(S2Vec(vec![1 ]), r#" ["1" ]"#);
check_error_deserialization::<S2Vec>(
r#" {}"#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid type : map, expected a string
Many: invalid type : map, expected a sequence"#]],
);
check_error_deserialization::<S2Vec>(
r#" "xx" "#,
expect![[r#"
OneOrMany could not deserialize any variant:
One: invalid digit found in string
Many: invalid type : string "xx" , expected a sequence"#]],
);
}
/// Test that Cow borrows from the input
#[ test]
fn test_borrow_cow_str() {
use alloc::borrow::Cow;
use serde_test::{assert_ser_tokens, Token};
use serde_with::BorrowCow;
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S1<'a> {
#[ serde_as(as = "BorrowCow" )]
cow: Cow<'a, str>,
#[ serde_as(as = "Option<BorrowCow>" )]
opt: Option<Cow<'a, str>>,
#[ serde_as(as = "Box<BorrowCow>" )]
b: Box <Cow<'a, str>>,
#[ serde_as(as = "[BorrowCow; 1]" )]
arr: [Cow<'a, str>; 1],
}
assert_ser_tokens(
&S1 {
cow: "abc" .into(),
opt: Some("foo" .into()),
b: Box ::new("bar" .into()),
arr: ["def" .into()],
},
&[
Token::Struct { name: "S1" , len: 4 },
Token::Str("cow" ),
Token::BorrowedStr("abc" ),
Token::Str("opt" ),
Token::Some,
Token::BorrowedStr("foo" ),
Token::Str("b" ),
Token::BorrowedStr("bar" ),
Token::Str("arr" ),
Token::Tuple { len: 1 },
Token::BorrowedStr("def" ),
Token::TupleEnd,
Token::StructEnd,
],
);
let s1: S1<'_> = serde_json::from_str(
r#" {
"cow" : "abc" ,
"opt" : "foo" ,
"b" : "bar" ,
"arr" : ["def" ]
}"#,
)
.unwrap();
assert!(matches!(s1.cow, Cow::Borrowed(_)));
assert!(matches!(s1.opt, Some(Cow::Borrowed(_))));
assert!(matches!(*s1.b, Cow::Borrowed(_)));
assert!(matches!(s1.arr, [Cow::Borrowed(_)]));
let s1: S1<'_> = serde_json::from_str(
r#" {
"cow" : "a\" c",
"opt" : "f\" o",
"b" : "b\" r",
"arr" : ["d\" f"]
}"#,
)
.unwrap();
assert!(matches!(s1.cow, Cow::Owned(_)));
assert!(matches!(s1.opt, Some(Cow::Owned(_))));
assert!(matches!(*s1.b, Cow::Owned(_)));
assert!(matches!(s1.arr, [Cow::Owned(_)]));
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S2<'a> {
#[ serde_as(as = "BorrowCow" )]
cow: Cow<'a, [u8]>,
#[ serde_as(as = "Option<BorrowCow>" )]
opt: Option<Cow<'a, [u8]>>,
}
assert_ser_tokens(
&S2 {
cow: b"abc" [..].into(),
opt: Some(b"foo" [..].into()),
},
&[
Token::Struct { name: "S2" , len: 2 },
Token::Str("cow" ),
Token::Seq { len: Some(3 ) },
Token::U8(b'a' ),
Token::U8(b'b' ),
Token::U8(b'c' ),
Token::SeqEnd,
Token::Str("opt" ),
Token::Some,
Token::Seq { len: Some(3 ) },
Token::U8(b'f' ),
Token::U8(b'o' ),
Token::U8(b'o' ),
Token::SeqEnd,
Token::StructEnd,
],
);
let tokens = &[
Token::Struct { name: "S2" , len: 2 },
Token::Str("cow" ),
Token::BorrowedBytes(b"abc" ),
Token::Str("opt" ),
Token::Some,
Token::BorrowedBytes(b"foo" ),
Token::StructEnd,
];
let mut deser = serde_test::Deserializer::new(tokens);
let s2 = S2::deserialize(&mut deser).unwrap();
assert!(matches!(s2.cow, Cow::Borrowed(_)));
assert!(matches!(s2.opt, Some(Cow::Borrowed(_))));
// Check that a manual borrow works too
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S3<'a>(
#[ serde(borrow = "'a" )]
#[ serde_as(as = "BorrowCow" )]
Cow<'a, [u8]>,
// TODO add a test for Cow<'b, [u8; N]>
// #[serde_as(as = "BorrowCow")]
// Cow<'b, [u8; N]>,
);
let tokens = &[
Token::NewtypeStruct { name: "S3" },
Token::BorrowedBytes(b"abc" ),
];
let mut deser = serde_test::Deserializer::new(tokens);
let s3 = S3::deserialize(&mut deser).unwrap();
assert!(matches!(s3.0 , Cow::Borrowed(_)));
}
#[ test]
fn test_boolfromint() {
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct S(#[ serde_as(as = "BoolFromInt" )] bool);
is_equal(S(false ), expect![[r#" 0 "#]]);
is_equal(S(true ), expect![[r#" 1 "#]]);
check_error_deserialization::<S>(
"2" ,
expect![[r#" invalid value: integer `2 `, expected 0 or 1 at line 1 column 1 "#]],
);
check_error_deserialization::<S>(
"-100" ,
expect![[r#" invalid value: integer `-100 `, expected 0 or 1 at line 1 column 4 "#]],
);
check_error_deserialization::<S>(
"18446744073709551615" ,
expect![[
r#" invalid value: integer `18446744073709551615 `, expected 0 or 1 at line 1 column 20 "#
]],
);
check_error_deserialization::<S>(
r#" "" "#,
expect![[r#" invalid type : string "" , expected an integer 0 or 1 at line 1 column 2 "#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SStrict(#[ serde_as(as = "BoolFromInt<Strict>" )] bool);
is_equal(SStrict(false ), expect![[r#" 0 "#]]);
is_equal(SStrict(true ), expect![[r#" 1 "#]]);
check_error_deserialization::<SStrict>(
"2" ,
expect![[r#" invalid value: integer `2 `, expected 0 or 1 at line 1 column 1 "#]],
);
check_error_deserialization::<SStrict>(
"-100" ,
expect![[r#" invalid value: integer `-100 `, expected 0 or 1 at line 1 column 4 "#]],
);
check_error_deserialization::<SStrict>(
"18446744073709551615" ,
expect![[
r#" invalid value: integer `18446744073709551615 `, expected 0 or 1 at line 1 column 20 "#
]],
);
check_error_deserialization::<SStrict>(
r#" "" "#,
expect![[r#" invalid type : string "" , expected an integer 0 or 1 at line 1 column 2 "#]],
);
#[ serde_as]
#[ derive(Debug, Serialize, Deserialize, PartialEq)]
struct SFlexible(#[ serde_as(as = "BoolFromInt<Flexible>" )] bool);
is_equal(SFlexible(false ), expect![[r#" 0 "#]]);
is_equal(SFlexible(true ), expect![[r#" 1 "#]]);
check_deserialization::<SFlexible>(SFlexible(true ), "2" );
check_deserialization::<SFlexible>(SFlexible(true ), "-100" );
check_deserialization::<SFlexible>(SFlexible(true ), "18446744073709551615" );
check_error_deserialization::<SFlexible>(
r#" "" "#,
expect![[r#" invalid type : string "" , expected an integer at line 1 column 2 "#]],
);
}
Messung V0.5 in Prozent C=99 H=100 G=99
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-06-21)
¤
*© Formatika GbR, Deutschland