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}