serde_pyobject/
ser.rs

1use crate::error::{Error, Result};
2use pyo3::{prelude::*, types::*, IntoPyObjectExt};
3use serde::{ser, Serialize};
4
5/// Serialize `T: Serialize` into a [`pyo3::PyAny`] value.
6///
7/// # Examples
8///
9/// ## string
10///
11/// ```
12/// use pyo3::{Python, types::{PyString, PyAnyMethods}};
13/// use serde_pyobject::to_pyobject;
14///
15/// Python::with_gil(|py| {
16///     // char
17///     let obj = to_pyobject(py, &'a').unwrap();
18///     assert!(obj.is_exact_instance_of::<PyString>());
19///     // &str
20///     let obj = to_pyobject(py, "test").unwrap();
21///     assert!(obj.is_exact_instance_of::<PyString>());
22/// });
23/// ```
24///
25/// ## integer
26///
27/// ```
28/// use pyo3::{Python, types::{PyLong, PyAnyMethods}};
29/// use serde_pyobject::to_pyobject;
30///
31/// Python::with_gil(|py| {
32///     let obj = to_pyobject(py, &1_u16).unwrap();
33///     assert!(obj.is_exact_instance_of::<PyLong>());
34///
35///     let obj = to_pyobject(py, &1_i64).unwrap();
36///     assert!(obj.is_exact_instance_of::<PyLong>());
37///
38///     let obj = to_pyobject(py, &1_i64).unwrap();
39///     assert!(obj.is_exact_instance_of::<PyLong>());
40/// });
41/// ```
42///
43/// ## float
44///
45/// ```
46/// use pyo3::{Python, types::{PyFloat, PyAnyMethods}};
47/// use serde_pyobject::to_pyobject;
48///
49/// Python::with_gil(|py| {
50///     let obj = to_pyobject(py, &3.1_f32).unwrap();
51///     assert!(obj.is_exact_instance_of::<PyFloat>());
52///
53///     let obj = to_pyobject(py, &-3.1_f64).unwrap();
54///     assert!(obj.is_exact_instance_of::<PyFloat>());
55/// });
56/// ```
57///
58/// ## option
59///
60/// Rust `None` is serialized to Python `None`, and `Some(value)` is serialized as `value` is serialized
61///
62/// ```
63/// use pyo3::{Python, types::{PyLong, PyAnyMethods}};
64/// use serde_pyobject::to_pyobject;
65///
66/// Python::with_gil(|py| {
67///     let obj = to_pyobject(py, &Option::<i32>::None).unwrap();
68///     assert!(obj.is(&py.None()));
69///
70///     let obj = to_pyobject(py, &Some(1_i64)).unwrap();
71///     assert!(obj.is_exact_instance_of::<PyLong>());
72/// });
73/// ```
74///
75/// ## unit
76///
77/// Rust's `()` is serialized to Python's `()`
78///
79/// ```
80/// use pyo3::{Python, types::{PyTuple, PyAnyMethods}};
81/// use serde_pyobject::to_pyobject;
82///
83/// Python::with_gil(|py| {
84///     let obj = to_pyobject(py, &()).unwrap();
85///     assert!(obj.is(&PyTuple::empty_bound(py)));
86/// });
87/// ```
88///
89/// ## unit_struct
90///
91/// `Unit` is serialized as an empty tuple `()`
92///
93/// ```
94/// use serde::Serialize;
95/// use pyo3::{Python, types::{PyTuple, PyAnyMethods}};
96/// use serde_pyobject::{to_pyobject, pydict};
97///
98/// #[derive(Serialize)]
99/// struct UnitStruct;
100///
101/// Python::with_gil(|py| {
102///     let obj = to_pyobject(py, &UnitStruct {}).unwrap();
103///     assert!(obj.eq(PyTuple::empty_bound(py)).unwrap());
104/// });
105/// ```
106///
107/// ## unit_variant
108///
109/// ```
110/// use serde::Serialize;
111/// use pyo3::{Python, types::{PyTuple, PyAnyMethods}};
112/// use serde_pyobject::{to_pyobject, pydict};
113///
114/// #[derive(Serialize)]
115/// enum UnitVariant {
116///     A,
117///     B,
118/// }
119///
120/// Python::with_gil(|py| {
121///     let obj = to_pyobject(py, &UnitVariant::A).unwrap();
122///     assert!(obj.eq("A").unwrap());
123///     let obj = to_pyobject(py, &UnitVariant::B).unwrap();
124///     assert!(obj.eq("B").unwrap());
125/// });
126/// ```
127///
128/// ## newtype_struct
129///
130/// ```
131/// use serde::Serialize;
132/// use pyo3::{Python, types::{PyLong, PyAnyMethods}};
133/// use serde_pyobject::to_pyobject;
134///
135/// #[derive(Serialize)]
136/// struct NewtypeStruct(u8);
137///
138/// Python::with_gil(|py| {
139///     let obj = to_pyobject(py, &NewtypeStruct(10)).unwrap();
140///     assert!(obj.is_exact_instance_of::<PyLong>());
141///     assert!(obj.eq(10).unwrap());
142/// });
143/// ```
144///
145/// ## newtype_variant
146///
147/// ```
148/// use serde::Serialize;
149/// use pyo3::{Python, types::PyAnyMethods};
150/// use serde_pyobject::{to_pyobject, pydict};
151///
152/// #[derive(Serialize)]
153/// enum NewtypeVariant {
154///     N(u8),
155/// }
156///
157/// Python::with_gil(|py| {
158///     let obj = to_pyobject(py, &NewtypeVariant::N(3)).unwrap();
159///     assert!(obj.eq(pydict! { "N" => 3 }.unwrap()).unwrap());
160/// });
161/// ```
162///
163/// ## seq
164///
165/// ```
166/// use pyo3::{Python, types::PyAnyMethods};
167/// use serde_pyobject::{to_pyobject, pylist};
168///
169/// Python::with_gil(|py| {
170///     let obj = to_pyobject(py, &vec![1, 2, 3]).unwrap();
171///     assert!(obj.eq(pylist![py; 1, 2, 3].unwrap()).unwrap());
172/// });
173/// ```
174///
175/// ## tuple
176///
177/// ```
178/// use pyo3::{IntoPy, Python, types::{PyTuple, PyAnyMethods}};
179/// use serde_pyobject::to_pyobject;
180///
181/// Python::with_gil(|py| {
182///     let obj = to_pyobject(py, &(3, "test")).unwrap();
183///     assert!(obj.eq(PyTuple::new_bound(py, [3.into_py(py), "test".into_py(py)])).unwrap());
184/// });
185/// ```
186///
187/// ## tuple struct
188///
189/// ```
190/// use pyo3::{Python, types::{PyTuple, PyAnyMethods}};
191/// use serde::Serialize;
192/// use serde_pyobject::to_pyobject;
193///
194/// #[derive(Serialize)]
195/// struct TupleStruct(u8, u8, u8);
196///
197/// Python::with_gil(|py| {
198///     let obj = to_pyobject(py, &TupleStruct(1, 2, 3)).unwrap();
199///     assert!(obj.eq(PyTuple::new_bound(py, [1, 2, 3])).unwrap());
200/// });
201/// ```
202///
203/// ## tuple variant
204///
205/// ```
206/// use pyo3::{Python, types::PyAnyMethods};
207/// use serde::Serialize;
208/// use serde_pyobject::{to_pyobject, pydict};
209///
210/// #[derive(Serialize)]
211/// enum TupleVariant {
212///     T(u8, u8),
213/// }
214///
215/// Python::with_gil(|py| {
216///     let obj = to_pyobject(py, &TupleVariant::T(1, 2)).unwrap();
217///     assert!(obj.eq(pydict!{ "T" => (1, 2) }.unwrap()).unwrap());
218/// });
219/// ```
220///
221/// ## map
222///
223/// ```
224/// use pyo3::{Python, types::PyAnyMethods};
225/// use serde_pyobject::{to_pyobject, pydict};
226/// use maplit::hashmap;
227///
228/// Python::with_gil(|py| {
229///     let obj = to_pyobject(py, &hashmap! {
230///         "a".to_owned() => 1_u8,
231///         "b".to_owned() => 2,
232///         "c".to_owned() => 3
233///     }).unwrap();
234///     assert!(obj.eq(pydict! {
235///         "a" => 1,
236///         "b" => 2,
237///         "c" => 3
238///     }.unwrap()).unwrap());
239/// });
240/// ```
241///
242/// ## struct
243///
244/// ```
245/// use serde::Serialize;
246/// use pyo3::{IntoPy, Python, types::{PyTuple, PyAnyMethods}};
247/// use serde_pyobject::{to_pyobject, pydict};
248///
249/// #[derive(Serialize)]
250/// struct Struct {
251///     a: i32,
252///     b: String,
253/// }
254///
255/// Python::with_gil(|py| {
256///     let obj = to_pyobject(py, &Struct { a: 32, b: "test".to_string() }).unwrap();
257///     assert!(obj.eq(pydict!{ "a" => 32, "b" => "test" }.unwrap()).unwrap());
258/// });
259/// ```
260///
261/// ## struct variant
262///
263/// ```
264/// use serde::Serialize;
265/// use pyo3::{Python, types::PyAnyMethods};
266/// use serde_pyobject::{to_pyobject, pydict};
267///
268/// #[derive(Serialize)]
269/// enum StructVariant {
270///     S { r: u8, g: u8, b: u8 },
271/// }
272///
273/// Python::with_gil(|py| {
274///     let obj = to_pyobject(py, &StructVariant::S { r: 1, g: 2, b: 3 }).unwrap();
275///     assert!(
276///         obj.eq(
277///             pydict! {
278///                 "S" => pydict! {
279///                     "r" => 1,
280///                     "g" => 2,
281///                     "b" => 3
282///                 }.unwrap()
283///             }.unwrap()
284///         ).unwrap()
285///     );
286/// });
287/// ```
288pub fn to_pyobject<'py, T>(py: Python<'py>, value: &T) -> Result<Bound<'py, PyAny>>
289where
290    T: Serialize + ?Sized,
291{
292    let serializer = PyAnySerializer { py };
293    value.serialize(serializer)
294}
295
296pub struct PyAnySerializer<'py> {
297    py: Python<'py>,
298}
299
300macro_rules! serialize_impl {
301    ($f:ident, $t:ty) => {
302        fn $f(self, v: $t) -> Result<Self::Ok> {
303            Ok(v.into_bound_py_any(self.py)?)
304        }
305    };
306}
307
308impl<'py> ser::Serializer for PyAnySerializer<'py> {
309    type Ok = Bound<'py, PyAny>;
310
311    type Error = Error;
312
313    type SerializeSeq = Seq<'py>;
314    type SerializeTuple = Seq<'py>;
315    type SerializeTupleStruct = TupleStruct<'py>;
316    type SerializeTupleVariant = TupleVariant<'py>;
317    type SerializeMap = Map<'py>;
318    type SerializeStruct = Struct<'py>;
319    type SerializeStructVariant = StructVariant<'py>;
320
321    serialize_impl!(serialize_bool, bool);
322    serialize_impl!(serialize_i8, i8);
323    serialize_impl!(serialize_i16, i16);
324    serialize_impl!(serialize_i32, i32);
325    serialize_impl!(serialize_i64, i64);
326    serialize_impl!(serialize_u8, u8);
327    serialize_impl!(serialize_u16, u16);
328    serialize_impl!(serialize_u32, u32);
329    serialize_impl!(serialize_u64, u64);
330    serialize_impl!(serialize_f32, f32);
331    serialize_impl!(serialize_f64, f64);
332    serialize_impl!(serialize_char, char);
333    serialize_impl!(serialize_str, &str);
334    serialize_impl!(serialize_bytes, &[u8]);
335
336    fn serialize_none(self) -> Result<Self::Ok> {
337        Ok(self.py.None().into_bound(self.py))
338    }
339
340    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok>
341    where
342        T: ?Sized + Serialize,
343    {
344        value.serialize(self)
345    }
346
347    fn serialize_unit(self) -> Result<Self::Ok> {
348        Ok(PyTuple::empty(self.py).into_any())
349    }
350
351    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
352        Ok(PyTuple::empty(self.py).into_any())
353    }
354
355    fn serialize_unit_variant(
356        self,
357        _name: &'static str,
358        _index: u32,
359        variant: &'static str,
360    ) -> Result<Self::Ok> {
361        Ok(PyString::new(self.py, variant).into_any())
362    }
363
364    fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Self::Ok>
365    where
366        T: ?Sized + Serialize,
367    {
368        value.serialize(self)
369    }
370
371    fn serialize_newtype_variant<T>(
372        self,
373        _name: &'static str,
374        _variant_index: u32,
375        variant: &'static str,
376        value: &T,
377    ) -> Result<Self::Ok>
378    where
379        T: ?Sized + Serialize,
380    {
381        let dict = PyDict::new(self.py).into_any();
382        dict.set_item(variant, value.serialize(self)?)?;
383        Ok(dict)
384    }
385
386    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
387        Ok(Seq {
388            py: self.py,
389            seq: Vec::new(),
390        })
391    }
392
393    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
394        Ok(Seq {
395            py: self.py,
396            seq: Vec::new(),
397        })
398    }
399
400    fn serialize_tuple_struct(
401        self,
402        _name: &'static str,
403        _len: usize,
404    ) -> Result<Self::SerializeTupleStruct> {
405        Ok(TupleStruct {
406            py: self.py,
407            fields: Vec::new(),
408        })
409    }
410
411    fn serialize_tuple_variant(
412        self,
413        _name: &'static str,
414        _variant_index: u32,
415        variant: &'static str,
416        _len: usize,
417    ) -> Result<Self::SerializeTupleVariant> {
418        Ok(TupleVariant {
419            py: self.py,
420            variant,
421            fields: Vec::new(),
422        })
423    }
424
425    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
426        Ok(Map {
427            py: self.py,
428            map: PyDict::new(self.py),
429            key: None,
430        })
431    }
432
433    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
434        Ok(Struct {
435            py: self.py,
436            fields: PyDict::new(self.py),
437        })
438    }
439
440    fn serialize_struct_variant(
441        self,
442        _name: &'static str,
443        _variant_index: u32,
444        variant: &'static str,
445        _len: usize,
446    ) -> Result<Self::SerializeStructVariant> {
447        Ok(StructVariant {
448            py: self.py,
449            variant,
450            fields: PyDict::new(self.py),
451        })
452    }
453}
454
455pub struct Seq<'py> {
456    py: Python<'py>,
457    seq: Vec<Bound<'py, PyAny>>,
458}
459
460impl<'py> ser::SerializeSeq for Seq<'py> {
461    type Ok = Bound<'py, PyAny>;
462    type Error = Error;
463
464    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
465    where
466        T: ?Sized + Serialize,
467    {
468        self.seq
469            .push(value.serialize(PyAnySerializer { py: self.py })?);
470        Ok(())
471    }
472
473    fn end(self) -> Result<Self::Ok> {
474        Ok(PyList::new(self.py, self.seq)?.into_any())
475    }
476}
477
478impl<'py> ser::SerializeTuple for Seq<'py> {
479    type Ok = Bound<'py, PyAny>;
480    type Error = Error;
481
482    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
483    where
484        T: ?Sized + Serialize,
485    {
486        self.seq
487            .push(value.serialize(PyAnySerializer { py: self.py })?);
488        Ok(())
489    }
490
491    fn end(self) -> Result<Self::Ok> {
492        Ok(PyTuple::new(self.py, self.seq)?.into_any())
493    }
494}
495
496pub struct TupleStruct<'py> {
497    py: Python<'py>,
498    fields: Vec<Bound<'py, PyAny>>,
499}
500
501impl<'py> ser::SerializeTupleStruct for TupleStruct<'py> {
502    type Ok = Bound<'py, PyAny>;
503    type Error = Error;
504
505    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
506    where
507        T: ?Sized + Serialize,
508    {
509        self.fields
510            .push(value.serialize(PyAnySerializer { py: self.py })?);
511        Ok(())
512    }
513
514    fn end(self) -> Result<Self::Ok> {
515        Ok(PyTuple::new(self.py, self.fields)?.into_any())
516    }
517}
518
519pub struct TupleVariant<'py> {
520    py: Python<'py>,
521    variant: &'static str,
522    fields: Vec<Bound<'py, PyAny>>,
523}
524
525impl<'py> ser::SerializeTupleVariant for TupleVariant<'py> {
526    type Ok = Bound<'py, PyAny>;
527    type Error = Error;
528
529    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
530    where
531        T: ?Sized + Serialize,
532    {
533        self.fields
534            .push(value.serialize(PyAnySerializer { py: self.py })?);
535        Ok(())
536    }
537
538    fn end(self) -> Result<Self::Ok> {
539        let dict = PyDict::new(self.py);
540        dict.set_item(self.variant, PyTuple::new(self.py, self.fields)?)?;
541        Ok(dict.into_any())
542    }
543}
544
545pub struct Map<'py> {
546    py: Python<'py>,
547    map: Bound<'py, PyDict>,
548    key: Option<Bound<'py, PyAny>>,
549}
550
551impl<'py> ser::SerializeMap for Map<'py> {
552    type Ok = Bound<'py, PyAny>;
553    type Error = Error;
554
555    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
556    where
557        T: ?Sized + Serialize,
558    {
559        self.key = Some(key.serialize(PyAnySerializer { py: self.py })?);
560        Ok(())
561    }
562
563    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
564    where
565        T: ?Sized + Serialize,
566    {
567        let key = self
568            .key
569            .take()
570            .expect("Invalid Serialize implementation. Key is missing.");
571        self.map
572            .set_item(key, value.serialize(PyAnySerializer { py: self.py })?)?;
573        Ok(())
574    }
575
576    fn end(self) -> Result<Self::Ok> {
577        Ok(self.map.into_any())
578    }
579}
580
581pub struct Struct<'py> {
582    py: Python<'py>,
583    fields: Bound<'py, PyDict>,
584}
585
586impl<'py> ser::SerializeStruct for Struct<'py> {
587    type Ok = Bound<'py, PyAny>;
588    type Error = Error;
589
590    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
591    where
592        T: ?Sized + Serialize,
593    {
594        self.fields
595            .set_item(key, value.serialize(PyAnySerializer { py: self.py })?)?;
596        Ok(())
597    }
598
599    fn end(self) -> Result<Self::Ok> {
600        Ok(self.fields.into_any())
601    }
602}
603
604pub struct StructVariant<'py> {
605    py: Python<'py>,
606    variant: &'static str,
607    fields: Bound<'py, PyDict>,
608}
609
610impl<'py> ser::SerializeStructVariant for StructVariant<'py> {
611    type Ok = Bound<'py, PyAny>;
612    type Error = Error;
613
614    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
615    where
616        T: ?Sized + Serialize,
617    {
618        self.fields
619            .set_item(key, value.serialize(PyAnySerializer { py: self.py })?)?;
620        Ok(())
621    }
622
623    fn end(self) -> Result<Self::Ok> {
624        let dict = PyDict::new(self.py);
625        dict.set_item(self.variant, self.fields)?;
626        Ok(dict.into_any())
627    }
628}