use serde_bytes;
use serde_derive::Deserialize;
use crate ::{
de::from_str,
error::{Error, Position, SpannedError, SpannedResult},
parse::{AnyNum, Bytes},
};
#[ derive(Debug, PartialEq, Deserialize)]
struct EmptyStruct1;
#[ derive(Debug, PartialEq, Deserialize)]
struct EmptyStruct2 {}
#[ derive(Clone, Copy, Debug, PartialEq, Deserialize)]
struct MyStruct {
x: f32,
y: f32,
}
#[ derive(Clone, Copy, Debug, PartialEq, Deserialize)]
enum MyEnum {
A,
B(bool),
C(bool, f32),
D { a: i32, b: i32 },
}
#[ derive(Debug, Deserialize, PartialEq)]
struct BytesStruct {
small: Vec<u8>,
#[ serde(with = "serde_bytes" )]
large: Vec<u8>,
}
#[ test]
fn test_empty_struct() {
assert_eq!(Ok(EmptyStruct1), from_str("EmptyStruct1" ));
assert_eq!(Ok(EmptyStruct2 {}), from_str("EmptyStruct2()" ));
}
#[ test]
fn test_struct() {
let my_struct = MyStruct { x: 4 .0 , y: 7 .0 };
assert_eq!(Ok(my_struct), from_str("MyStruct(x:4,y:7,)" ));
assert_eq!(Ok(my_struct), from_str("(x:4,y:7)" ));
#[ derive(Debug, PartialEq, Deserialize)]
struct NewType(i32);
assert_eq!(Ok(NewType(42 )), from_str("NewType(42)" ));
assert_eq!(Ok(NewType(33 )), from_str("(33)" ));
#[ derive(Debug, PartialEq, Deserialize)]
struct TupleStruct(f32, f32);
assert_eq!(Ok(TupleStruct(2 .0 , 5 .0 )), from_str("TupleStruct(2,5,)" ));
assert_eq!(Ok(TupleStruct(3 .0 , 4 .0 )), from_str("(3,4)" ));
}
#[ test]
fn test_option() {
assert_eq!(Ok(Some(1 u8)), from_str("Some(1)" ));
assert_eq!(Ok(None::<u8>), from_str("None" ));
}
#[ test]
fn test_enum() {
assert_eq!(Ok(MyEnum::A), from_str("A" ));
assert_eq!(Ok(MyEnum::B(true )), from_str("B(true,)" ));
assert_eq!(Ok(MyEnum::C(true , 3 .5 )), from_str("C(true,3.5,)" ));
assert_eq!(Ok(MyEnum::D { a: 2 , b: 3 }), from_str("D(a:2,b:3,)" ));
}
#[ test]
fn test_array() {
let empty: [i32; 0 ] = [];
assert_eq!(Ok(empty), from_str("()" ));
let empty_array = empty.to_vec();
assert_eq!(Ok(empty_array), from_str("[]" ));
assert_eq!(Ok([2 , 3 , 4 i32]), from_str("(2,3,4,)" ));
assert_eq!(Ok([2 , 3 , 4 i32].to_vec()), from_str("[2,3,4,]" ));
}
#[ test]
fn test_map() {
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert((true , false ), 4 );
map.insert((false , false ), 123 );
assert_eq!(
Ok(map),
from_str(
"{
(true ,false ,):4 ,
(false ,false ,):123 ,
}"
)
);
}
#[ test]
fn test_string() {
let s: String = from_str("\" String\"" ).unwrap();
assert_eq!("String" , s);
let raw: String = from_str("r\" String\"" ).unwrap();
assert_eq!("String" , raw);
let raw_hashes: String = from_str("r#\" String\"#" ).unwrap();
assert_eq!("String" , raw_hashes);
let raw_hashes_multiline: String = from_str("r#\" String with\nmultiple\nlines\n\"#" ).unwrap();
assert_eq!("String with\nmultiple\nlines\n" , raw_hashes_multiline);
let raw_hashes_quote: String = from_str("r##\" String with \"#\" ## ").unwrap();
assert_eq!("String with \" #" , raw_hashes_quote);
}
#[ test]
fn test_char() {
assert_eq!(Ok('c' ), from_str("'c'" ));
}
#[ test]
fn test_escape_char() {
assert_eq!('\' ', from_str::<char>("' \\'' ").unwrap());
}
#[ test]
fn test_escape() {
assert_eq!("\" Quoted\"" , from_str::<String>(r#" "\" Quoted\"" "#).unwrap());
}
#[ test]
fn test_comment() {
assert_eq!(
MyStruct { x: 1 .0 , y: 2 .0 },
from_str(
"(
x: 1 .0 , // x is just 1
// There is another comment in the very next line..
// And y is indeed
y: 2 .0 // 2!
)"
)
.unwrap()
);
}
fn err<T>(kind: Error, line: usize, col: usize) -> SpannedResult<T> {
Err(SpannedError {
code: kind,
position: Position { line, col },
})
}
#[ test]
fn test_err_wrong_value() {
use std::collections::HashMap;
use self ::Error::*;
assert_eq!(from_str::<f32>("'c'" ), err(ExpectedFloat, 1 , 1 ));
assert_eq!(from_str::<String>("'c'" ), err(ExpectedString, 1 , 1 ));
assert_eq!(from_str::<HashMap<u32, u32>>("'c'" ), err(ExpectedMap, 1 , 1 ));
assert_eq!(from_str::<[u8; 5 ]>("'c'" ), err(ExpectedStructLike, 1 , 1 ));
assert_eq!(from_str::<Vec<u32>>("'c'" ), err(ExpectedArray, 1 , 1 ));
assert_eq!(from_str::<MyEnum>("'c'" ), err(ExpectedIdentifier, 1 , 1 ));
assert_eq!(
from_str::<MyStruct>("'c'" ),
err(ExpectedNamedStructLike("MyStruct" ), 1 , 1 )
);
assert_eq!(
from_str::<MyStruct>("NotMyStruct(x: 4, y: 2)" ),
err(
ExpectedDifferentStructName {
expected: "MyStruct" ,
found: String::from("NotMyStruct" )
},
1 ,
12
)
);
assert_eq!(from_str::<(u8, bool)>("'c'" ), err(ExpectedStructLike, 1 , 1 ));
assert_eq!(from_str::<bool>("notabool" ), err(ExpectedBoolean, 1 , 1 ));
assert_eq!(
from_str::<MyStruct>("MyStruct(\n x: true)" ),
err(ExpectedFloat, 2 , 8 )
);
assert_eq!(
from_str::<MyStruct>("MyStruct(\n x: 3.5, \n y:)" ),
err(ExpectedFloat, 3 , 7 )
);
}
#[ test]
fn test_perm_ws() {
assert_eq!(
from_str::<MyStruct>("\nMyStruct \t ( \n x : 3.5 , \t y\n: 4.5 \n ) \t\n" ),
Ok(MyStruct { x: 3 .5 , y: 4 .5 })
);
}
#[ test]
fn untagged() {
#[ derive(Deserialize, Debug, PartialEq)]
#[ serde(untagged)]
enum Untagged {
U8(u8),
Bool(bool),
}
assert_eq!(from_str::<Untagged>("true" ).unwrap(), Untagged::Bool(true ));
assert_eq!(from_str::<Untagged>("8" ).unwrap(), Untagged::U8(8 ));
}
#[ test]
fn rename() {
#[ derive(Deserialize, Debug, PartialEq)]
enum Foo {
#[ serde(rename = "2d" )]
D2,
#[ serde(rename = "triangle-list" )]
TriangleList,
}
assert_eq!(from_str::<Foo>("r#2d" ).unwrap(), Foo::D2);
assert_eq!(
from_str::<Foo>("r#triangle-list" ).unwrap(),
Foo::TriangleList
);
}
#[ test]
fn forgot_apostrophes() {
let de: SpannedResult<(i32, String)> = from_str("(4, \" Hello)");
assert!(matches!(
de,
Err(SpannedError {
code: Error::ExpectedStringEnd,
position: _,
})
));
}
#[ test]
fn expected_attribute() {
let de: SpannedResult<String> = from_str("#\" Hello\"" );
assert_eq!(de, err(Error::ExpectedAttribute, 1 , 2 ));
}
#[ test]
fn expected_attribute_end() {
let de: SpannedResult<String> = from_str("#![enable(unwrap_newtypes) \" Hello\"" );
assert_eq!(de, err(Error::ExpectedAttributeEnd, 1 , 28 ));
}
#[ test]
fn invalid_attribute() {
let de: SpannedResult<String> = from_str("#![enable(invalid)] \" Hello\"" );
assert_eq!(
de,
err(Error::NoSuchExtension("invalid" .to_string()), 1 , 18 )
);
}
#[ test]
fn multiple_attributes() {
#[ derive(Debug, Deserialize, PartialEq)]
struct New(String);
let de: SpannedResult<New> =
from_str("#![enable(unwrap_newtypes)] #![enable(unwrap_newtypes)] \" Hello\"" );
assert_eq!(de, Ok(New("Hello" .to_owned())));
}
#[ test]
fn uglified_attribute() {
let de: SpannedResult<()> = from_str(
"# !\
// We definitely want to add a comment here
[\t\tenable( // best style ever
unwrap_newtypes ) ] ()",
);
assert_eq!(de, Ok(()));
}
#[ test]
fn implicit_some() {
use serde::de::DeserializeOwned;
fn de<T: DeserializeOwned>(s: &str) -> Option<T> {
let enable = "#![enable(implicit_some)]\n" .to_string();
from_str::<Option<T>>(&(enable + s)).unwrap()
}
assert_eq!(de("'c'" ), Some('c' ));
assert_eq!(de("5" ), Some(5 ));
assert_eq!(de("\" Hello\"" ), Some("Hello" .to_owned()));
assert_eq!(de("false" ), Some(false ));
assert_eq!(
de("MyStruct(x: .4, y: .5)" ),
Some(MyStruct { x: 0 .4 , y: 0 .5 })
);
assert_eq!(de::<char>("None" ), None);
// Not concise
assert_eq!(de::<Option<Option<char>>>("None" ), None);
}
#[ test]
fn ws_tuple_newtype_variant() {
assert_eq!(Ok(MyEnum::B(true )), from_str("B ( \n true \n ) " ));
}
#[ test]
fn test_byte_stream() {
assert_eq!(
Ok(BytesStruct {
small: vec![1 , 2 ],
large: vec![1 , 2 , 3 , 4 ]
}),
from_str("BytesStruct( small:[1, 2], large:\" AQIDBA==\" )" ),
);
}
#[ test]
fn test_numbers() {
assert_eq!(
Ok(vec![1234 , 12345 , 123456 , 1234567 , 555 _555 ]),
from_str("[1_234, 12_345, 1_2_3_4_5_6, 1_234_567, 5_55_55_5]" ),
);
}
fn de_any_number(s: &str) -> AnyNum {
let mut bytes = Bytes::new(s.as_bytes()).unwrap();
bytes.any_num().unwrap()
}
#[ test]
fn test_any_number_precision() {
assert_eq!(de_any_number("1" ), AnyNum::U8(1 ));
assert_eq!(de_any_number("+1" ), AnyNum::I8(1 ));
assert_eq!(de_any_number("-1" ), AnyNum::I8(-1 ));
assert_eq!(de_any_number("-1.0" ), AnyNum::F32(-1 .0 ));
assert_eq!(de_any_number("1." ), AnyNum::F32(1 .));
assert_eq!(de_any_number("-1." ), AnyNum::F32(-1 .));
assert_eq!(de_any_number("0.3" ), AnyNum::F64(0 .3 ));
}
Messung V0.5 in Prozent C=83 H=93 G=87
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-18)
¤
*© Formatika GbR, Deutschland