1use crate::utils::{operation::{Operation, Params}, transaction::Transaction};
27
28use asn1::{Asn1Read, Asn1Readable, Asn1Write, ParseError};
29use std::collections::BTreeMap;
30
31#[derive(Asn1Read, Asn1Write, Debug, Clone)]
32pub enum Choice<'a> {
33 #[explicit(0)]
34 NULL(()),
35 #[explicit(1)]
36 OCTETSTRING(&'a [u8]),
37 #[explicit(2)]
38 UTF8STRING(asn1::Utf8String<'a>),
39 #[explicit(3)]
40 INTEGER(i64),
41 #[explicit(4)]
42 DICT(asn1::Sequence<'a>),
43 #[explicit(5)]
44 ARRAY(asn1::Sequence<'a>),
45 #[explicit(6)]
46 BIGINTEGER(asn1::BigInt<'a>),
47}
48
49#[derive(Debug)]
50pub enum GTVType {
51 Null = 0,
52 ByteArray = 1,
53 String = 2,
54 Integer = 3,
55 Dict = 4,
56 Array = 5,
57 BigInteger = 6,
58}
59
60pub trait GTVParams: Clone {
61 fn to_writer(&self, writer: &mut asn1::Writer) -> asn1::WriteResult;
62}
63
64pub fn write_explicit_element<T: asn1::Asn1Writable>(writer: &mut asn1::Writer, val: &T, tag: u32)
65 -> asn1::WriteResult {
66 let tag = asn1::explicit_tag(tag);
67 writer.write_tlv(tag, |dest| asn1::Writer::new(dest).write_element(val))
68}
69
70#[allow(unused_assignments)]
71impl<'a> GTVParams for Params {
72 fn to_writer(&self, writer: &mut asn1::Writer) -> asn1::WriteResult {
73 if let Params::Array(val) = self {
74 write_explicit_element(writer,
75 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
76 for v in val {
77 v.to_writer(writer)?;
78 }
79 Ok(())
80 }),
81 5,
82 )?;
83 Ok(())
84 } else if let Params::Dict(val) = self {
85 write_explicit_element(writer,
86 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
87 for v in val {
88 writer.write_element(&asn1::SequenceWriter::new(
89 &|writer: &mut asn1::Writer| {
90 writer.write_element(&asn1::Utf8String::new(v.0))?;
91 v.1.to_writer(writer)?;
92 Ok(())
93 },
94 ))?;
95 }
96
97 Ok(())
98 }),
99 4,
100 )?;
101 Ok(())
102 } else {
103 let mut decimal_to_string = String::new();
104 let mut bigint_to_vec_u8: Vec<u8> = Vec::new();
105
106 let gtv_choice = match self {
107 Params::Integer(val) => Choice::INTEGER(*val),
108 Params::Boolean(val) => Choice::INTEGER(*val as i64),
109 Params::Decimal(val) => {
110 decimal_to_string = val.to_string();
111 Choice::UTF8STRING(asn1::Utf8String::new(decimal_to_string.as_str()))
112 }
113 Params::Text(val) => Choice::UTF8STRING(asn1::Utf8String::new(val)),
114 Params::ByteArray(val) => Choice::OCTETSTRING(&val),
115 Params::BigInteger(val) => {
116 let (sign, bytes) = val.to_bytes_be();
117
118 if sign == num_bigint::Sign::Minus {
119 let bytes1 = val.to_signed_bytes_be();
120 bigint_to_vec_u8 = bytes1;
121 } else {
122 bigint_to_vec_u8 = bytes;
123 }
124
125 Choice::BIGINTEGER(asn1::BigInt::new(bigint_to_vec_u8.as_slice()).unwrap())
126 }
127 _ => Choice::NULL(())
128 };
129
130 writer.write_element(>v_choice)?;
131 Ok(())
132 }
133 }
134}
135
136pub fn encode_tx<'a>(tx: &Transaction<'a>) -> Vec<u8> {
146 asn1::write(|writer| {
147 write_explicit_element(writer,
148 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
149
150 write_explicit_element(writer,
151 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
152
153 writer.write_element(&Choice::OCTETSTRING(
155 &tx.blockchain_rid))?;
156
157 write_explicit_element(writer,
159 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
160
161 if let Some(operations) = &tx.operations {
162 for operation in operations {
163 encode_tx_body(writer, operation)?;
164 }
165 }
166
167 Ok(())
168 }), 5)?;
169
170
171 write_explicit_element(writer,
173 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
174
175 if let Some(signers) = &tx.signers {
176 for sig in signers {
177 writer.write_element(&Choice::OCTETSTRING(&sig))?;
178 }
179 }
180
181 Ok(())
182 }), 5)?;
183
184 Ok(())
185 }), 5)?;
186
187 write_explicit_element(writer,
189 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
190
191 if let Some(signatures) = &tx.signatures {
192 for sig in signatures {
193 writer.write_element(&Choice::OCTETSTRING(&sig))?;
194 }
195 }
196
197 Ok(())
198 }), 5)?;
199
200 Ok(())
201 }),
202 5, )?;
203 Ok(())
204 }).unwrap()
205}
206
207pub fn encode<'a>(
218 query_type: &str,
219 query_args: Option<&'a mut Vec<(&str, Params)>>,
220) -> Vec<u8> {
221 asn1::write(|writer| {
222 write_explicit_element(writer,
223 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
224 writer.write_element(&Choice::UTF8STRING(asn1::Utf8String::new(query_type)))?;
225 encode_body(writer, &query_args)?;
226 Ok(())
227 }),
228 5,
229 )?;
230 Ok(())
231 })
232 .unwrap()
233}
234
235fn encode_tx_body<'a>(writer: &mut asn1::Writer, operation: &Operation<'a>) -> asn1::WriteResult {
246 write_explicit_element(writer, &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
247 write_explicit_element(writer,&asn1::Utf8String::new(&operation.operation_name.unwrap()), 2)?;
249 write_explicit_element(writer, &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
251 if let Some(operation_args) = &operation.list {
252 for arg in operation_args {
253 arg.to_writer(writer)?;
254 }
255 } else if let Some(operation_args) = &operation.dict {
256 write_explicit_element(writer, &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
257 for (_key, val) in operation_args {
258 val.to_writer(writer)?;
259 }
260 Ok(())
261 }), 5)?;
262 }
263 Ok(())
264 }), 5)?;
265 Ok(())
266 }), 5)?;
267 Ok(())
268}
269
270fn encode_body<'a>(writer: &mut asn1::Writer,
281 query_args: &Option<&'a mut Vec<(&str, Params)>>)
282 -> asn1::WriteResult {
283 write_explicit_element(writer,
284 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
285 if let Some(q_args) = &query_args {
286 let q_args_as_slice = q_args.iter().as_slice();
287 for (q_type, q_args) in q_args_as_slice {
288 writer.write_element(&asn1::SequenceWriter::new(
289 &|writer: &mut asn1::Writer| {
290 writer.write_element(&asn1::Utf8String::new(&q_type))?;
291 q_args.to_writer(writer)?;
292 Ok(())
293 },
294 ))?;
295 }
296 }
297 Ok(())
298 }),
299 4,
300 )?;
301 Ok(())
302}
303
304fn decode_simple(choice: Choice) -> Params {
314 match choice {
315 Choice::INTEGER(val) =>
316 Params::Integer(val),
317 Choice::BIGINTEGER(val) => {
318 let result = if val.is_negative() {
319 num_bigint::BigInt::from_signed_bytes_be(val.as_bytes().try_into().unwrap())
320 } else {
321 num_bigint::BigInt::from_bytes_be(num_bigint::Sign::Plus, val.as_bytes().try_into().unwrap())
322 };
323 Params::BigInteger(result)
324 },
325 Choice::OCTETSTRING(val) =>
326 Params::ByteArray(val.to_vec()),
327 Choice::UTF8STRING(val) =>
328 Params::Text(val.as_str().to_string()),
329 _ =>
330 Params::Null
331 }
332}
333
334fn decode_sequence_array<'a>(parser: &mut asn1::Parser<'a>, vec_array: &mut Vec<Params>) {
341 while let Ok(val) = Choice::parse(parser) {
342 let op_val = match val {
343 Choice::ARRAY(seq) => {
344 let res: Result<Params, ParseError> = seq.parse(|parser| {
345 let mut vect_array_new: Vec<Params> = Vec::new();
346 decode_sequence_array(parser, &mut vect_array_new);
347 Ok(Params::Array(vect_array_new))
348 });
349 res.unwrap()
350 }
351 Choice::DICT(seq) => {
352 let res: Result<Params, ParseError> = seq.parse(|parser| {
353 let mut btree_map_new: BTreeMap<String, Params> = BTreeMap::new();
354 decode_sequence_dict(parser, &mut btree_map_new);
355 Ok(Params::Dict(btree_map_new))
356 });
357 res.unwrap()
358 }
359 _ =>
360 decode_simple(val)
361 };
362 vec_array.push(op_val);
363 }
364}
365
366fn decode_sequence_dict<'a>(parser: &mut asn1::Parser<'a>, btreemap: &mut BTreeMap<String, Params>) {
373 loop {
374 let seq = parser.read_element::<asn1::Sequence>();
375 if let Err(_) = seq {
376 break;
377 }
378 let res: Result<(&'a str, Params), ParseError> = seq.unwrap().parse(|parser| {
379 let key = parser.read_element::<asn1::Utf8String>()?;
380 let val = Choice::parse(parser).unwrap();
381
382 let op_val = match val {
383 Choice::DICT(seq) => {
384 let res: Result<Params, ParseError> = seq.parse(|parser| {
385 let mut btree_map_new: BTreeMap<String, Params> = BTreeMap::new();
386 decode_sequence_dict(parser, &mut btree_map_new);
387 Ok(Params::Dict(btree_map_new))
388 });
389 res.unwrap()
390 }
391 Choice::ARRAY(seq) => {
392 let res: Result<Params, ParseError> = seq.parse(|parser| {
393 let mut vect_array_new: Vec<Params> = Vec::new();
394 decode_sequence_array(parser, &mut vect_array_new);
395 Ok(Params::Array(vect_array_new))
396 });
397 res.unwrap()
398 },
399 _ =>
400 decode_simple(val)
401 };
402
403 Ok((key.as_str(), op_val))
404 });
405
406 let res: (&'a str, Params) = res.unwrap();
407
408 btreemap.insert(res.0.to_string(), res.1);
409 }
410}
411
412pub fn decode<'a>(data: &'a [u8]) -> Result<Params, ParseError> {
422 let tag = asn1::Tag::from_bytes(data).unwrap();
423 let tag_num = tag.0.as_u8().unwrap() & 0x1f;
424
425 if vec![0, 1, 2, 3, 6].contains(&tag_num) {
426 asn1::parse(data, |d| {
427 let res_choice = Choice::parse(d);
428 match res_choice {
429 Ok(val) => Ok(decode_simple(val)),
430 Err(error) => Err(error),
431 }
432 })
433 } else {
434 if tag_num == 4 {
435 let result = asn1::parse_single::<asn1::Explicit<asn1::Sequence, 4>>(data).unwrap();
436 result.into_inner().parse(|parser| {
437 let mut btree_map_new: BTreeMap<String, Params> = BTreeMap::new();
438 decode_sequence_dict(parser, &mut btree_map_new);
439 Ok(Params::Dict(btree_map_new))
440 })
441 } else if tag_num == 5 {
442 let result = asn1::parse_single::<asn1::Explicit<asn1::Sequence, 5>>(data).unwrap();
443 result.into_inner().parse(|parser|{
444 let mut vect_array_new: Vec<Params> = Vec::new();
445 decode_sequence_array(parser, &mut vect_array_new);
446 Ok(Params::Array(vect_array_new))
447 })
448 } else {
449 Ok(Params::Null)
450 }
451 }
452}
453
454pub fn decode_tx<'a>(data: &'a [u8]) -> Result<Params, ParseError> {
464 decode(data)
465}
466
467pub fn encode_value(value: &Params) -> Vec<u8> {
477 asn1::write(|writer| {
478 value.to_writer(writer)?;
479 Ok(())
480 }).unwrap()
481}
482
483pub fn encode_value_hex_encode(value: &Params) -> String {
493 hex::encode(encode_value(value))
494}
495
496pub fn to_draw_gtx<'a>(tx: &'a Transaction<'a>) -> Params {
506 let mut signers: Vec<Params> = vec![];
507 let mut operations:Vec<Params> = vec![];
508
509 if let Some(raw_signers) = &tx.signers {
510 for signer in raw_signers {
511 signers.push(Params::ByteArray(signer.to_vec()));
512 }
513 }
514
515 for op in &tx.operations.clone().unwrap() {
516 let mut op_args: Vec<Params> = vec![];
517
518 if let Some(op_list) = &op.list {
519 for arg in op_list {
520 op_args.push(arg.clone());
521 }
522 } else if let Some(op_dict) = &op.dict {
523 for (_key, value) in op_dict {
524 op_args.push(value.clone());
525 }
526 }
527
528 operations.push(Params::Array(vec![
529 Params::Text(op.operation_name.unwrap().to_string()),
530 Params::Array(op_args)
531 ]));
532 }
533
534 Params::Array(vec![
535 Params::ByteArray(tx.blockchain_rid.to_vec()),
536 Params::Array(operations),
537 Params::Array(signers)
538 ])
539}
540
541#[allow(dead_code)]
542fn assert_roundtrips<'a>(
549 query_args: Option<&'a mut Vec<(&str, Params)>>,
550 expected_value: &str) {
551 let result = asn1::write(|writer| {
552 encode_body(writer, &query_args)?;
553 Ok(())
554 });
555 assert_eq!(hex::encode(result.unwrap()), expected_value);
556}
557
558#[allow(dead_code)]
559fn assert_roundtrips_value<'a>(
567 value: &Params,
568 expected_decode: &Params,
569 expected_value: &str) {
570 let encode_result = encode_value(&value);
571 assert_eq!(expected_value, hex::encode(encode_result.clone()));
572
573 let decode_result = decode(&encode_result).unwrap();
574 assert_eq!(expected_decode, &decode_result);
575}
576
577#[test]
578fn gtv_encode_value_null() {
579 assert_roundtrips_value(&Params::Null, &Params::Null, "a0020500")
580}
581
582#[test]
583fn gtv_encode_value_boolean() {
584 assert_roundtrips_value(&Params::Boolean(true), &Params::Integer(1), "a303020101");
585 assert_roundtrips_value(&Params::Boolean(false), &Params::Integer(0),"a303020100")
586}
587
588#[test]
589fn gtv_encode_value_integer() {
590 assert_roundtrips_value(&Params::Integer(999), &Params::Integer(999), "a304020203e7")
591}
592
593#[test]
594fn gtv_encode_value_decimal() {
595 use std::str::FromStr;
596 assert_roundtrips_value(&Params::Decimal(bigdecimal::BigDecimal::from_str("999.999").unwrap()), &Params::Text("999.999".to_string()), "a2090c073939392e393939")
597}
598
599#[test]
600fn gtv_encode_value_text() {
601 assert_roundtrips_value(&Params::Text("hello!".to_string()), &Params::Text("hello!".to_string()), "a2080c0668656c6c6f21")
602}
603
604#[test]
605fn gtv_encode_value_bytearray() {
606 assert_roundtrips_value(&Params::ByteArray(b"123456789".to_vec()), &Params::ByteArray(b"123456789".to_vec()), "a10b0409313233343536373839")
607}
608
609#[test]
610fn gtv_encode_value_array() {
611 let array = Params::Array(vec![
612 Params::Text("foo1".to_string()),
613 Params::Text("foo2".to_string()),
614 ]);
615 assert_roundtrips_value(&array, &array, "a5123010a2060c04666f6f31a2060c04666f6f32")
616}
617
618#[test]
619fn gtv_encode_value_dict() {
620 use std::collections::BTreeMap;
621 let mut data: BTreeMap<String, Params> = BTreeMap::new();
622 let mut data1: BTreeMap<String, Params> = BTreeMap::new();
623 let mut data2: BTreeMap<String, Params> = BTreeMap::new();
624
625 data2.insert("foo1_1_1".to_string(), Params::Integer(1000));
626
627 data1.insert("foo1_1".to_string(), Params::Dict(data2));
628 data1.insert("foo1_2".to_string(), Params::Text("hello!".to_string()));
629
630 data.insert("foo".to_string(), Params::Text("bar".to_string()));
631 data.insert("foo1".to_string(), Params::Dict(data1));
632
633 let dict = Params::Dict(data);
634 assert_roundtrips_value(&dict, &dict, "a450304e300c0c03666f6fa2050c03626172303e0c04666f6f31a4363034301e0c06666f6f315f31a414301230100c08666f6f315f315f31a304020203e830120c06666f6f315f32a2080c0668656c6c6f21")
635}
636
637#[test]
638fn gtv_encode_value_big_integer() {
639 use std::str::FromStr;
640
641 let max_i128: i128 = i128::MAX;
642 let data = num_bigint::BigInt::from_str(max_i128.to_string().as_str()).unwrap();
643 assert_roundtrips_value(&Params::BigInteger(data.clone()), &Params::BigInteger(data), "a61202107fffffffffffffffffffffffffffffff");
644}
645
646#[test]
647fn gtv_test_sequence_with_empty() {
648 assert_roundtrips(None, "a4023000");
649}
650
651#[test]
652fn gtv_test_sequence_with_boolean() {
653 assert_roundtrips(Some(&mut vec![("foo", Params::Boolean(true))]),
654 "a40e300c300a0c03666f6fa303020101");
655}
656
657#[test]
658fn gtv_test_sequence_with_string() {
659 assert_roundtrips(Some(&mut vec![("foo", Params::Text("bar".to_string()))]),
660 "a410300e300c0c03666f6fa2050c03626172");
661}
662
663#[test]
664fn gtv_test_sequence_with_octet_string() {
665 assert_roundtrips(Some(&mut vec![("foo", Params::ByteArray("bar".as_bytes().to_vec()))]),
666 "a410300e300c0c03666f6fa1050403626172");
667}
668
669#[test]
670fn gtv_test_sequence_with_number() {
671 assert_roundtrips(Some(&mut vec![("foo", Params::Integer(9999))]),
672 "a40f300d300b0c03666f6fa3040202270f");
673}
674
675#[test]
676fn gtv_test_sequence_with_negative_number() {
677 assert_roundtrips(Some(&mut vec![("foo", Params::Integer(-9999))]),
678 "a40f300d300b0c03666f6fa3040202d8f1");
679}
680
681#[test]
682fn gtv_test_sequence_with_decimal() {
683 use std::str::FromStr;
684 assert_roundtrips(Some(&mut vec![("foo", Params::Decimal(bigdecimal::BigDecimal::from_str("99.99").unwrap()))]),
685 "a4123010300e0c03666f6fa2070c0539392e3939");
686}
687
688#[test]
689fn gtv_test_sequence_with_negative_decimal() {
690 use std::str::FromStr;
691 assert_roundtrips(Some(&mut vec![("foo", Params::Decimal(bigdecimal::BigDecimal::from_str("-99.99").unwrap()))]),
692 "a4133011300f0c03666f6fa2080c062d39392e3939");
693}
694
695#[test]
696fn gtv_test_sequence_with_json() {
697 let data = serde_json::json!({
698 "foo": "bar",
699 "bar": 9,
700 "foo": 9.00
701 }).to_string();
702 assert_roundtrips(Some(&mut vec![("foo", Params::Text(data))]),
703 "a420301e301c0c03666f6fa2150c137b22626172223a392c22666f6f223a392e307d");
704}
705
706#[test]
707fn gtv_test_sequence_with_big_integer() {
708 use std::str::FromStr;
709
710 let max_i128: i128 = i128::MAX;
711 let data = num_bigint::BigInt::from_str(max_i128.to_string().as_str()).unwrap();
712 assert_roundtrips(Some(&mut vec![("foo", Params::BigInteger(data))]),
713 "a41d301b30190c03666f6fa61202107fffffffffffffffffffffffffffffff");
714}
715
716#[test]
717fn gtv_test_sequence_with_negative_big_integer() {
718 use std::str::FromStr;
719
720 let min_i128: i128 = i128::MIN;
721 let data = num_bigint::BigInt::from_str(min_i128.to_string().as_str()).unwrap();
722 assert_roundtrips(Some(&mut vec![("foo", Params::BigInteger(data))]),
723 "a41d301b30190c03666f6fa612021080000000000000000000000000000000");
724
725 let h_data = "a41d301b30190c03666f6fa6120210ff123b1a8199614ad13ab29a33fba0eb";
726
727 let data = num_bigint::BigInt::from_str("-1234567890123456789123456789123456789").unwrap();
728 assert_roundtrips(Some(&mut vec![("foo", Params::BigInteger(data.clone()))]),
729 h_data);
730
731 let hex_decode_data = hex::decode(h_data).unwrap();
732 let result = decode(&hex_decode_data).unwrap();
733
734 if let Params::Dict(dict) = result {
735 let bi: num_bigint::BigInt = dict["foo"].clone().into();
736 assert_eq!(data, bi);
737 }
738}
739
740#[test]
741fn gtv_test_sequence_with_array() {
742 let data = &mut vec![(
743 "foo",
744 Params::Array(vec![
745 Params::Text("bar1".to_string()),
746 Params::Text("bar2".to_string()),
747 ]),
748 )];
749 assert_roundtrips(Some(data),
750 "a41d301b30190c03666f6fa5123010a2060c0462617231a2060c0462617232");
751}
752
753#[test]
754fn gtv_test_sequence_with_dict() {
755 use std::collections::BTreeMap;
756
757 let mut params: BTreeMap<String, Params> = BTreeMap::new();
758 params.insert("foo".to_string(), Params::Text("bar".to_string()));
759 params.insert("foo1".to_string(), Params::Text("bar1".to_string()));
760
761 let data = &mut vec![("foo", Params::Dict(params))];
762
763 assert_roundtrips(Some(data),
764 "a42b302930270c03666f6fa420301e300c0c03666f6fa2050c03626172300e0c04666f6f31a2060c0462617231");
765}
766
767#[test]
768fn gtv_test_sequence_with_nested_dict() {
769 use std::collections::BTreeMap;
770
771 let mut dict1: BTreeMap<String, Params> = BTreeMap::new();
772 let mut dict2: BTreeMap<String, Params> = BTreeMap::new();
773 let dict3: BTreeMap<String, Params> = BTreeMap::new();
774
775 dict1.insert("dict1_foo".to_string(), Params::Text("dict1_bar".to_string()));
776
777 dict2.insert("dict2_foo".to_string(), Params::Text("dict2_bar".to_string()));
778 dict2.insert("dict2_foo1".to_string(), Params::Text("dict2_bar1".to_string()));
779
780 dict2.insert("dict3_empty_data".to_string(), Params::Dict(dict3));
781
782 dict1.insert("dict2_data".to_string(), Params::Dict(dict2));
783
784 let data = &mut vec![("foo", Params::Dict(dict1))];
785
786 assert_roundtrips(Some(data),
787 "a481893081863081830c03666f6fa47c307a30180c0964696374315f666f6fa20b0c0964696374315f626172305e0c0a64696374325f64617461a450304e30180c0964696374325f666f6fa20b0c0964696374325f626172301a0c0a64696374325f666f6f31a20c0c0a64696374325f6261723130160c1064696374335f656d7074795f64617461a4023000");
788}
789
790#[test]
791fn gtv_test_sequence_with_nested_dict_array() {
792 use std::collections::BTreeMap;
793
794 let mut dict1: BTreeMap<String, Params> = BTreeMap::new();
795 let mut dict2: BTreeMap<String, Params> = BTreeMap::new();
796 let mut dict3: BTreeMap<String, Params> = BTreeMap::new();
797
798 dict2.insert("dict2_foo".to_string(), Params::Text("dict2_bar".to_string()));
799 dict3.insert("dict3_foo".to_string(), Params::Text("dict3_bar".to_string()));
800
801 let array1 = vec![
802 Params::Dict(dict2), Params::Dict(dict3)];
803
804 dict1.insert("array1".to_string(), Params::Array(array1));
805
806 let data = &mut vec![("foo", Params::Dict(dict1))];
807
808 assert_roundtrips(Some(data),
809 "a457305530530c03666f6fa44c304a30480c06617272617931a53e303ca41c301a30180c0964696374325f666f6fa20b0c0964696374325f626172a41c301a30180c0964696374335f666f6fa20b0c0964696374335f626172");
810}
811
812#[allow(dead_code)]
813fn assert_roundtrips_simple(op: Params, expected_value: &str) {
820 let result = asn1::write(|writer| {
821 op.to_writer(writer)?;
822 Ok(())
823 });
824 assert_eq!(hex::encode(result.unwrap()), expected_value);
825}
826
827#[test]
828fn gtv_test_simple_null() {
829 assert_roundtrips_simple(Params::Null, "a0020500");
830}
831
832#[test]
833fn gtv_test_simple_boolean() {
834 assert_roundtrips_simple(Params::Boolean(true), "a303020101");
835 assert_roundtrips_simple(Params::Boolean(false), "a303020100");
836}
837
838#[test]
839fn gtv_test_simple_integer() {
840 assert_roundtrips_simple(Params::Integer(99999), "a305020301869f");
841}
842
843#[test]
844fn gtv_test_simple_big_integer() {
845 assert_roundtrips_simple(Params::BigInteger(num_bigint::BigInt::from(1234567890123456789 as i128)), "a60a0208112210f47de98115");
846}
847
848#[test]
849fn gtv_test_simple_decimal() {
850 use std::str::FromStr;
851 assert_roundtrips_simple(Params::Decimal(bigdecimal::BigDecimal::from_str("99.999").unwrap()), "a2080c0639392e393939");
852}
853
854#[test]
855fn gtv_test_simple_string() {
856 assert_roundtrips_simple(Params::Text("abcABC123".to_string()), "a20b0c09616263414243313233");
857 assert_roundtrips_simple(Params::Text("utf-8 unicode Trái Tim Ngục Tù ...!@#$%^&*()".to_string()), "a2320c307574662d3820756e69636f6465205472c3a1692054696d204e67e1bba5632054c3b9202e2e2e21402324255e262a2829");
858}
859
860#[test]
861fn gtv_test_simple_byte_array() {
862 assert_roundtrips_simple(Params::ByteArray(b"123456abcedf".to_vec()), "a10e040c313233343536616263656466");
863}
864
865#[test]
866fn gtv_test_simple_array() {
867 assert_roundtrips_simple(Params::Array(vec![
868 Params::Text("foo".to_string()), Params::Integer(1)
869 ]), "a50e300ca2050c03666f6fa303020101");
870}
871
872#[test]
873fn gtv_test_simple_dict() {
874 use std::collections::BTreeMap;
875 let mut data: BTreeMap<String, Params> = BTreeMap::new();
876 data.insert("foo".to_string(), Params::Text("bar".to_string()));
877 assert_roundtrips_simple(Params::Dict(data), "a410300e300c0c03666f6fa2050c03626172");
878}
879
880#[allow(dead_code)]
881fn assert_roundtrips_simple_decode(data: &str, expected_value: Params) {
888 let hex_decode_data = hex::decode(data).unwrap();
889 let result = decode(&hex_decode_data).unwrap();
890 assert_eq!(result, expected_value);
891}
892
893#[test]
894fn gtv_test_simple_null_decode() {
895 assert_roundtrips_simple_decode("a0020500", Params::Null);
896}
897
898#[test]
899fn gtv_test_simple_big_integer_decode() {
900 assert_roundtrips_simple_decode("a60a0208112210f47de98115",
901 Params::BigInteger(num_bigint::BigInt::from(1234567890123456789 as i128)));
902}
903
904#[test]
905fn gtv_test_simple_integer_decode() {
906 assert_roundtrips_simple_decode("a305020301869f", Params::Integer(99999));
907}
908
909#[test]
910fn gtv_test_simple_decimal_decode() {
911 assert_roundtrips_simple_decode("a2080c0639392e393939", Params::Text("99.999".to_string()));
912}
913
914#[test]
915fn gtv_test_simple_string_decode() {
916 assert_roundtrips_simple_decode("a2320c307574662d3820756e69636f6465205472c3a1692054696d204e67e1bba5632054c3b9202e2e2e21402324255e262a2829",
917 Params::Text("utf-8 unicode Trái Tim Ngục Tù ...!@#$%^&*()".to_string()))
918}
919
920#[test]
921fn gtv_test_simple_bytearray_with_hex_decode() {
922 assert_roundtrips_simple_decode("a53b3039a5373035a12304210373599a61cc6b3bc02a78c34313e1737ae9cfd56b9bb24360b437d469efdf3b15a20e0c0c73616d706c655f76616c7565",
923 Params::Array(vec![
924 Params::Array(vec![
925 Params::ByteArray(hex::decode("0373599A61CC6B3BC02A78C34313E1737AE9CFD56B9BB24360B437D469EFDF3B15").unwrap()),
926 Params::Text("sample_value".to_string())
927 ])
928 ]))
929}
930
931#[test]
932fn gtv_test_sequence_simple_array_decode() {
933 let data = Params::Array(vec![
934 Params::Text("foo".to_string()), Params::Integer(1),
935 Params::Text("bar".to_string()), Params::Integer(2),
936 Params::Array(vec![]),
937 Params::Text("ca".to_string()), Params::Integer(3),
938 Params::Array(vec![
939 Params::Integer(1111),
940 Params::Array(vec![
941 Params::Integer(2222),
942 Params::Integer(3333),
943 ])
944 ]),
945 ]);
946
947 let result = asn1::write(|writer| {
948 data.to_writer(writer)?; Ok(()) }).unwrap();
949
950 assert_eq!(data, decode(result.as_slice()).unwrap());
951}
952
953#[test]
954fn gtv_test_sequence_simple_dict_decode() {
955 let mut data_btreemap: BTreeMap<String, Params> = BTreeMap::new();
956
957 data_btreemap.insert("foo".to_string(), Params::Text("bar".to_string()));
958 data_btreemap.insert("status".to_string(), Params::ByteArray("OK".as_bytes().to_vec()));
959
960 let data = Params::Dict(data_btreemap);
961
962 let result = asn1::write(|writer| {
963 data.to_writer(writer)?; Ok(()) }).unwrap();
964
965 assert_eq!(data, decode(result.as_slice()).unwrap());
966}
967
968#[test]
969fn gtv_test_sequence_complex_mix_dict_array_decode() {
970 use std::collections::BTreeMap;
971 let mut data_btreemap: BTreeMap<String, Params> = BTreeMap::new();
972 let mut dict_in: BTreeMap<String, Params> = BTreeMap::new();
973
974 dict_in.insert("foo".to_string(), Params::Text("bar".to_string()));
975
976 data_btreemap.insert("status".to_string(), Params::Text("dict_bar".to_string()));
977 data_btreemap.insert("command".to_string(), Params::Text("dict_bar2".to_string()));
978 data_btreemap.insert("state".to_string(), Params::Integer(123));
979 data_btreemap.insert("dict".to_string(), Params::Dict(dict_in));
980 data_btreemap.insert("array".to_string(), Params::Array(vec![
981 Params::Text("test array".to_string()),
982 Params::BigInteger(num_bigint::BigInt::from(123456 as i128)),
983 Params::Array(vec![
984 Params::Text("test array 2".to_string())
985 ])
986 ]));
987
988 let data = Params::Dict(data_btreemap);
989
990 let result = asn1::write(|writer| {
991 data.to_writer(writer)?; Ok(()) }).unwrap();
992
993 assert_eq!(data, decode(result.as_slice()).unwrap());
994}