@@ -93,16 +93,22 @@ macro_rules! impl_serde_for_symbol {
9393 & self ,
9494 serializer: T ,
9595 ) -> :: core:: result:: Result <T :: Ok , T :: Error > {
96- self . value. serialize( serializer)
96+ // When the value is deserialized below, it will be converted back to a non-zero
97+ // type by adding 1 to the value, so we need to account for that here by subtracting
98+ // 1 from the value.
99+ let zeroable_value = self . value. get( ) - 1 ;
100+ zeroable_value. serialize( serializer)
97101 }
98102 }
99103
100104 impl <' de> :: serde:: Deserialize <' de> for $crate:: symbol:: $name {
101105 fn deserialize<D : :: serde:: Deserializer <' de>>(
102106 deserializer: D ,
103107 ) -> :: core:: result:: Result <Self , D :: Error > {
104- let index = <$ty as :: serde:: Deserialize <' de>>:: deserialize( deserializer) ?;
105- let :: core:: option:: Option :: Some ( symbol) = Self :: new( index) else {
108+ let zeroable_value = <$ty as :: serde:: Deserialize <' de>>:: deserialize( deserializer) ?;
109+ // Symbol::new() will add 1 to the value to guarantee that the resulting underlying
110+ // index will be non-zero.
111+ let :: core:: option:: Option :: Some ( symbol) = Self :: new( zeroable_value) else {
106112 return :: core:: result:: Result :: Err ( <D :: Error as :: serde:: de:: Error >:: custom(
107113 :: core:: concat!(
108114 "invalid index value for `" ,
@@ -119,3 +125,61 @@ macro_rules! impl_serde_for_symbol {
119125impl_serde_for_symbol ! ( SymbolU16 , u16 ) ;
120126impl_serde_for_symbol ! ( SymbolU32 , u32 ) ;
121127impl_serde_for_symbol ! ( SymbolUsize , usize ) ;
128+
129+ #[ cfg( test) ]
130+ mod tests {
131+ use crate :: {
132+ symbol:: { SymbolU16 , SymbolU32 , SymbolUsize } ,
133+ Symbol ,
134+ } ;
135+ use serde_json;
136+
137+ fn symbol_round_trip_serializes < S > ( symbol : S ) -> bool
138+ where
139+ S : Symbol + std:: fmt:: Debug + serde:: Serialize + serde:: de:: DeserializeOwned + PartialEq ,
140+ {
141+ let serialized = serde_json:: to_string ( & symbol) . expect ( "serialization should succeed" ) ;
142+ let deserialized: S =
143+ serde_json:: from_str ( & serialized) . expect ( "deserialization should succeed" ) ;
144+ symbol == deserialized
145+ }
146+
147+ #[ test]
148+ fn symbol_u16_round_trips ( ) {
149+ assert ! ( symbol_round_trip_serializes(
150+ SymbolU16 :: try_from_usize( 0 ) . unwrap( )
151+ ) ) ;
152+ assert ! ( symbol_round_trip_serializes(
153+ SymbolU16 :: try_from_usize( 42 ) . unwrap( )
154+ ) ) ;
155+ assert ! ( symbol_round_trip_serializes(
156+ SymbolU16 :: try_from_usize( u16 :: MAX as usize - 1 ) . unwrap( )
157+ ) ) ;
158+ }
159+
160+ #[ test]
161+ fn symbol_u32_round_trips ( ) {
162+ assert ! ( symbol_round_trip_serializes(
163+ SymbolU32 :: try_from_usize( 0 ) . unwrap( )
164+ ) ) ;
165+ assert ! ( symbol_round_trip_serializes(
166+ SymbolU32 :: try_from_usize( 42 ) . unwrap( )
167+ ) ) ;
168+ assert ! ( symbol_round_trip_serializes(
169+ SymbolU32 :: try_from_usize( u32 :: MAX as usize - 1 ) . unwrap( )
170+ ) ) ;
171+ }
172+
173+ #[ test]
174+ fn symbol_usize_round_trips ( ) {
175+ assert ! ( symbol_round_trip_serializes(
176+ SymbolUsize :: try_from_usize( 0 ) . unwrap( )
177+ ) ) ;
178+ assert ! ( symbol_round_trip_serializes(
179+ SymbolUsize :: try_from_usize( 42 ) . unwrap( )
180+ ) ) ;
181+ assert ! ( symbol_round_trip_serializes(
182+ SymbolUsize :: try_from_usize( usize :: MAX as usize - 1 ) . unwrap( )
183+ ) ) ;
184+ }
185+ }
0 commit comments