firestore_serde/
lib.rs

1pub use crate::deserialize::ValueDeserializer;
2use crate::firestore::{value::ValueType, Document, MapValue, Value};
3use crate::serialize::SerializationError;
4pub use crate::serialize::ValueSerializer;
5use serde::de::DeserializeOwned;
6use serde::Serialize;
7
8mod deserialize;
9pub mod firestore;
10mod serialize;
11
12pub const TYPE: &str = "type";
13pub const VALUE: &str = "value";
14pub const VALUES: &str = "values";
15pub const DATE_MAGIC: &str = "$TimestampValue";
16
17#[cfg(all(feature = "google-firestore-v1", feature = "google-firestore-v1beta1"))]
18compile_error!("If you enable the google-firestore-v1beta1 crate feature, you must disable the default feature google-firestore-v1 to avoid a conflict.");
19
20pub fn to_grpc_value<T>(value: &T) -> crate::serialize::Result<Value>
21where
22    T: Serialize,
23{
24    let result = value.serialize(ValueSerializer)?;
25    Ok(result)
26}
27
28pub fn from_grpc_value<T>(value: &Value) -> crate::deserialize::Result<T>
29where
30    T: DeserializeOwned,
31{
32    T::deserialize(&mut ValueDeserializer(value))
33}
34
35pub fn to_document<T>(value: &T) -> crate::serialize::Result<Document>
36where
37    T: Serialize,
38{
39    if let Value {
40        value_type: Some(ValueType::MapValue(MapValue { fields })),
41    } = to_grpc_value(value)?
42    {
43        Ok(Document {
44            fields,
45            ..Document::default()
46        })
47    } else {
48        Err(SerializationError::NotAMap)
49    }
50}
51
52pub fn from_document<T>(document: Document) -> crate::deserialize::Result<T>
53where
54    T: DeserializeOwned,
55{
56    let fields = document.fields;
57    let value = Value {
58        value_type: Some(ValueType::MapValue(MapValue { fields })),
59    };
60
61    from_grpc_value(&value)
62}
63
64#[cfg(test)]
65mod test {
66    use super::*;
67    use crate::firestore::ArrayValue;
68    use crate::serialize::SerializationError;
69    use serde::Deserialize;
70    use serde_bytes::{ByteBuf, Bytes};
71    use std::{collections::HashMap, convert::TryFrom, fmt::Display};
72
73    #[test]
74    fn test_serialize_string() {
75        let result = to_grpc_value(&"blah").unwrap();
76
77        assert_eq!(
78            Value {
79                value_type: Some(ValueType::StringValue("blah".to_string()))
80            },
81            result
82        );
83
84        assert_eq!(
85            "blah".to_string(),
86            from_grpc_value::<String>(&result).unwrap()
87        )
88    }
89
90    #[test]
91    fn test_serialize_bytes() {
92        // Per https://serde.rs/impl-serialize.html#other-special-cases,
93        // serialize_bytes is not used directly. We could create a wrapper
94        // type that uses it, though, so we've implemented it.
95        let v = Bytes::new(b"blah");
96        let result = to_grpc_value(&v).unwrap();
97
98        assert_eq!(
99            Value {
100                value_type: Some(ValueType::BytesValue(v.to_vec()))
101            },
102            result
103        );
104
105        assert_eq!(*v, from_grpc_value::<ByteBuf>(&result).unwrap());
106
107        // Without the serde_bytes crate, we can still deserialize bytes
108        // as a Vec<u8>.
109        assert_eq!(
110            v.iter().cloned().collect::<Vec<u8>>(),
111            from_grpc_value::<Vec<u8>>(&result).unwrap()
112        )
113    }
114
115    #[test]
116    fn test_serialize_char() {
117        let result = to_grpc_value(&'a').unwrap();
118
119        assert_eq!(
120            Value {
121                value_type: Some(ValueType::StringValue("a".to_string()))
122            },
123            result
124        );
125
126        assert_eq!('a', from_grpc_value::<char>(&result).unwrap())
127    }
128
129    #[test]
130    fn test_serialize_option() {
131        let p: Option<u32> = None;
132        let result = to_grpc_value(&p).unwrap();
133
134        assert_eq!(
135            Value {
136                value_type: Some(ValueType::NullValue(0))
137            },
138            result
139        );
140
141        assert_eq! {
142            p,
143            from_grpc_value::<Option<u32>>(&result).unwrap()
144        }
145
146        let result = to_grpc_value(&Some(100)).unwrap();
147
148        assert_eq!(
149            Value {
150                value_type: Some(ValueType::IntegerValue(100))
151            },
152            result
153        );
154
155        assert_eq! {
156            Some(100),
157            from_grpc_value::<Option<u32>>(&result).unwrap()
158        }
159    }
160
161    fn test_serialize_int_type<'a, T>(num: T)
162    where
163        i64: TryFrom<T>,
164        T: Serialize + Display + Copy + PartialEq + std::fmt::Debug + DeserializeOwned,
165    {
166        let result = to_grpc_value(&num).unwrap();
167
168        let exp_val = if let Ok(val) = i64::try_from(num) {
169            val
170        } else {
171            // Should only occur if we convert a u64 that is
172            // greater than the i64 range.
173            panic!("Could not convert {} to i64", num);
174        };
175
176        assert_eq!(
177            Value {
178                value_type: Some(ValueType::IntegerValue(exp_val))
179            },
180            result
181        );
182
183        assert_eq!(num, from_grpc_value(&result).unwrap());
184    }
185
186    #[test]
187    fn test_serialize_int() {
188        test_serialize_int_type(4u8);
189        test_serialize_int_type(4u16);
190        test_serialize_int_type(4u32);
191        test_serialize_int_type(4u64);
192
193        test_serialize_int_type(4i8);
194        test_serialize_int_type(4i16);
195        test_serialize_int_type(4i32);
196        test_serialize_int_type(4i64);
197
198        assert_eq!(
199            SerializationError::OutsideIntRange(u64::MAX),
200            to_grpc_value(&u64::MAX).unwrap_err()
201        );
202    }
203
204    #[test]
205    fn test_serialize_float() {
206        let result = to_grpc_value(&99.9f32).unwrap();
207
208        assert_eq!(
209            Value {
210                value_type: Some(ValueType::DoubleValue(f64::from(99.9f32)))
211            },
212            result
213        );
214
215        assert_eq!(99.9f32, from_grpc_value(&result).unwrap());
216
217        let result = to_grpc_value(&99.9f64).unwrap();
218
219        assert_eq!(
220            Value {
221                value_type: Some(ValueType::DoubleValue(99.9f64))
222            },
223            result
224        );
225
226        assert_eq!(99.9f64, from_grpc_value(&result).unwrap());
227    }
228
229    #[test]
230    fn test_serialize_bool() {
231        let result_true = to_grpc_value(&true).unwrap();
232
233        assert_eq!(
234            Value {
235                value_type: Some(ValueType::BooleanValue(true))
236            },
237            result_true
238        );
239
240        assert_eq!(true, from_grpc_value(&result_true).unwrap());
241
242        let result_false = to_grpc_value(&false).unwrap();
243
244        assert_eq!(
245            Value {
246                value_type: Some(ValueType::BooleanValue(false))
247            },
248            result_false
249        );
250
251        assert_eq!(false, from_grpc_value(&result_false).unwrap());
252    }
253
254    #[derive(Serialize)]
255    struct JustAUnitStruct;
256
257    #[test]
258    fn test_unrepresentable() {
259        assert_eq!(
260            SerializationError::Unrepresentable("()".to_string()),
261            to_grpc_value(&()).unwrap_err()
262        );
263
264        assert_eq!(
265            SerializationError::Unrepresentable("unit_struct".to_string()),
266            to_grpc_value(&JustAUnitStruct).unwrap_err()
267        );
268    }
269
270    #[derive(Serialize, Deserialize, PartialEq, Debug)]
271    enum JustAnEnum {
272        TagUnitVariant,
273        ANewtypeVariant(u32),
274        ATupleVariant(u8, bool),
275        ARecordVariant { an_int: u32, a_bool: bool },
276    }
277
278    #[test]
279    fn test_serialize_enum_record() {
280        let v = JustAnEnum::ARecordVariant {
281            an_int: 4,
282            a_bool: false,
283        };
284        let result = to_grpc_value(&v).unwrap();
285
286        assert_eq!(
287            Value {
288                value_type: Some(ValueType::MapValue(MapValue {
289                    fields: vec![
290                        (
291                            TYPE.to_string(),
292                            Value {
293                                value_type: Some(ValueType::StringValue(
294                                    "ARecordVariant".to_string()
295                                ))
296                            }
297                        ),
298                        (
299                            VALUES.to_string(),
300                            Value {
301                                value_type: Some(ValueType::MapValue(MapValue {
302                                    fields: vec![
303                                        (
304                                            "an_int".to_string(),
305                                            Value {
306                                                value_type: Some(ValueType::IntegerValue(4))
307                                            }
308                                        ),
309                                        (
310                                            "a_bool".to_string(),
311                                            Value {
312                                                value_type: Some(ValueType::BooleanValue(false))
313                                            }
314                                        ),
315                                    ]
316                                    .into_iter()
317                                    .collect()
318                                }))
319                            }
320                        )
321                    ]
322                    .into_iter()
323                    .collect()
324                }))
325            },
326            result
327        );
328
329        assert_eq!(v, from_grpc_value(&result).unwrap());
330    }
331
332    #[test]
333    fn test_serialize_enum_unit() {
334        let result = to_grpc_value(&JustAnEnum::TagUnitVariant).unwrap();
335
336        assert_eq!(
337            Value {
338                value_type: Some(ValueType::StringValue("TagUnitVariant".to_string()))
339            },
340            result
341        );
342
343        assert_eq!(
344            JustAnEnum::TagUnitVariant,
345            from_grpc_value(&result).unwrap()
346        );
347    }
348
349    #[test]
350    fn test_serialize_enum_newtype() {
351        let v = JustAnEnum::ANewtypeVariant(55);
352        let result = to_grpc_value(&v).unwrap();
353
354        assert_eq!(
355            Value {
356                value_type: Some(ValueType::MapValue(MapValue {
357                    fields: vec![
358                        (
359                            "type".to_string(),
360                            Value {
361                                value_type: Some(ValueType::StringValue(
362                                    "ANewtypeVariant".to_string()
363                                ))
364                            }
365                        ),
366                        (
367                            "value".to_string(),
368                            Value {
369                                value_type: Some(ValueType::IntegerValue(55))
370                            }
371                        ),
372                    ]
373                    .into_iter()
374                    .collect()
375                }))
376            },
377            result
378        );
379
380        assert_eq!(v, from_grpc_value(&result).unwrap());
381    }
382
383    #[test]
384    fn test_serialize_enum_tuple() {
385        let v = JustAnEnum::ATupleVariant(55, false);
386        let result = to_grpc_value(&v).unwrap();
387
388        assert_eq!(
389            Value {
390                value_type: Some(ValueType::MapValue(MapValue {
391                    fields: vec![
392                        (
393                            "type".to_string(),
394                            Value {
395                                value_type: Some(ValueType::StringValue(
396                                    "ATupleVariant".to_string()
397                                ))
398                            }
399                        ),
400                        (
401                            "values".to_string(),
402                            Value {
403                                value_type: Some(ValueType::ArrayValue(ArrayValue {
404                                    values: vec![
405                                        Value {
406                                            value_type: Some(ValueType::IntegerValue(55))
407                                        },
408                                        Value {
409                                            value_type: Some(ValueType::BooleanValue(false))
410                                        },
411                                    ]
412                                }))
413                            }
414                        ),
415                    ]
416                    .into_iter()
417                    .collect()
418                }))
419            },
420            result
421        );
422
423        assert_eq!(v, from_grpc_value(&result).unwrap());
424    }
425
426    #[test]
427    fn serialize_tuple() {
428        let v = (3, false, "okay".to_string());
429        let result = to_grpc_value(&v).unwrap();
430
431        assert_eq!(
432            Value {
433                value_type: Some(ValueType::ArrayValue(ArrayValue {
434                    values: vec![
435                        Value {
436                            value_type: Some(ValueType::IntegerValue(3))
437                        },
438                        Value {
439                            value_type: Some(ValueType::BooleanValue(false))
440                        },
441                        Value {
442                            value_type: Some(ValueType::StringValue("okay".to_string()))
443                        },
444                    ]
445                }))
446            },
447            result
448        );
449
450        assert_eq!(v, from_grpc_value(&result).unwrap());
451    }
452
453    #[test]
454    fn serialize_slice() {
455        let v = [9, 5, 1];
456        let result = to_grpc_value(&v).unwrap();
457
458        assert_eq!(
459            Value {
460                value_type: Some(ValueType::ArrayValue(ArrayValue {
461                    values: vec![
462                        Value {
463                            value_type: Some(ValueType::IntegerValue(9))
464                        },
465                        Value {
466                            value_type: Some(ValueType::IntegerValue(5))
467                        },
468                        Value {
469                            value_type: Some(ValueType::IntegerValue(1))
470                        },
471                    ]
472                }))
473            },
474            result
475        );
476
477        assert_eq!(v, from_grpc_value::<[u32; 3]>(&result).unwrap());
478    }
479
480    #[test]
481    fn serialize_vector() {
482        let v = vec![9, 5, 1];
483        let result = to_grpc_value(&v).unwrap();
484
485        assert_eq!(
486            Value {
487                value_type: Some(ValueType::ArrayValue(ArrayValue {
488                    values: vec![
489                        Value {
490                            value_type: Some(ValueType::IntegerValue(9))
491                        },
492                        Value {
493                            value_type: Some(ValueType::IntegerValue(5))
494                        },
495                        Value {
496                            value_type: Some(ValueType::IntegerValue(1))
497                        },
498                    ]
499                }))
500            },
501            result
502        );
503
504        assert_eq!(v, from_grpc_value::<Vec<u32>>(&result).unwrap());
505    }
506
507    #[derive(Serialize, Deserialize, PartialEq, Debug)]
508    struct JustATupleStruct(u32, bool, String);
509
510    #[test]
511    fn serialize_tuple_struct() {
512        let v = JustATupleStruct(3, false, "okay".to_string());
513        let result = to_grpc_value(&v).unwrap();
514
515        assert_eq!(
516            Value {
517                value_type: Some(ValueType::ArrayValue(ArrayValue {
518                    values: vec![
519                        Value {
520                            value_type: Some(ValueType::IntegerValue(3))
521                        },
522                        Value {
523                            value_type: Some(ValueType::BooleanValue(false))
524                        },
525                        Value {
526                            value_type: Some(ValueType::StringValue("okay".to_string()))
527                        },
528                    ]
529                }))
530            },
531            result
532        );
533
534        assert_eq!(v, from_grpc_value(&result).unwrap());
535    }
536
537    #[derive(Serialize, Deserialize, PartialEq, Debug)]
538    struct ARecordStruct {
539        an_int_field: u32,
540        a_string_field: String,
541        a_vec_field: Vec<bool>,
542    }
543
544    #[test]
545    fn serialize_record_struct() {
546        let v = ARecordStruct {
547            an_int_field: 8,
548            a_string_field: "blah".to_string(),
549            a_vec_field: vec![false, false, true],
550        };
551        let result = to_grpc_value(&v).unwrap();
552
553        assert_eq!(
554            Value {
555                value_type: Some(ValueType::MapValue(MapValue {
556                    fields: vec![
557                        (
558                            "an_int_field".to_string(),
559                            Value {
560                                value_type: Some(ValueType::IntegerValue(8))
561                            }
562                        ),
563                        (
564                            "a_string_field".to_string(),
565                            Value {
566                                value_type: Some(ValueType::StringValue("blah".to_string()))
567                            }
568                        ),
569                        (
570                            "a_vec_field".to_string(),
571                            Value {
572                                value_type: Some(ValueType::ArrayValue(ArrayValue {
573                                    values: vec![
574                                        Value {
575                                            value_type: Some(ValueType::BooleanValue(false))
576                                        },
577                                        Value {
578                                            value_type: Some(ValueType::BooleanValue(false))
579                                        },
580                                        Value {
581                                            value_type: Some(ValueType::BooleanValue(true))
582                                        },
583                                    ]
584                                }))
585                            }
586                        ),
587                    ]
588                    .into_iter()
589                    .collect()
590                }))
591            },
592            result
593        );
594
595        assert_eq!(v, from_grpc_value(&result).unwrap());
596    }
597
598    #[test]
599    fn serialize_map() {
600        let map: HashMap<String, u32> = vec![("foo".to_string(), 5), ("bar".to_string(), 50)]
601            .into_iter()
602            .collect();
603
604        let result = to_grpc_value(&map).unwrap();
605
606        assert_eq!(
607            Value {
608                value_type: Some(ValueType::MapValue(MapValue {
609                    fields: vec![
610                        (
611                            "foo".to_string(),
612                            Value {
613                                value_type: Some(ValueType::IntegerValue(5))
614                            }
615                        ),
616                        (
617                            "bar".to_string(),
618                            Value {
619                                value_type: Some(ValueType::IntegerValue(50))
620                            }
621                        ),
622                    ]
623                    .into_iter()
624                    .collect()
625                }))
626            },
627            result
628        );
629
630        assert_eq!(map, from_grpc_value(&result).unwrap());
631    }
632
633    #[derive(Serialize, PartialEq, Debug, Deserialize)]
634    struct ANewtypeStruct(u32);
635
636    #[test]
637    fn serialize_newtype_struct() {
638        let record = ANewtypeStruct(55);
639
640        let result = to_grpc_value(&record).unwrap();
641
642        assert_eq!(
643            Value {
644                value_type: Some(ValueType::IntegerValue(55))
645            },
646            result
647        );
648
649        assert_eq!(record, from_grpc_value(&result).unwrap());
650    }
651}