@@ -244,11 +244,7 @@ macro_rules! deserialize_unsigned {
244244
245245 match peek {
246246 b'-' => Err ( Error :: InvalidNumber ) ,
247- b'0' => {
248- $self. eat_char( ) ;
249- $visitor. $visit_uxx( 0 )
250- }
251- b'1' ..=b'9' => {
247+ b'0' ..=b'9' => {
252248 $self. eat_char( ) ;
253249
254250 let mut number = ( peek - b'0' ) as $uxx;
@@ -285,11 +281,7 @@ macro_rules! deserialize_signed {
285281 } ;
286282
287283 match $self. peek( ) . ok_or( Error :: EofWhileParsingValue ) ? {
288- b'0' => {
289- $self. eat_char( ) ;
290- $visitor. $visit_ixx( 0 )
291- }
292- c @ b'1' ..=b'9' => {
284+ c @ b'0' ..=b'9' => {
293285 $self. eat_char( ) ;
294286
295287 let mut number = ( c - b'0' ) as $ixx * if signed { -1 } else { 1 } ;
@@ -317,19 +309,19 @@ macro_rules! deserialize_fromstr {
317309 let start = $self. index;
318310 loop {
319311 match $self. peek( ) {
320- Some ( c) => {
321- if $pattern. iter( ) . find( |&&d| d == c) . is_some( ) {
322- $self. eat_char( ) ;
323- } else {
324- let s = unsafe {
325- // already checked that it contains only ascii
326- str :: from_utf8_unchecked( & $self. slice[ start..$self. index] )
327- } ;
328- let v = $typ:: from_str( s) . or( Err ( Error :: InvalidNumber ) ) ?;
329- return $visitor. $visit_fn( v) ;
330- }
312+ Some ( c) if $pattern. iter( ) . find( |&&d| d == c) . is_some( ) => {
313+ $self. eat_char( ) ;
314+ }
315+ Some ( _) | None => {
316+ // either found a character not in the pattern, or reached end of input
317+ // in both cases, parse the accumulated string
318+ let s = unsafe {
319+ // already checked that it contains only ascii
320+ str :: from_utf8_unchecked( & $self. slice[ start..$self. index] )
321+ } ;
322+ let v = $typ:: from_str( s) . or( Err ( Error :: InvalidNumber ) ) ?;
323+ return $visitor. $visit_fn( v) ;
331324 }
332- None => return Err ( Error :: EofWhileParsingNumber ) ,
333325 }
334326 }
335327 } } ;
@@ -1005,4 +997,251 @@ mod tests {
1005997 Bytes :: <32 >:: from_slice( b"{\" cmd\" : \" blink\" , \" pin\" : \" 2\" }" ) . unwrap( )
1006998 ) ;
1007999 }
1000+
1001+ #[ test]
1002+ fn f32_basic_numbers ( ) {
1003+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1004+ pub struct F32Test {
1005+ pub value : f32 ,
1006+ }
1007+
1008+ assert_eq ! ( crate :: from_str( "+TEST: 42" ) , Ok ( F32Test { value: 42.0 } ) ) ;
1009+
1010+ assert_eq ! ( crate :: from_str( "+TEST: -42" ) , Ok ( F32Test { value: -42.0 } ) ) ;
1011+
1012+ assert_eq ! ( crate :: from_str( "+TEST: 0" ) , Ok ( F32Test { value: 0.0 } ) ) ;
1013+
1014+ assert_eq ! ( crate :: from_str( "+TEST: 3.14" ) , Ok ( F32Test { value: 3.14 } ) ) ;
1015+
1016+ assert_eq ! (
1017+ crate :: from_str( "+TEST: -2.718" ) ,
1018+ Ok ( F32Test { value: -2.718 } )
1019+ ) ;
1020+ }
1021+
1022+ #[ test]
1023+ fn f32_scientific_notation ( ) {
1024+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1025+ pub struct F32Test {
1026+ pub value : f32 ,
1027+ }
1028+
1029+ assert_eq ! (
1030+ crate :: from_str( "+TEST: 1.23e4" ) ,
1031+ Ok ( F32Test { value: 1.23e4 } )
1032+ ) ;
1033+
1034+ assert_eq ! (
1035+ crate :: from_str( "+TEST: 1.23E4" ) ,
1036+ Ok ( F32Test { value: 1.23E4 } )
1037+ ) ;
1038+
1039+ assert_eq ! (
1040+ crate :: from_str( "+TEST: 1.23e-4" ) ,
1041+ Ok ( F32Test { value: 1.23e-4 } )
1042+ ) ;
1043+
1044+ assert_eq ! (
1045+ crate :: from_str( "+TEST: 1.23e+4" ) ,
1046+ Ok ( F32Test { value: 1.23e+4 } )
1047+ ) ;
1048+
1049+ assert_eq ! (
1050+ crate :: from_str( "+TEST: -1.23e4" ) ,
1051+ Ok ( F32Test { value: -1.23e4 } )
1052+ ) ;
1053+ }
1054+
1055+ #[ test]
1056+ fn f64_basic_numbers ( ) {
1057+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1058+ pub struct F64Test {
1059+ pub value : f64 ,
1060+ }
1061+
1062+ assert_eq ! ( crate :: from_str( "+TEST: 42" ) , Ok ( F64Test { value: 42.0 } ) ) ;
1063+
1064+ assert_eq ! ( crate :: from_str( "+TEST: -42" ) , Ok ( F64Test { value: -42.0 } ) ) ;
1065+
1066+ assert_eq ! ( crate :: from_str( "+TEST: 0" ) , Ok ( F64Test { value: 0.0 } ) ) ;
1067+
1068+ assert_eq ! (
1069+ crate :: from_str( "+TEST: 3.141592653589793" ) ,
1070+ Ok ( F64Test {
1071+ value: 3.141592653589793
1072+ } )
1073+ ) ;
1074+
1075+ assert_eq ! (
1076+ crate :: from_str( "+TEST: -2.718281828459045" ) ,
1077+ Ok ( F64Test {
1078+ value: -2.718281828459045
1079+ } )
1080+ ) ;
1081+ }
1082+
1083+ #[ test]
1084+ fn f64_scientific_notation ( ) {
1085+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1086+ pub struct F64Test {
1087+ pub value : f64 ,
1088+ }
1089+
1090+ assert_eq ! (
1091+ crate :: from_str( "+TEST: 1.23456789e15" ) ,
1092+ Ok ( F64Test {
1093+ value: 1.23456789e15
1094+ } )
1095+ ) ;
1096+
1097+ assert_eq ! (
1098+ crate :: from_str( "+TEST: 1.23456789E15" ) ,
1099+ Ok ( F64Test {
1100+ value: 1.23456789E15
1101+ } )
1102+ ) ;
1103+
1104+ assert_eq ! (
1105+ crate :: from_str( "+TEST: 1.23456789e-15" ) ,
1106+ Ok ( F64Test {
1107+ value: 1.23456789e-15
1108+ } )
1109+ ) ;
1110+
1111+ assert_eq ! (
1112+ crate :: from_str( "+TEST: 1.23456789e+15" ) ,
1113+ Ok ( F64Test {
1114+ value: 1.23456789e+15
1115+ } )
1116+ ) ;
1117+
1118+ assert_eq ! (
1119+ crate :: from_str( "+TEST: -1.23456789e15" ) ,
1120+ Ok ( F64Test {
1121+ value: -1.23456789e15
1122+ } )
1123+ ) ;
1124+ }
1125+
1126+ #[ test]
1127+ fn float_edge_cases ( ) {
1128+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1129+ pub struct F32Test {
1130+ pub value : f32 ,
1131+ }
1132+
1133+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1134+ pub struct F64Test {
1135+ pub value : f64 ,
1136+ }
1137+
1138+ assert_eq ! ( crate :: from_str( "+TEST: .5" ) , Ok ( F32Test { value: 0.5 } ) ) ;
1139+
1140+ assert_eq ! ( crate :: from_str( "+TEST: -.5" ) , Ok ( F32Test { value: -0.5 } ) ) ;
1141+
1142+ assert_eq ! ( crate :: from_str( "+TEST: 42." ) , Ok ( F32Test { value: 42.0 } ) ) ;
1143+
1144+ assert_eq ! (
1145+ crate :: from_str( "+TEST: 1e-10" ) ,
1146+ Ok ( F64Test { value: 1e-10 } )
1147+ ) ;
1148+
1149+ assert_eq ! ( crate :: from_str( "+TEST: 1e10" ) , Ok ( F64Test { value: 1e10 } ) ) ;
1150+ }
1151+
1152+ #[ test]
1153+ fn float_in_struct_with_multiple_fields ( ) {
1154+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1155+ pub struct MixedTest {
1156+ pub id : u8 ,
1157+ pub temperature : f32 ,
1158+ pub pressure : f64 ,
1159+ pub active : bool ,
1160+ }
1161+
1162+ assert_eq ! (
1163+ crate :: from_str( "+SENSOR: 1,23.5,-1.013e5,true" ) ,
1164+ Ok ( MixedTest {
1165+ id: 1 ,
1166+ temperature: 23.5 ,
1167+ pressure: -1.013e5 ,
1168+ active: true ,
1169+ } )
1170+ ) ;
1171+ }
1172+
1173+ #[ test]
1174+ fn float_with_whitespace ( ) {
1175+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1176+ pub struct F32Test {
1177+ pub value : f32 ,
1178+ }
1179+ assert_eq ! (
1180+ crate :: from_str( "+TEST: 3.14" ) ,
1181+ Ok ( F32Test { value: 3.14 } )
1182+ ) ;
1183+
1184+ assert_eq ! (
1185+ crate :: from_str( "+TEST: \t \n 2.718 " ) ,
1186+ Ok ( F32Test { value: 2.718 } )
1187+ ) ;
1188+ }
1189+
1190+ #[ test]
1191+ fn qgpsloc ( ) {
1192+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
1193+ pub struct GpsLocation {
1194+ pub utc : Option < f64 > ,
1195+ pub latitude : Option < f64 > ,
1196+ pub longitude : Option < f64 > ,
1197+ pub hdop : Option < f32 > ,
1198+ pub altitude : Option < f32 > ,
1199+ pub fix : Option < i16 > ,
1200+ pub course_over_ground : Option < f32 > ,
1201+ pub speed_km : Option < f32 > ,
1202+ pub speed_knots : Option < f32 > ,
1203+ pub date : Option < i32 > ,
1204+ pub nsat : Option < i8 > ,
1205+ }
1206+
1207+ let res = crate :: from_str (
1208+ "+QGPSLOC: 000040.000,30.28653,120.03266,1.2,84.1,3,0.00,0.0,0.0,240725,07" ,
1209+ ) ;
1210+
1211+ assert_eq ! (
1212+ res,
1213+ Ok ( GpsLocation {
1214+ utc: Some ( 40.0 ) ,
1215+ latitude: Some ( 30.28653 ) ,
1216+ longitude: Some ( 120.03266 ) ,
1217+ hdop: Some ( 1.2 ) ,
1218+ altitude: Some ( 84.1 ) ,
1219+ fix: Some ( 3 ) ,
1220+ course_over_ground: Some ( 0.0 ) ,
1221+ speed_km: Some ( 0.0 ) ,
1222+ speed_knots: Some ( 0.0 ) ,
1223+ date: Some ( 240725 ) ,
1224+ nsat: Some ( 7 ) ,
1225+ } )
1226+ ) ;
1227+
1228+ let res = crate :: from_str ( "+QGPSLOC: , , , , , , , , , ," ) ;
1229+
1230+ assert_eq ! (
1231+ res,
1232+ Ok ( GpsLocation {
1233+ utc: None ,
1234+ latitude: None ,
1235+ longitude: None ,
1236+ hdop: None ,
1237+ altitude: None ,
1238+ fix: None ,
1239+ course_over_ground: None ,
1240+ speed_km: None ,
1241+ speed_knots: None ,
1242+ date: None ,
1243+ nsat: None ,
1244+ } )
1245+ ) ;
1246+ }
10081247}
0 commit comments