Skip to main content

serde_php/
ser.rs

1use crate::error::{Error, Result};
2use serde::{ser, Serialize};
3use std::io::Write;
4
5/// Write out serialization of value.
6#[inline]
7pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()>
8where
9    W: Write,
10    T: Serialize + ?Sized,
11{
12    let mut ser = Serializer::new(writer);
13    value.serialize(&mut ser)
14}
15
16/// Write serialization of value into byte vector.
17#[inline]
18pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
19where
20    T: Serialize + ?Sized,
21{
22    let mut buf = Vec::new();
23    to_writer(&mut buf, value)?;
24    Ok(buf)
25}
26
27/// Central serializer structure.
28#[derive(Debug)]
29struct Serializer<W> {
30    output: W,
31}
32
33impl<W> Serializer<W> {
34    /// Create new serializer on writer.
35    #[inline]
36    fn new(output: W) -> Self {
37        Serializer { output }
38    }
39}
40
41/// Not implemented helper struct.
42///
43/// "Implements" various traits required for serialization that are not supported. Always fails
44/// with an error message if called.
45#[derive(Debug)]
46struct NotImplemented;
47
48impl<'a, W> ser::Serializer for &'a mut Serializer<W>
49where
50    W: Write,
51{
52    type Ok = ();
53
54    type Error = Error;
55
56    type SerializeSeq = NumericArraySerializer<'a, W>;
57    type SerializeTuple = NumericArraySerializer<'a, W>;
58    type SerializeTupleStruct = NumericArraySerializer<'a, W>;
59    type SerializeTupleVariant = NotImplemented;
60    type SerializeMap = Self;
61    type SerializeStruct = Self;
62    type SerializeStructVariant = NotImplemented;
63
64    #[inline]
65    fn serialize_bool(self, v: bool) -> Result<()> {
66        if v {
67            self.output.write_all(b"b:1;")
68        } else {
69            self.output.write_all(b"b:0;")
70        }
71        .map_err(Error::WriteSerialized)
72    }
73
74    #[inline]
75    fn serialize_i8(self, v: i8) -> Result<()> {
76        self.serialize_i64(i64::from(v))
77    }
78
79    #[inline]
80    fn serialize_i16(self, v: i16) -> Result<()> {
81        self.serialize_i64(i64::from(v))
82    }
83
84    #[inline]
85    fn serialize_i32(self, v: i32) -> Result<()> {
86        self.serialize_i64(i64::from(v))
87    }
88
89    #[inline]
90    fn serialize_i64(self, v: i64) -> Result<()> {
91        // We rely on Rust having a "standard" display implementation for
92        // `i64` types, which is a reasonable assumption.
93        write!(self.output, "i:{};", v).map_err(Error::WriteSerialized)
94    }
95
96    #[inline]
97    fn serialize_u8(self, v: u8) -> Result<()> {
98        self.serialize_u64(u64::from(v))
99    }
100
101    #[inline]
102    fn serialize_u16(self, v: u16) -> Result<()> {
103        self.serialize_u64(u64::from(v))
104    }
105
106    #[inline]
107    fn serialize_u32(self, v: u32) -> Result<()> {
108        self.serialize_u64(u64::from(v))
109    }
110
111    #[inline]
112    fn serialize_u64(self, v: u64) -> Result<()> {
113        write!(self.output, "i:{};", v).map_err(Error::WriteSerialized)
114    }
115
116    #[inline]
117    fn serialize_f32(self, v: f32) -> Result<()> {
118        self.serialize_f64(f64::from(v))
119    }
120
121    #[inline]
122    fn serialize_f64(self, v: f64) -> Result<()> {
123        // Float representations _should_ match up.
124        // TODO: Verify this prints edges correctly.
125        write!(self.output, "d:{};", v).map_err(Error::WriteSerialized)
126    }
127
128    #[inline]
129    fn serialize_char(self, v: char) -> Result<()> {
130        self.serialize_u32(u32::from(v))
131    }
132
133    #[inline]
134    fn serialize_str(self, v: &str) -> Result<()> {
135        self.serialize_bytes(v.as_bytes())
136    }
137
138    #[inline]
139    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
140        write!(self.output, "s:{}:\"", v.len()).map_err(Error::WriteSerialized)?;
141        self.output.write_all(v).map_err(Error::WriteSerialized)?;
142        write!(self.output, "\";").map_err(Error::WriteSerialized)
143    }
144
145    #[inline]
146    fn serialize_none(self) -> Result<()> {
147        self.serialize_unit()
148    }
149
150    #[inline]
151    fn serialize_some<T>(self, value: &T) -> Result<()>
152    where
153        T: ?Sized + Serialize,
154    {
155        value.serialize(self)
156    }
157
158    #[inline]
159    fn serialize_unit(self) -> Result<()> {
160        self.output.write_all(b"N;").map_err(Error::WriteSerialized)
161    }
162
163    #[inline]
164    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
165        Err(Error::MissingFeature(
166            "Serialization of unit structures is not supported.",
167        ))
168    }
169
170    #[inline]
171    fn serialize_unit_variant(
172        self,
173        _name: &'static str,
174        _variant_index: u32,
175        _variant: &'static str,
176    ) -> Result<()> {
177        Err(Error::MissingFeature(
178            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
179        ))
180    }
181
182    #[inline]
183    fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
184    where
185        T: ?Sized + Serialize,
186    {
187        // We just "unpack" newtypes when deserializing.
188        value.serialize(self)
189    }
190
191    #[inline]
192    fn serialize_newtype_variant<T>(
193        self,
194        _name: &'static str,
195        _variant_index: u32,
196        _variant: &'static str,
197        _value: &T,
198    ) -> Result<()>
199    where
200        T: ?Sized + Serialize,
201    {
202        Err(Error::MissingFeature(
203            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
204        ))
205    }
206
207    #[inline]
208    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
209        // Sequence serialization is iffy because we would need to buffer
210        // the whole serialized string in memory if we do not know the number
211        // of elements in the sequence.
212        //
213        // We return an error instead if the length is not known, as this is
214        // preferrable to writing multi-megabyte strings into memory by
215        // accident.
216        if let Some(n) = len {
217            // We can assume sequences are all of the same type.
218            write!(self.output, "a:{}:{{", n).map_err(Error::WriteSerialized)?;
219            Ok(NumericArraySerializer::new(self))
220        } else {
221            Err(Error::LengthRequired)
222        }
223    }
224
225    #[inline]
226    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
227        self.serialize_seq(Some(len))
228    }
229
230    #[inline]
231    fn serialize_tuple_struct(
232        self,
233        _name: &'static str,
234        len: usize,
235    ) -> Result<Self::SerializeTupleStruct> {
236        self.serialize_tuple(len)
237    }
238
239    #[inline]
240    fn serialize_tuple_variant(
241        self,
242        _name: &'static str,
243        _variant_index: u32,
244        _variant: &'static str,
245        _len: usize,
246    ) -> Result<Self::SerializeTupleVariant> {
247        Err(Error::MissingFeature(
248            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
249        ))
250    }
251
252    #[inline]
253    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
254        if let Some(n) = len {
255            write!(self.output, "a:{}:{{", n).map_err(Error::WriteSerialized)?;
256            // No need to count elements, thus no added state.
257            Ok(self)
258        } else {
259            Err(Error::LengthRequired)
260        }
261    }
262
263    #[inline]
264    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
265        self.serialize_map(Some(len))
266    }
267
268    #[inline]
269    fn serialize_struct_variant(
270        self,
271        _name: &'static str,
272        _variant_index: u32,
273        _variant: &'static str,
274        _len: usize,
275    ) -> Result<Self::SerializeStructVariant> {
276        Err(Error::MissingFeature(
277            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
278        ))
279    }
280}
281
282/// Helper structure for numeric arrays.
283#[derive(Debug)]
284pub struct NumericArraySerializer<'a, W> {
285    // There is no delimiter for elements (arrays are length-prefixed and
286    // and carry their own terminator. However, we still need to count
287    // the elements.
288    index: usize,
289    serializer: &'a mut Serializer<W>,
290}
291
292impl<'a, W> NumericArraySerializer<'a, W> {
293    /// Create new numeric array helper.
294    fn new(serializer: &'a mut Serializer<W>) -> Self {
295        NumericArraySerializer {
296            index: 0,
297            serializer,
298        }
299    }
300}
301
302impl<'a, W> ser::SerializeSeq for NumericArraySerializer<'a, W>
303where
304    W: Write,
305{
306    type Ok = ();
307    type Error = Error;
308
309    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
310    where
311        T: ?Sized + Serialize,
312    {
313        // Output-format is just index directly followed by value.
314        self.index.serialize(&mut *self.serializer)?;
315        value.serialize(&mut *self.serializer)?;
316        self.index += 1;
317        Ok(())
318    }
319
320    fn end(self) -> Result<()> {
321        self.serializer
322            .output
323            .write_all(b"}")
324            .map_err(Error::WriteSerialized)
325    }
326}
327
328impl<'a, W> ser::SerializeTuple for NumericArraySerializer<'a, W>
329where
330    W: Write,
331{
332    type Ok = ();
333    type Error = Error;
334
335    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
336    where
337        T: ?Sized + Serialize,
338    {
339        ser::SerializeSeq::serialize_element(self, value)
340    }
341
342    fn end(self) -> Result<()> {
343        ser::SerializeSeq::end(self)
344    }
345}
346
347impl<'a, W> ser::SerializeTupleStruct for NumericArraySerializer<'a, W>
348where
349    W: Write,
350{
351    type Ok = ();
352    type Error = Error;
353
354    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
355    where
356        T: ?Sized + Serialize,
357    {
358        ser::SerializeSeq::serialize_element(self, value)
359    }
360
361    fn end(self) -> Result<()> {
362        ser::SerializeSeq::end(self)
363    }
364}
365
366impl ser::SerializeTupleVariant for NotImplemented {
367    type Ok = ();
368    type Error = Error;
369
370    fn serialize_field<T>(&mut self, _value: &T) -> Result<()>
371    where
372        T: ?Sized + Serialize,
373    {
374        Err(Error::MissingFeature(
375            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
376        ))
377    }
378
379    fn end(self) -> Result<()> {
380        Err(Error::MissingFeature(
381            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
382        ))
383    }
384}
385
386impl<'a, W> ser::SerializeMap for &'a mut Serializer<W>
387where
388    W: Write,
389{
390    type Ok = ();
391    type Error = Error;
392
393    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
394    where
395        T: ?Sized + Serialize,
396    {
397        key.serialize(&mut **self)
398    }
399
400    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
401    where
402        T: ?Sized + Serialize,
403    {
404        value.serialize(&mut **self)
405    }
406
407    fn end(self) -> Result<()> {
408        self.output.write_all(b"}").map_err(Error::WriteSerialized)
409    }
410}
411
412impl<'a, W> ser::SerializeStruct for &'a mut Serializer<W>
413where
414    W: Write,
415{
416    type Ok = ();
417    type Error = Error;
418
419    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
420    where
421        T: ?Sized + Serialize,
422    {
423        key.serialize(&mut **self)?;
424        value.serialize(&mut **self)?;
425        Ok(())
426    }
427
428    fn end(self) -> Result<()> {
429        self.output.write_all(b"}").map_err(Error::WriteSerialized)
430    }
431}
432
433impl ser::SerializeStructVariant for NotImplemented {
434    type Ok = ();
435    type Error = Error;
436
437    fn serialize_field<T>(&mut self, _key: &'static str, _value: &T) -> Result<()>
438    where
439        T: ?Sized + Serialize,
440    {
441        Err(Error::MissingFeature(
442            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
443        ))
444    }
445
446    fn end(self) -> Result<()> {
447        Err(Error::MissingFeature(
448            "Serialization of enums is not supported. If you need C-style enums serialized, look at `serde_repr`.",
449        ))
450    }
451}
452
453#[cfg(test)]
454mod tests {
455    use super::to_vec;
456    use serde::Serialize;
457    use std::collections::BTreeMap;
458
459    macro_rules! assert_serializes {
460        ($v:expr, $expected:expr) => {
461            let actual = to_vec(&$v).expect("serialization failed");
462
463            eprintln!("{}", String::from_utf8_lossy(actual.as_slice()));
464            eprintln!("{}", String::from_utf8_lossy($expected));
465
466            assert_eq!(actual.as_slice(), &$expected[..]);
467        };
468    }
469
470    #[test]
471    fn serialize_unit() {
472        assert_serializes!((), b"N;");
473    }
474
475    #[test]
476    fn serialize_bool() {
477        assert_serializes!(false, b"b:0;");
478        assert_serializes!(true, b"b:1;");
479    }
480
481    #[test]
482    fn serialize_integer() {
483        assert_serializes!(-1i64, b"i:-1;");
484        assert_serializes!(0i64, b"i:0;");
485        assert_serializes!(1i64, b"i:1;");
486        assert_serializes!(123i64, b"i:123;");
487    }
488
489    #[test]
490    fn serialize_float() {
491        assert_serializes!(-1f64, b"d:-1;");
492        assert_serializes!(0f64, b"d:0;");
493        assert_serializes!(1f64, b"d:1;");
494        assert_serializes!(-1.9f64, b"d:-1.9;");
495        assert_serializes!(0.9f64, b"d:0.9;");
496        assert_serializes!(1.9f64, b"d:1.9;");
497    }
498
499    #[test]
500    fn serialize_php_string() {
501        assert_serializes!(
502            serde_bytes::Bytes::new(b"single quote '"),
503            br#"s:14:"single quote '";"#
504        );
505
506        assert_serializes!(
507            serde_bytes::ByteBuf::from(b"single quote '".to_vec()),
508            br#"s:14:"single quote '";"#
509        );
510    }
511
512    #[test]
513    fn serialize_string() {
514        assert_serializes!("single quote '", br#"s:14:"single quote '";"#);
515        assert_serializes!("single quote '".to_owned(), br#"s:14:"single quote '";"#);
516    }
517
518    #[test]
519    fn serialize_array() {
520        #[derive(Debug, Serialize, Eq, PartialEq)]
521        struct SubData();
522
523        #[derive(Debug, Serialize, Eq, PartialEq)]
524        struct Data(
525            #[serde(with = "serde_bytes")] Vec<u8>,
526            #[serde(with = "serde_bytes")] Vec<u8>,
527            SubData,
528        );
529
530        assert_serializes!(
531            Data(b"user".to_vec(), b"".to_vec(), SubData()),
532            br#"a:3:{i:0;s:4:"user";i:1;s:0:"";i:2;a:0:{}}"#
533        );
534    }
535
536    #[test]
537    fn serialize_struct() {
538        // PHP equiv:
539        //
540        // array("foo" => true,
541        //       "bar" => "xyz",
542        //       "sub" => array("x" => 42))
543
544        #[derive(Debug, Serialize, Eq, PartialEq)]
545        struct Outer {
546            foo: bool,
547            bar: String,
548            sub: Inner,
549        }
550
551        #[derive(Debug, Serialize, Eq, PartialEq)]
552        struct Inner {
553            x: i64,
554        }
555
556        assert_serializes!(
557            Outer {
558                foo: true,
559                bar: "xyz".to_owned(),
560                sub: Inner { x: 42 },
561            },
562            br#"a:3:{s:3:"foo";b:1;s:3:"bar";s:3:"xyz";s:3:"sub";a:1:{s:1:"x";i:42;}}"#
563        );
564    }
565
566    #[test]
567    fn serialize_struct_with_optional() {
568        #[derive(Debug, Serialize, Eq, PartialEq)]
569        struct Location {
570            #[serde(skip_serializing_if = "Option::is_none")]
571            province: Option<String>,
572            #[serde(skip_serializing_if = "Option::is_none")]
573            postalcode: Option<String>,
574            #[serde(skip_serializing_if = "Option::is_none")]
575            country: Option<String>,
576        }
577
578        assert_serializes!(
579            Location {
580                province: None,
581                postalcode: None,
582                country: None,
583            },
584            br#"a:0:{}"#
585        );
586
587        assert_serializes!(
588            Location {
589                province: Some("Newfoundland and Labrador, CA".to_owned()),
590                postalcode: None,
591                country: None,
592            },
593            br#"a:1:{s:8:"province";s:29:"Newfoundland and Labrador, CA";}"#
594        );
595
596        assert_serializes!(
597            Location {
598                province: None,
599                postalcode: Some("90002".to_owned()),
600                country: Some("United States of America".to_owned()),
601            },
602            br#"a:2:{s:10:"postalcode";s:5:"90002";s:7:"country";s:24:"United States of America";}"#
603        );
604    }
605
606    #[test]
607    fn serialize_nested() {
608        // PHP: array("x" => array("inner" => 1), "y" => array("inner" => 2))
609
610        #[derive(Debug, Serialize, Eq, PartialEq)]
611        struct Outer {
612            x: Inner,
613            y: Inner,
614        }
615
616        #[derive(Debug, Serialize, Eq, PartialEq)]
617        struct Inner {
618            inner: u8,
619        }
620
621        assert_serializes!(
622            Outer {
623                x: Inner { inner: 1 },
624                y: Inner { inner: 2 },
625            },
626            br#"a:2:{s:1:"x";a:1:{s:5:"inner";i:1;}s:1:"y";a:1:{s:5:"inner";i:2;}}"#
627        );
628    }
629
630    #[test]
631    fn serialize_variable_length() {
632        // PHP: array(1.1, 2.2, 3.3, 4.4)
633        assert_serializes!(
634            vec![1.1, 2.2, 3.3, 4.4],
635            br#"a:4:{i:0;d:1.1;i:1;d:2.2;i:2;d:3.3;i:3;d:4.4;}"#
636        );
637    }
638
639    #[test]
640    fn serialize_btreemap() {
641        // PHP: array("foo" => 1, "bar" => 2)
642        let mut input: BTreeMap<String, u16> = BTreeMap::new();
643        input.insert("foo".to_owned(), 42);
644        input.insert("bar".to_owned(), 7);
645
646        assert_serializes!(input, br#"a:2:{s:3:"bar";i:7;s:3:"foo";i:42;}"#);
647    }
648
649    #[test]
650    fn unaffected_by_recursive_type_error() {
651        // The following code will not compile, but fail with an infinite type recursion instead,
652        // if self-referential associated types are used.
653        //
654        // See
655        //
656        // * https://github.com/rust-lang/rust/issues/62755
657        //
658        // This is technically a bug that only props up in specific cases, but is very confusing
659        // for the caller.
660
661        let val: bson::Bson = bson::Document::new().into();
662        to_vec(&val).unwrap();
663    }
664}