@@ -41,7 +41,7 @@ pub enum Network {
4141 ICMPv6 ,
4242}
4343
44- #[ derive( Debug , Clone , Copy ) ]
44+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
4545pub enum StackPrefer {
4646 V4 ,
4747 V6 ,
@@ -54,3 +54,113 @@ impl StackPrefer {
5454 !matches ! ( self , StackPrefer :: V4 )
5555 }
5656}
57+
58+ impl Serialize for StackPrefer {
59+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
60+ where
61+ S : serde:: Serializer ,
62+ {
63+ let s = match self {
64+ StackPrefer :: V4 => "v4" ,
65+ StackPrefer :: V6 => "v6" ,
66+ StackPrefer :: V4V6 => "v4v6" ,
67+ StackPrefer :: V6V4 => "v6v4" ,
68+ } ;
69+ serializer. serialize_str ( s)
70+ }
71+ }
72+
73+ impl < ' de > Deserialize < ' de > for StackPrefer {
74+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
75+ where
76+ D : serde:: Deserializer < ' de > ,
77+ {
78+ let s = String :: deserialize ( deserializer) ?;
79+ match s. to_ascii_lowercase ( ) . as_str ( ) {
80+ "v4" | "v4only" | "only_v4" => Ok ( StackPrefer :: V4 ) ,
81+ "v6" | "v6only" | "only_v6" => Ok ( StackPrefer :: V6 ) ,
82+ "v4v6" | "v4_v6" | "v4first" | "prefer_v4" => Ok ( StackPrefer :: V4V6 ) ,
83+ "v6v4" | "v6_v4" | "v6first" | "prefer_v6" => Ok ( StackPrefer :: V6V4 ) ,
84+ _ => Err ( serde:: de:: Error :: custom ( format ! ( "invalid stack preference: '{s}'" ) ) ) ,
85+ }
86+ }
87+ }
88+
89+ #[ cfg( test) ]
90+ mod tests {
91+ use super :: * ;
92+
93+ #[ test]
94+ fn test_stack_prefer_serialize ( ) {
95+ assert_eq ! ( serde_json:: to_string( & StackPrefer :: V4 ) . unwrap( ) , r#""v4""# ) ;
96+ assert_eq ! ( serde_json:: to_string( & StackPrefer :: V6 ) . unwrap( ) , r#""v6""# ) ;
97+ assert_eq ! ( serde_json:: to_string( & StackPrefer :: V4V6 ) . unwrap( ) , r#""v4v6""# ) ;
98+ assert_eq ! ( serde_json:: to_string( & StackPrefer :: V6V4 ) . unwrap( ) , r#""v6v4""# ) ;
99+ }
100+
101+ #[ test]
102+ fn test_stack_prefer_deserialize_canonical ( ) {
103+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v4""# ) . unwrap( ) , StackPrefer :: V4 ) ;
104+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v6""# ) . unwrap( ) , StackPrefer :: V6 ) ;
105+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v4v6""# ) . unwrap( ) , StackPrefer :: V4V6 ) ;
106+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v6v4""# ) . unwrap( ) , StackPrefer :: V6V4 ) ;
107+ }
108+
109+ #[ test]
110+ fn test_stack_prefer_deserialize_aliases ( ) {
111+ // V4 aliases
112+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v4only""# ) . unwrap( ) , StackPrefer :: V4 ) ;
113+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""only_v4""# ) . unwrap( ) , StackPrefer :: V4 ) ;
114+
115+ // V6 aliases
116+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v6only""# ) . unwrap( ) , StackPrefer :: V6 ) ;
117+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""only_v6""# ) . unwrap( ) , StackPrefer :: V6 ) ;
118+
119+ // V4V6 aliases
120+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v4_v6""# ) . unwrap( ) , StackPrefer :: V4V6 ) ;
121+ assert_eq ! (
122+ serde_json:: from_str:: <StackPrefer >( r#""v4first""# ) . unwrap( ) ,
123+ StackPrefer :: V4V6
124+ ) ;
125+ assert_eq ! (
126+ serde_json:: from_str:: <StackPrefer >( r#""prefer_v4""# ) . unwrap( ) ,
127+ StackPrefer :: V4V6
128+ ) ;
129+
130+ // V6V4 aliases
131+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""v6_v4""# ) . unwrap( ) , StackPrefer :: V6V4 ) ;
132+ assert_eq ! (
133+ serde_json:: from_str:: <StackPrefer >( r#""v6first""# ) . unwrap( ) ,
134+ StackPrefer :: V6V4
135+ ) ;
136+ assert_eq ! (
137+ serde_json:: from_str:: <StackPrefer >( r#""prefer_v6""# ) . unwrap( ) ,
138+ StackPrefer :: V6V4
139+ ) ;
140+ }
141+
142+ #[ test]
143+ fn test_stack_prefer_deserialize_case_insensitive ( ) {
144+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""V4""# ) . unwrap( ) , StackPrefer :: V4 ) ;
145+ assert_eq ! ( serde_json:: from_str:: <StackPrefer >( r#""V4V6""# ) . unwrap( ) , StackPrefer :: V4V6 ) ;
146+ assert_eq ! (
147+ serde_json:: from_str:: <StackPrefer >( r#""V6First""# ) . unwrap( ) ,
148+ StackPrefer :: V6V4
149+ ) ;
150+ }
151+
152+ #[ test]
153+ fn test_stack_prefer_deserialize_invalid ( ) {
154+ assert ! ( serde_json:: from_str:: <StackPrefer >( r#""invalid""# ) . is_err( ) ) ;
155+ assert ! ( serde_json:: from_str:: <StackPrefer >( r#""v5""# ) . is_err( ) ) ;
156+ }
157+
158+ #[ test]
159+ fn test_stack_prefer_roundtrip ( ) {
160+ for variant in [ StackPrefer :: V4 , StackPrefer :: V6 , StackPrefer :: V4V6 , StackPrefer :: V6V4 ] {
161+ let serialized = serde_json:: to_string ( & variant) . unwrap ( ) ;
162+ let deserialized: StackPrefer = serde_json:: from_str ( & serialized) . unwrap ( ) ;
163+ assert_eq ! ( variant, deserialized) ;
164+ }
165+ }
166+ }
0 commit comments