@@ -23,6 +23,45 @@ pub(crate) struct SerializationState {
2323 config : SerializationConfig ,
2424}
2525
26+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
27+ pub enum DuckTypingSerMode {
28+ // Don't check the type of the value, use the type of the schema
29+ SchemaBased ,
30+ // Check the type of the value, use the type of the value
31+ NeedsInference ,
32+ // We already checked the type of the value
33+ // we don't want to infer again, but if we recurse down
34+ // we do want to flip this back to NeedsInference for the
35+ // fields / keys / items of any inner serializers
36+ Inferred ,
37+ }
38+
39+ impl DuckTypingSerMode {
40+ pub fn from_bool ( serialize_as_any : bool ) -> Self {
41+ if serialize_as_any {
42+ DuckTypingSerMode :: NeedsInference
43+ } else {
44+ DuckTypingSerMode :: SchemaBased
45+ }
46+ }
47+
48+ pub fn to_bool ( self ) -> bool {
49+ match self {
50+ DuckTypingSerMode :: SchemaBased => false ,
51+ DuckTypingSerMode :: NeedsInference => true ,
52+ DuckTypingSerMode :: Inferred => true ,
53+ }
54+ }
55+
56+ pub fn next_mode ( self ) -> Self {
57+ match self {
58+ DuckTypingSerMode :: SchemaBased => DuckTypingSerMode :: SchemaBased ,
59+ DuckTypingSerMode :: NeedsInference => DuckTypingSerMode :: Inferred ,
60+ DuckTypingSerMode :: Inferred => DuckTypingSerMode :: NeedsInference ,
61+ }
62+ }
63+ }
64+
2665impl SerializationState {
2766 pub fn new ( timedelta_mode : & str , bytes_mode : & str , inf_nan_mode : & str ) -> PyResult < Self > {
2867 let warnings = CollectWarnings :: new ( false ) ;
@@ -44,8 +83,9 @@ impl SerializationState {
4483 exclude_none : bool ,
4584 round_trip : bool ,
4685 serialize_unknown : bool ,
47- fallback : Option < & ' py Bound < ' py , PyAny > > ,
48- context : Option < & ' py Bound < ' py , PyAny > > ,
86+ fallback : Option < & ' py Bound < ' _ , PyAny > > ,
87+ duck_typing_ser_mode : DuckTypingSerMode ,
88+ context : Option < & ' py Bound < ' _ , PyAny > > ,
4989 ) -> Extra < ' py > {
5090 Extra :: new (
5191 py,
@@ -60,6 +100,7 @@ impl SerializationState {
60100 & self . rec_guard ,
61101 serialize_unknown,
62102 fallback,
103+ duck_typing_ser_mode,
63104 context,
64105 )
65106 }
@@ -92,6 +133,7 @@ pub(crate) struct Extra<'a> {
92133 pub field_name : Option < & ' a str > ,
93134 pub serialize_unknown : bool ,
94135 pub fallback : Option < & ' a Bound < ' a , PyAny > > ,
136+ pub duck_typing_ser_mode : DuckTypingSerMode ,
95137 pub context : Option < & ' a Bound < ' a , PyAny > > ,
96138}
97139
@@ -110,6 +152,7 @@ impl<'a> Extra<'a> {
110152 rec_guard : & ' a SerRecursionState ,
111153 serialize_unknown : bool ,
112154 fallback : Option < & ' a Bound < ' a , PyAny > > ,
155+ duck_typing_ser_mode : DuckTypingSerMode ,
113156 context : Option < & ' a Bound < ' a , PyAny > > ,
114157 ) -> Self {
115158 Self {
@@ -128,6 +171,7 @@ impl<'a> Extra<'a> {
128171 field_name : None ,
129172 serialize_unknown,
130173 fallback,
174+ duck_typing_ser_mode,
131175 context,
132176 }
133177 }
@@ -187,6 +231,7 @@ pub(crate) struct ExtraOwned {
187231 field_name : Option < String > ,
188232 serialize_unknown : bool ,
189233 pub fallback : Option < PyObject > ,
234+ duck_typing_ser_mode : DuckTypingSerMode ,
190235 pub context : Option < PyObject > ,
191236}
192237
@@ -206,8 +251,9 @@ impl ExtraOwned {
206251 model : extra. model . map ( |model| model. clone ( ) . into ( ) ) ,
207252 field_name : extra. field_name . map ( ToString :: to_string) ,
208253 serialize_unknown : extra. serialize_unknown ,
209- fallback : extra. fallback . map ( |fallback| fallback. clone ( ) . into ( ) ) ,
210- context : extra. context . map ( |context| context. clone ( ) . into ( ) ) ,
254+ fallback : extra. fallback . map ( |model| model. clone ( ) . into ( ) ) ,
255+ duck_typing_ser_mode : extra. duck_typing_ser_mode ,
256+ context : extra. context . map ( |model| model. clone ( ) . into ( ) ) ,
211257 }
212258 }
213259
@@ -228,6 +274,7 @@ impl ExtraOwned {
228274 field_name : self . field_name . as_deref ( ) ,
229275 serialize_unknown : self . serialize_unknown ,
230276 fallback : self . fallback . as_ref ( ) . map ( |m| m. bind ( py) ) ,
277+ duck_typing_ser_mode : self . duck_typing_ser_mode ,
231278 context : self . context . as_ref ( ) . map ( |m| m. bind ( py) ) ,
232279 }
233280 }
0 commit comments