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 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 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 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}