php_serde/
ser.rs

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