substreams_entity_change/
change.rs

1use crate::pb::entity::value::Typed;
2use crate::pb::entity::{Array, Field, Value};
3use std::str;
4use substreams::pb::substreams::store_delta::Operation;
5use substreams::scalar::{BigDecimal, BigInt};
6use substreams::store::{
7    DeltaArray, DeltaBigDecimal, DeltaBigInt, DeltaBool, DeltaBytes, DeltaInt32, DeltaString,
8};
9
10pub trait ToField {
11    fn to_field<N: AsRef<str>>(self, name: N) -> Field;
12}
13
14impl Into<Typed> for i32 {
15    fn into(self) -> Typed {
16        Typed::Int32(self)
17    }
18}
19
20impl ToField for DeltaInt32 {
21    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
22        ToField::to_field(&self, name)
23    }
24}
25
26impl ToField for &DeltaInt32 {
27    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
28        delta_to_field(
29            name.as_ref(),
30            self.operation,
31            self.old_value,
32            self.new_value,
33        )
34    }
35}
36
37// ---------- BigDecimal ----------
38impl Into<Typed> for BigDecimal {
39    fn into(self) -> Typed {
40        Into::into(&self)
41    }
42}
43
44impl Into<Typed> for &BigDecimal {
45    fn into(self) -> Typed {
46        Typed::Bigdecimal(self.to_string())
47    }
48}
49
50impl ToField for DeltaBigDecimal {
51    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
52        delta_to_field(
53            name.as_ref(),
54            self.operation,
55            self.old_value,
56            self.new_value,
57        )
58    }
59}
60
61impl ToField for &DeltaBigDecimal {
62    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
63        delta_to_field(
64            name.as_ref(),
65            self.operation,
66            &self.old_value,
67            &self.new_value,
68        )
69    }
70}
71// ---------- BigInt ----------
72impl Into<Typed> for BigInt {
73    fn into(self) -> Typed {
74        Into::into(&self)
75    }
76}
77
78impl Into<Typed> for &BigInt {
79    fn into(self) -> Typed {
80        Typed::Bigint(self.to_string())
81    }
82}
83
84impl ToField for DeltaBigInt {
85    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
86        delta_to_field(
87            name.as_ref(),
88            self.operation,
89            self.old_value,
90            self.new_value,
91        )
92    }
93}
94
95impl ToField for &DeltaBigInt {
96    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
97        delta_to_field(
98            name.as_ref(),
99            self.operation,
100            &self.old_value,
101            &self.new_value,
102        )
103    }
104}
105
106// ---------- BigDecimalArray ----------
107
108impl Into<Typed> for Vec<BigDecimal> {
109    fn into(self) -> Typed {
110        Into::into(&self)
111    }
112}
113
114impl Into<Typed> for &Vec<BigDecimal> {
115    fn into(self) -> Typed {
116        let mut list: Vec<Value> = vec![];
117        for item in self.iter() {
118            list.push(Value {
119                typed: Some(Typed::Bigdecimal(item.to_string())),
120            });
121        }
122
123        Typed::Array(Array { value: list })
124    }
125}
126
127impl ToField for DeltaArray<BigDecimal> {
128    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
129        ToField::to_field(&self, name)
130    }
131}
132
133impl ToField for &DeltaArray<BigDecimal> {
134    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
135        let new_value: Option<Value> = Some(Value {
136            typed: Some((&self.new_value).into()),
137        });
138        let mut old_value: Option<Value> = None;
139
140        match Operation::from(self.operation) {
141            Operation::Update => {
142                old_value = Some(Value {
143                    typed: Some((&self.old_value).into()),
144                });
145            }
146            Operation::Create => {}
147            _ => panic!("unsupported operation {:?}", self.operation),
148        }
149
150        #[allow(deprecated)]
151        Field {
152            name: name.as_ref().to_string(),
153            new_value,
154            old_value,
155        }
156    }
157}
158
159// ---------- BigIntArray ----------
160
161impl Into<Typed> for Vec<BigInt> {
162    fn into(self) -> Typed {
163        Into::into(&self)
164    }
165}
166
167impl Into<Typed> for &Vec<BigInt> {
168    fn into(self) -> Typed {
169        let mut list: Vec<Value> = vec![];
170        for item in self.iter() {
171            list.push(Value {
172                typed: Some(Typed::Bigint(item.to_string())),
173            });
174        }
175
176        Typed::Array(Array { value: list })
177    }
178}
179
180impl ToField for DeltaArray<BigInt> {
181    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
182        ToField::to_field(&self, name)
183    }
184}
185
186impl ToField for &DeltaArray<BigInt> {
187    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
188        let new_value: Option<Value> = Some(Value {
189            typed: Some((&self.new_value).into()),
190        });
191        let mut old_value: Option<Value> = None;
192
193        match Operation::from(self.operation) {
194            Operation::Update => {
195                old_value = Some(Value {
196                    typed: Some((&self.old_value).into()),
197                });
198            }
199            Operation::Create => {}
200            _ => panic!("unsupported operation {:?}", self.operation),
201        }
202
203        #[allow(deprecated)]
204        Field {
205            name: name.as_ref().to_string(),
206            new_value,
207            old_value,
208        }
209    }
210}
211
212// ---------- String ----------
213impl Into<Typed> for String {
214    fn into(self) -> Typed {
215        let string = clean_invalid_string_sequence(self.clone());
216        Typed::String(string)
217    }
218}
219
220impl Into<Typed> for &String {
221    fn into(self) -> Typed {
222        let string = clean_invalid_string_sequence(self.clone());
223        Typed::String(string)
224    }
225}
226
227impl ToField for DeltaString {
228    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
229        delta_to_field(
230            name.as_ref(),
231            self.operation,
232            self.old_value,
233            self.new_value,
234        )
235    }
236}
237
238impl ToField for &DeltaString {
239    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
240        delta_to_field(
241            name.as_ref(),
242            self.operation,
243            &self.old_value,
244            &self.new_value,
245        )
246    }
247}
248
249// ---------- Bytes ----------
250impl Into<Typed> for Vec<u8> {
251    fn into(self) -> Typed {
252        Into::into(&self)
253    }
254}
255
256impl Into<Typed> for &Vec<u8> {
257    fn into(self) -> Typed {
258        Typed::Bytes(base64::encode(self))
259    }
260}
261
262impl ToField for DeltaBytes {
263    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
264        ToField::to_field(&self, name)
265    }
266}
267
268impl ToField for &DeltaBytes {
269    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
270        delta_to_field(
271            name.as_ref(),
272            self.operation,
273            &self.old_value,
274            &self.new_value,
275        )
276    }
277}
278
279// ---------- ByteArray ----------
280impl Into<Typed> for Vec<Vec<u8>> {
281    fn into(self) -> Typed {
282        Into::into(&self)
283    }
284}
285
286impl Into<Typed> for &Vec<Vec<u8>> {
287    fn into(self) -> Typed {
288        let mut list: Vec<Value> = vec![];
289        for item in self.iter() {
290            list.push(Value {
291                typed: Some(Typed::Bytes(base64::encode(item))),
292            });
293        }
294
295        Typed::Array(Array { value: list })
296    }
297}
298
299impl ToField for DeltaArray<Vec<u8>> {
300    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
301        ToField::to_field(&self, name)
302    }
303}
304
305impl ToField for &DeltaArray<Vec<u8>> {
306    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
307        let new_value: Option<Value> = Some(Value {
308            typed: Some((&self.new_value).into()),
309        });
310        let mut old_value: Option<Value> = None;
311
312        match Operation::from(self.operation) {
313            Operation::Update => {
314                old_value = Some(Value {
315                    typed: Some((&self.old_value).into()),
316                });
317            }
318            Operation::Create => {}
319            _ => panic!("unsupported operation {:?}", self.operation),
320        }
321
322        #[allow(deprecated)]
323        Field {
324            name: name.as_ref().to_string(),
325            new_value,
326            old_value,
327        }
328    }
329}
330
331fn delta_to_field<T: Into<Typed>>(
332    name: &str,
333    operation: Operation,
334    old_value: T,
335    new_value: T,
336) -> Field {
337    match Operation::from(operation) {
338        Operation::Update => ToField::to_field((old_value, new_value), name),
339        Operation::Create => ToField::to_field(new_value, name),
340        x => panic!("unsupported operation {:?}", x),
341    }
342}
343
344// ---------- BoolChange ----------
345impl Into<Typed> for bool {
346    fn into(self) -> Typed {
347        Typed::Bool(self)
348    }
349}
350
351impl ToField for DeltaBool {
352    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
353        ToField::to_field(&self, name)
354    }
355}
356
357impl ToField for &DeltaBool {
358    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
359        let new_value: Option<Value> = Some(Value {
360            typed: Some(self.new_value.into()),
361        });
362        let mut old_value: Option<Value> = None;
363
364        match Operation::from(self.operation) {
365            Operation::Update => {
366                old_value = Some(Value {
367                    typed: Some(self.old_value.into()),
368                });
369            }
370            Operation::Create => {}
371            _ => panic!("unsupported operation {:?}", self.operation),
372        }
373
374        #[allow(deprecated)]
375        Field {
376            name: name.as_ref().to_string(),
377            new_value,
378            old_value,
379        }
380    }
381}
382
383// ---------- StringArray ----------
384impl Into<Typed> for Vec<String> {
385    fn into(self) -> Typed {
386        Into::into(&self)
387    }
388}
389
390impl Into<Typed> for &Vec<String> {
391    fn into(self) -> Typed {
392        let mut list: Vec<Value> = vec![];
393        for item in self.iter() {
394            let string = clean_invalid_string_sequence(item.clone());
395            list.push(Value {
396                typed: Some(Typed::String(string)),
397            });
398        }
399
400        Typed::Array(Array { value: list })
401    }
402}
403
404impl ToField for DeltaArray<String> {
405    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
406        ToField::to_field(&self, name)
407    }
408}
409
410impl ToField for &DeltaArray<String> {
411    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
412        let new_value: Option<Value> = Some(Value {
413            typed: Some((&self.new_value).into()),
414        });
415        let mut old_value: Option<Value> = None;
416
417        match Operation::from(self.operation) {
418            Operation::Update => {
419                old_value = Some(Value {
420                    typed: Some((&self.old_value).into()),
421                });
422            }
423            Operation::Create => {}
424            _ => panic!("unsupported operation {:?}", self.operation),
425        }
426
427        #[allow(deprecated)]
428        Field {
429            name: name.as_ref().to_string(),
430            new_value,
431            old_value,
432        }
433    }
434}
435
436impl Into<Typed> for u64 {
437    fn into(self) -> Typed {
438        Typed::Bigint(self.to_string())
439    }
440}
441
442impl Into<Typed> for ::prost_types::Timestamp {
443    fn into(self) -> Typed {
444        Into::into(&self)
445    }
446}
447
448impl Into<Typed> for &::prost_types::Timestamp {
449    fn into(self) -> Typed {
450        Typed::String(self.to_string())
451    }
452}
453
454impl<T: Into<Typed>> ToField for T {
455    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
456        #[allow(deprecated)]
457        Field {
458            name: name.as_ref().to_string(),
459            old_value: None,
460            new_value: Some(Value {
461                typed: Some(self.into()),
462            }),
463        }
464    }
465}
466
467impl<T: Into<Typed>> ToField for (T, T) {
468    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
469        #[allow(deprecated)]
470        Field {
471            name: name.as_ref().to_string(),
472            old_value: Some(Value {
473                typed: Some(self.0.into()),
474            }),
475            new_value: Some(Value {
476                typed: Some(self.1.into()),
477            }),
478        }
479    }
480}
481
482impl<T: Into<Typed>> ToField for (T, Option<T>) {
483    fn to_field<N: AsRef<str>>(self, name: N) -> Field {
484        match self.1 {
485            Some(x) => ToField::to_field((self.0, x), name),
486            None =>
487            {
488                #[allow(deprecated)]
489                Field {
490                    name: name.as_ref().to_string(),
491                    old_value: Some(Value {
492                        typed: Some(self.0.into()),
493                    }),
494                    new_value: None,
495                }
496            }
497        }
498    }
499}
500
501fn clean_invalid_string_sequence(invalid_string: String) -> String {
502    let mut string = invalid_string;
503
504    // Strip null characters since they are not accepted by Postgres.
505    if string.contains('\u{0000}') {
506        string = string.replace('\u{0000}', "");
507    }
508
509    string
510}
511
512#[cfg(test)]
513mod test {
514    use crate::change::ToField;
515    use crate::pb::entity::value::Typed;
516    use crate::pb::entity::{Array, Field, Value};
517    use substreams::pb::substreams::store_delta::Operation;
518    use substreams::scalar::{BigDecimal, BigInt};
519    use substreams::store::{
520        DeltaArray, DeltaBigDecimal, DeltaBigInt, DeltaBool, DeltaBytes, DeltaString,
521    };
522
523    const FIELD_NAME: &str = "field.name.1";
524
525    #[test]
526    fn i32_change() {
527        let i32_change: i32 = 1;
528        assert_eq!(
529            create_expected_field(FIELD_NAME, None, Some(Typed::Int32(1))),
530            i32_change.to_field(FIELD_NAME)
531        );
532    }
533
534    #[test]
535    fn big_decimal_change() {
536        let bd_change = BigDecimal::from(1 as i32);
537        assert_eq!(
538            create_expected_field(FIELD_NAME, None, Some(Typed::Bigdecimal("1".to_string()))),
539            bd_change.to_field(FIELD_NAME)
540        );
541    }
542
543    #[test]
544    fn delta_big_decimal_change() {
545        let delta = DeltaBigDecimal {
546            operation: Operation::Update,
547            ordinal: 0,
548            key: "change".to_string(),
549            old_value: BigDecimal::from(10),
550            new_value: BigDecimal::from(20),
551        };
552
553        assert_eq!(
554            create_expected_field(
555                FIELD_NAME,
556                Some(Typed::Bigdecimal("10".to_string())),
557                Some(Typed::Bigdecimal("20".to_string()))
558            ),
559            delta.to_field(FIELD_NAME)
560        );
561    }
562
563    #[test]
564    fn big_int_change() {
565        let bi_change = BigInt::from(1 as i32);
566        assert_eq!(
567            create_expected_field(FIELD_NAME, None, Some(Typed::Bigint("1".to_string()))),
568            bi_change.to_field(FIELD_NAME)
569        );
570    }
571
572    #[test]
573    fn delta_big_int_change() {
574        let delta = DeltaBigInt {
575            operation: Operation::Update,
576            ordinal: 0,
577            key: "change".to_string(),
578            old_value: BigInt::from(10),
579            new_value: BigInt::from(20),
580        };
581
582        assert_eq!(
583            create_expected_field(
584                FIELD_NAME,
585                Some(Typed::Bigint("10".to_string())),
586                Some(Typed::Bigint("20".to_string()))
587            ),
588            delta.to_field(FIELD_NAME)
589        );
590    }
591
592    #[test]
593    fn string_change() {
594        let string_change = String::from("string");
595        assert_eq!(
596            create_expected_field(FIELD_NAME, None, Some(Typed::String("string".to_string()))),
597            string_change.to_field(FIELD_NAME)
598        );
599    }
600
601    #[test]
602    fn string_invalid_0x00_bytes_sequence_change() {
603        let string_change = String::from('\u{0000}');
604
605        assert_eq!(
606            create_expected_field(FIELD_NAME, None, Some(Typed::String("".to_string()))),
607            string_change.to_field(FIELD_NAME)
608        );
609    }
610
611    #[test]
612    fn delta_string_change() {
613        let delta = DeltaString {
614            operation: Operation::Update,
615            ordinal: 0,
616            key: "change".to_string(),
617            old_value: String::from("string1"),
618            new_value: String::from("string2"),
619        };
620
621        assert_eq!(
622            create_expected_field(
623                FIELD_NAME,
624                Some(Typed::String("string1".to_string())),
625                Some(Typed::String("string2".to_string()))
626            ),
627            delta.to_field(FIELD_NAME)
628        );
629    }
630
631    #[test]
632    fn delta_string_invalid_0x00_bytes_sequence_change() {
633        let delta = DeltaString {
634            operation: Operation::Update,
635            ordinal: 0,
636            key: "change".to_string(),
637            old_value: String::from("string1"),
638            new_value: String::from('\u{0000}'),
639        };
640
641        assert_eq!(
642            create_expected_field(
643                FIELD_NAME,
644                Some(Typed::String("string1".to_string())),
645                Some(Typed::String("".to_string()))
646            ),
647            delta.to_field(FIELD_NAME)
648        );
649    }
650
651    #[test]
652    fn bytes_change() {
653        let bytes_change = Vec::from("bytes");
654        assert_eq!(
655            create_expected_field(FIELD_NAME, None, Some(Typed::Bytes("Ynl0ZXM=".to_string()))),
656            bytes_change.to_field(FIELD_NAME)
657        );
658    }
659
660    #[test]
661    fn delta_bytes_change() {
662        let delta = DeltaBytes {
663            operation: Operation::Update,
664            ordinal: 0,
665            key: "change".to_string(),
666            old_value: Vec::from("bytes1"),
667            new_value: Vec::from("bytes2"),
668        };
669
670        assert_eq!(
671            create_expected_field(
672                FIELD_NAME,
673                Some(Typed::Bytes("Ynl0ZXMx".to_string())),
674                Some(Typed::Bytes("Ynl0ZXMy".to_string()))
675            ),
676            delta.to_field(FIELD_NAME)
677        );
678    }
679
680    #[test]
681    fn vec_byte_array_change() {
682        let vec_byte_array_change: Vec<Vec<u8>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
683        assert_eq!(
684            create_expected_field(
685                FIELD_NAME,
686                None,
687                Some(Typed::Array(Array {
688                    value: vec![
689                        Value {
690                            typed: Some(Typed::Bytes("AQID".to_string()))
691                        },
692                        Value {
693                            typed: Some(Typed::Bytes("BAUG".to_string()))
694                        },
695                    ]
696                }))
697            ),
698            vec_byte_array_change.to_field(FIELD_NAME)
699        );
700    }
701
702    #[test]
703    fn delta_vec_byte_array_change() {
704        let delta = DeltaArray {
705            operation: Operation::Update,
706            ordinal: 0,
707            key: "change".to_string(),
708            old_value: vec![vec![1, 2, 3], vec![4, 5, 6]],
709            new_value: vec![vec![7, 8, 9], vec![10, 11, 12]],
710        };
711
712        assert_eq!(
713            create_expected_field(
714                FIELD_NAME,
715                Some(Typed::Array(Array {
716                    value: vec![
717                        Value {
718                            typed: Some(Typed::Bytes("AQID".to_string()))
719                        },
720                        Value {
721                            typed: Some(Typed::Bytes("BAUG".to_string()))
722                        },
723                    ]
724                })),
725                Some(Typed::Array(Array {
726                    value: vec![
727                        Value {
728                            typed: Some(Typed::Bytes("BwgJ".to_string()))
729                        },
730                        Value {
731                            typed: Some(Typed::Bytes("CgsM".to_string()))
732                        },
733                    ]
734                })),
735            ),
736            delta.to_field(FIELD_NAME)
737        );
738    }
739
740    #[test]
741    fn bool_change() {
742        let bool_change = true;
743        assert_eq!(
744            create_expected_field(FIELD_NAME, None, Some(Typed::Bool(true))),
745            bool_change.to_field(FIELD_NAME)
746        );
747    }
748
749    #[test]
750    fn delta_bool_change() {
751        let delta = DeltaBool {
752            operation: Operation::Update,
753            ordinal: 0,
754            key: "change".to_string(),
755            old_value: true,
756            new_value: false,
757        };
758
759        assert_eq!(
760            create_expected_field(
761                FIELD_NAME,
762                Some(Typed::Bool(true)),
763                Some(Typed::Bool(false)),
764            ),
765            delta.to_field(FIELD_NAME)
766        );
767    }
768
769    #[test]
770    fn vec_string_change() {
771        let vec_string_change: Vec<String> = vec![
772            String::from("string1"),
773            String::from("string2"),
774            String::from("string3"),
775        ];
776        assert_eq!(
777            create_expected_field(
778                FIELD_NAME,
779                None,
780                Some(Typed::Array(Array {
781                    value: vec![
782                        Value {
783                            typed: Some(Typed::String("string1".to_string()))
784                        },
785                        Value {
786                            typed: Some(Typed::String("string2".to_string()))
787                        },
788                        Value {
789                            typed: Some(Typed::String("string3".to_string()))
790                        },
791                    ]
792                }))
793            ),
794            vec_string_change.to_field(FIELD_NAME)
795        );
796    }
797
798    #[test]
799    fn vec_string_invalid_0x00_sequence_change() {
800        let vec_string_change: Vec<String> = vec![
801            String::from("string1"),
802            String::from("string2"),
803            String::from('\u{0000}'),
804        ];
805        assert_eq!(
806            create_expected_field(
807                FIELD_NAME,
808                None,
809                Some(Typed::Array(Array {
810                    value: vec![
811                        Value {
812                            typed: Some(Typed::String("string1".to_string()))
813                        },
814                        Value {
815                            typed: Some(Typed::String("string2".to_string()))
816                        },
817                        Value {
818                            typed: Some(Typed::String("".to_string()))
819                        },
820                    ]
821                }))
822            ),
823            vec_string_change.to_field(FIELD_NAME)
824        );
825    }
826
827    #[test]
828    fn delta_vec_string_change() {
829        let delta = DeltaArray {
830            operation: Operation::Update,
831            ordinal: 0,
832            key: "change".to_string(),
833            old_value: vec![
834                "string1".to_string(),
835                "string2".to_string(),
836                "string3".to_string(),
837            ],
838            new_value: vec![
839                "string1.1".to_string(),
840                "string2.1".to_string(),
841                "string3.1".to_string(),
842            ],
843        };
844
845        assert_eq!(
846            create_expected_field(
847                FIELD_NAME,
848                Some(Typed::Array(Array {
849                    value: vec![
850                        Value {
851                            typed: Some(Typed::String("string1".to_string()))
852                        },
853                        Value {
854                            typed: Some(Typed::String("string2".to_string()))
855                        },
856                        Value {
857                            typed: Some(Typed::String("string3".to_string()))
858                        },
859                    ]
860                })),
861                Some(Typed::Array(Array {
862                    value: vec![
863                        Value {
864                            typed: Some(Typed::String("string1.1".to_string()))
865                        },
866                        Value {
867                            typed: Some(Typed::String("string2.1".to_string()))
868                        },
869                        Value {
870                            typed: Some(Typed::String("string3.1".to_string()))
871                        },
872                    ]
873                })),
874            ),
875            delta.to_field(FIELD_NAME)
876        );
877    }
878
879    #[test]
880    fn delta_vec_string_invalid_0x00_sequence_change() {
881        let delta = DeltaArray {
882            operation: Operation::Update,
883            ordinal: 0,
884            key: "change".to_string(),
885            old_value: vec![
886                "string1".to_string(),
887                "string2".to_string(),
888                "string3".to_string(),
889            ],
890            new_value: vec![
891                "string1.1".to_string(),
892                String::from("string2.1"),
893                String::from('\u{0000}'),
894            ],
895        };
896
897        assert_eq!(
898            create_expected_field(
899                FIELD_NAME,
900                Some(Typed::Array(Array {
901                    value: vec![
902                        Value {
903                            typed: Some(Typed::String("string1".to_string()))
904                        },
905                        Value {
906                            typed: Some(Typed::String("string2".to_string()))
907                        },
908                        Value {
909                            typed: Some(Typed::String("string3".to_string()))
910                        },
911                    ]
912                })),
913                Some(Typed::Array(Array {
914                    value: vec![
915                        Value {
916                            typed: Some(Typed::String("string1.1".to_string()))
917                        },
918                        Value {
919                            typed: Some(Typed::String("string2.1".to_string()))
920                        },
921                        Value {
922                            typed: Some(Typed::String("".to_string()))
923                        },
924                    ]
925                })),
926            ),
927            delta.to_field(FIELD_NAME)
928        );
929    }
930
931    #[test]
932    fn vec_big_decimal_change() {
933        let vec_big_decimal_change: Vec<BigDecimal> = vec![
934            BigDecimal::from(1),
935            BigDecimal::from(2),
936            BigDecimal::from(3),
937        ];
938        assert_eq!(
939            create_expected_field(
940                FIELD_NAME,
941                None,
942                Some(Typed::Array(Array {
943                    value: vec![
944                        Value {
945                            typed: Some(Typed::Bigdecimal("1".to_string()))
946                        },
947                        Value {
948                            typed: Some(Typed::Bigdecimal("2".to_string()))
949                        },
950                        Value {
951                            typed: Some(Typed::Bigdecimal("3".to_string()))
952                        },
953                    ]
954                }))
955            ),
956            vec_big_decimal_change.to_field(FIELD_NAME)
957        );
958    }
959
960    #[test]
961    fn delta_vec_big_decimal_change() {
962        let delta = DeltaArray {
963            operation: Operation::Update,
964            ordinal: 0,
965            key: "change".to_string(),
966            old_value: vec![
967                BigDecimal::from(1),
968                BigDecimal::from(2),
969                BigDecimal::from(3),
970            ],
971            new_value: vec![
972                BigDecimal::from(11),
973                BigDecimal::from(22),
974                BigDecimal::from(33),
975            ],
976        };
977
978        assert_eq!(
979            create_expected_field(
980                FIELD_NAME,
981                Some(Typed::Array(Array {
982                    value: vec![
983                        Value {
984                            typed: Some(Typed::Bigdecimal("1".to_string()))
985                        },
986                        Value {
987                            typed: Some(Typed::Bigdecimal("2".to_string()))
988                        },
989                        Value {
990                            typed: Some(Typed::Bigdecimal("3".to_string()))
991                        },
992                    ]
993                })),
994                Some(Typed::Array(Array {
995                    value: vec![
996                        Value {
997                            typed: Some(Typed::Bigdecimal("11".to_string()))
998                        },
999                        Value {
1000                            typed: Some(Typed::Bigdecimal("22".to_string()))
1001                        },
1002                        Value {
1003                            typed: Some(Typed::Bigdecimal("33".to_string()))
1004                        },
1005                    ]
1006                })),
1007            ),
1008            delta.to_field(FIELD_NAME)
1009        );
1010    }
1011
1012    #[test]
1013    fn vec_big_int_change() {
1014        let vec_big_int_change: Vec<BigInt> =
1015            vec![BigInt::from(1), BigInt::from(2), BigInt::from(3)];
1016        assert_eq!(
1017            create_expected_field(
1018                FIELD_NAME,
1019                None,
1020                Some(Typed::Array(Array {
1021                    value: vec![
1022                        Value {
1023                            typed: Some(Typed::Bigint("1".to_string()))
1024                        },
1025                        Value {
1026                            typed: Some(Typed::Bigint("2".to_string()))
1027                        },
1028                        Value {
1029                            typed: Some(Typed::Bigint("3".to_string()))
1030                        },
1031                    ]
1032                }))
1033            ),
1034            vec_big_int_change.to_field(FIELD_NAME)
1035        );
1036    }
1037
1038    #[test]
1039    fn delta_vec_big_int_change() {
1040        let delta = DeltaArray {
1041            operation: Operation::Update,
1042            ordinal: 0,
1043            key: "change".to_string(),
1044            old_value: vec![BigInt::from(1), BigInt::from(2), BigInt::from(3)],
1045            new_value: vec![BigInt::from(11), BigInt::from(22), BigInt::from(33)],
1046        };
1047
1048        assert_eq!(
1049            create_expected_field(
1050                FIELD_NAME,
1051                Some(Typed::Array(Array {
1052                    value: vec![
1053                        Value {
1054                            typed: Some(Typed::Bigint("1".to_string()))
1055                        },
1056                        Value {
1057                            typed: Some(Typed::Bigint("2".to_string()))
1058                        },
1059                        Value {
1060                            typed: Some(Typed::Bigint("3".to_string()))
1061                        },
1062                    ]
1063                })),
1064                Some(Typed::Array(Array {
1065                    value: vec![
1066                        Value {
1067                            typed: Some(Typed::Bigint("11".to_string()))
1068                        },
1069                        Value {
1070                            typed: Some(Typed::Bigint("22".to_string()))
1071                        },
1072                        Value {
1073                            typed: Some(Typed::Bigint("33".to_string()))
1074                        },
1075                    ]
1076                })),
1077            ),
1078            delta.to_field(FIELD_NAME)
1079        );
1080    }
1081
1082    fn create_expected_field<N: AsRef<str>>(
1083        name: N,
1084        old_value: Option<Typed>,
1085        new_value: Option<Typed>,
1086    ) -> Field {
1087        let mut field = Field {
1088            name: name.as_ref().to_string(),
1089            ..Default::default()
1090        };
1091        #[allow(deprecated)]
1092        if old_value.is_some() {
1093            field.old_value = Some(Value { typed: old_value })
1094        }
1095        if new_value.is_some() {
1096            field.new_value = Some(Value { typed: new_value })
1097        }
1098        field
1099    }
1100}