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
70impl GTVParams for Params {
71 fn to_writer(&self, writer: &mut asn1::Writer) -> asn1::WriteResult {
72 match self {
73 Params::Array(val) => {
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 }
84 Params::Dict(val) => {
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 Ok(())
97 }),
98 4,
99 )
100 }
101 Params::Integer(val) => writer.write_element(&Choice::INTEGER(*val)),
102 Params::Boolean(val) => writer.write_element(&Choice::INTEGER(*val as i64)),
103 Params::Decimal(val) => {
104 let decimal_to_string = val.to_string();
105 writer.write_element(&Choice::UTF8STRING(asn1::Utf8String::new(&decimal_to_string)))
106 }
107 Params::Text(val) => writer.write_element(&Choice::UTF8STRING(asn1::Utf8String::new(val))),
108 Params::ByteArray(val) => writer.write_element(&Choice::OCTETSTRING(val)),
109 Params::BigInteger(val) => {
110 let (sign, bytes) = val.to_bytes_be();
111 let bigint_to_vec_u8 = if sign == num_bigint::Sign::Minus {
112 val.to_signed_bytes_be()
113 } else {
114 bytes
115 };
116 writer.write_element(&Choice::BIGINTEGER(asn1::BigInt::new(&bigint_to_vec_u8).unwrap()))
117 }
118 _ => writer.write_element(&Choice::NULL(())),
119 }
120 }
121}
122
123pub fn encode_tx(tx: &Transaction) -> Vec<u8> {
133 asn1::write(|writer| {
134 write_explicit_element(writer,
135 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
136
137 write_explicit_element(writer,
138 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
139
140 writer.write_element(&Choice::OCTETSTRING(
142 &tx.blockchain_rid))?;
143
144 write_explicit_element(writer,
146 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
147
148 if let Some(operations) = &tx.operations {
149 for operation in operations {
150 encode_tx_body(writer, operation)?;
151 }
152 }
153
154 Ok(())
155 }), 5)?;
156
157
158 write_explicit_element(writer,
160 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
161
162 if let Some(signers) = &tx.signers {
163 for sig in signers {
164 writer.write_element(&Choice::OCTETSTRING(sig))?;
165 }
166 }
167
168 Ok(())
169 }), 5)?;
170
171 Ok(())
172 }), 5)?;
173
174 write_explicit_element(writer,
176 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
177
178 if let Some(signatures) = &tx.signatures {
179 for sig in signatures {
180 writer.write_element(&Choice::OCTETSTRING(sig))?;
181 }
182 }
183
184 Ok(())
185 }), 5)?;
186
187 Ok(())
188 }),
189 5, )?;
190 Ok(())
191 }).unwrap()
192}
193
194pub fn encode(
205 query_type: &str,
206 query_args: Option<&mut Vec<(&str, Params)>>,
207) -> Vec<u8> {
208 asn1::write(|writer| {
209 write_explicit_element(writer,
210 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
211 writer.write_element(&Choice::UTF8STRING(asn1::Utf8String::new(query_type)))?;
212 encode_body(writer, &query_args)?;
213 Ok(())
214 }),
215 5,
216 )?;
217 Ok(())
218 })
219 .unwrap()
220}
221
222fn encode_tx_body(writer: &mut asn1::Writer, operation: &Operation) -> asn1::WriteResult {
233 write_explicit_element(writer, &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
234 write_explicit_element(writer,&asn1::Utf8String::new(operation.operation_name.as_ref().unwrap()), 2)?;
236 write_explicit_element(writer, &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
238 if let Some(operation_args) = &operation.list {
239 for arg in operation_args {
240 arg.to_writer(writer)?;
241 }
242 } else if let Some(operation_args) = &operation.dict {
243 write_explicit_element(writer, &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
244 for (_key, val) in operation_args {
245 val.to_writer(writer)?;
246 }
247 Ok(())
248 }), 5)?;
249 }
250 Ok(())
251 }), 5)?;
252 Ok(())
253 }), 5)
254}
255
256fn encode_body(writer: &mut asn1::Writer,
267 query_args: &Option<&mut Vec<(&str, Params)>>)
268 -> asn1::WriteResult {
269 write_explicit_element(writer,
270 &asn1::SequenceWriter::new(&|writer: &mut asn1::Writer| {
271 if let Some(q_args) = &query_args {
272 for (q_type, q_args) in q_args.iter() {
273 writer.write_element(&asn1::SequenceWriter::new(
274 &|writer: &mut asn1::Writer| {
275 writer.write_element(&asn1::Utf8String::new(q_type))?;
276 q_args.to_writer(writer)?;
277 Ok(())
278 },
279 ))?;
280 }
281 }
282 Ok(())
283 }),
284 4,
285 )
286}
287
288fn decode_simple(choice: Choice) -> Params {
298 match choice {
299 Choice::INTEGER(val) =>
300 Params::Integer(val),
301 Choice::BIGINTEGER(val) => {
302 let result = if val.is_negative() {
303 num_bigint::BigInt::from_signed_bytes_be(val.as_bytes())
304 } else {
305 num_bigint::BigInt::from_bytes_be(num_bigint::Sign::Plus, val.as_bytes())
306 };
307 Params::BigInteger(result)
308 },
309 Choice::OCTETSTRING(val) =>
310 Params::ByteArray(val.to_vec()),
311 Choice::UTF8STRING(val) =>
312 Params::Text(val.as_str().to_string()),
313 _ =>
314 Params::Null
315 }
316}
317
318fn decode_sequence_array<'a>(parser: &mut asn1::Parser<'a>, vec_array: &mut Vec<Params>) {
325 while let Ok(val) = Choice::parse(parser) {
326 let op_val = match val {
327 Choice::ARRAY(seq) => {
328 let res: Result<Params, ParseError> = seq.parse(|parser| {
329 let mut vect_array_new: Vec<Params> = Vec::new();
330 decode_sequence_array(parser, &mut vect_array_new);
331 Ok(Params::Array(vect_array_new))
332 });
333 res.unwrap()
334 }
335 Choice::DICT(seq) => {
336 let res: Result<Params, ParseError> = seq.parse(|parser| {
337 let mut btree_map_new: BTreeMap<String, Params> = BTreeMap::new();
338 decode_sequence_dict(parser, &mut btree_map_new);
339 Ok(Params::Dict(btree_map_new))
340 });
341 res.unwrap()
342 }
343 _ =>
344 decode_simple(val)
345 };
346 vec_array.push(op_val);
347 }
348}
349
350fn decode_sequence_dict<'a>(parser: &mut asn1::Parser<'a>, btreemap: &mut BTreeMap<String, Params>) {
357 while let Ok(seq) = parser.read_element::<asn1::Sequence>() {
358 let res: Result<(&'a str, Params), ParseError> = seq.parse(|parser| {
359 let key = parser.read_element::<asn1::Utf8String>()?;
360 let val = Choice::parse(parser).unwrap();
361
362 let op_val = match val {
363 Choice::DICT(seq) => {
364 let res: Result<Params, ParseError> = seq.parse(|parser| {
365 let mut btree_map_new: BTreeMap<String, Params> = BTreeMap::new();
366 decode_sequence_dict(parser, &mut btree_map_new);
367 Ok(Params::Dict(btree_map_new))
368 });
369 res.unwrap()
370 }
371 Choice::ARRAY(seq) => {
372 let res: Result<Params, ParseError> = seq.parse(|parser| {
373 let mut vect_array_new: Vec<Params> = Vec::new();
374 decode_sequence_array(parser, &mut vect_array_new);
375 Ok(Params::Array(vect_array_new))
376 });
377 res.unwrap()
378 },
379 _ =>
380 decode_simple(val)
381 };
382
383 Ok((key.as_str(), op_val))
384 });
385
386 let (key, value) = res.unwrap();
387 btreemap.insert(key.to_string(), value);
388 }
389}
390
391pub fn decode(data: &[u8]) -> Result<Params, Box<ParseError>> {
401 let tag = asn1::Tag::from_bytes(data).unwrap();
402 let tag_num = tag.0.as_u8().unwrap() & 0x1f;
403
404 if [0, 1, 2, 3, 6].contains(&tag_num) {
405 asn1::parse(data, |d| {
406 let res_choice = Choice::parse(d);
407 match res_choice {
408 Ok(val) => Ok(decode_simple(val)),
409 Err(error) => Err(Box::new(error)),
410 }
411 })
412 } else if tag_num == 4 {
413 let result = asn1::parse_single::<asn1::Explicit<asn1::Sequence, 4>>(data).unwrap();
414 result.into_inner().parse(|parser| {
415 let mut btree_map_new: BTreeMap<String, Params> = BTreeMap::new();
416 decode_sequence_dict(parser, &mut btree_map_new);
417 Ok(Params::Dict(btree_map_new))
418 })
419 } else if tag_num == 5 {
420 let result = asn1::parse_single::<asn1::Explicit<asn1::Sequence, 5>>(data).unwrap();
421 result.into_inner().parse(|parser|{
422 let mut vect_array_new: Vec<Params> = Vec::new();
423 decode_sequence_array(parser, &mut vect_array_new);
424 Ok(Params::Array(vect_array_new))
425 })
426 } else {
427 Ok(Params::Null)
428 }
429}
430
431pub fn decode_tx(data: &[u8]) -> Result<Params, Box<ParseError>> {
441 decode(data)
442}
443
444pub fn encode_value(value: &Params) -> Vec<u8> {
454 asn1::write(|writer| {
455 value.to_writer(writer)?;
456 Ok(())
457 }).unwrap()
458}
459
460pub fn encode_value_hex_encode(value: &Params) -> String {
470 hex::encode(encode_value(value))
471}
472
473pub fn to_draw_gtx(tx: &Transaction) -> Params {
483 let mut signers: Vec<Params> = vec![];
484 let mut operations:Vec<Params> = vec![];
485
486 if let Some(raw_signers) = &tx.signers {
487 for signer in raw_signers {
488 signers.push(Params::ByteArray(signer.to_vec()));
489 }
490 }
491
492 for op in &tx.operations.clone().unwrap() {
493 let mut op_args: Vec<Params> = vec![];
494
495 if let Some(op_list) = &op.list {
496 for arg in op_list {
497 op_args.push(arg.clone());
498 }
499 } else if let Some(op_dict) = &op.dict {
500 for (_key, value) in op_dict {
501 op_args.push(value.clone());
502 }
503 }
504
505 operations.push(Params::Array(vec![
506 Params::Text(op.operation_name.clone().unwrap()),
507 Params::Array(op_args)
508 ]));
509 }
510
511 Params::Array(vec![
512 Params::ByteArray(tx.blockchain_rid.to_vec()),
513 Params::Array(operations),
514 Params::Array(signers)
515 ])
516}
517
518#[allow(dead_code)]
519fn assert_roundtrips(
526 query_args: Option<&mut Vec<(&str, Params)>>,
527 expected_value: &str) {
528 let result = asn1::write(|writer| {
529 encode_body(writer, &query_args)?;
530 Ok(())
531 });
532 assert_eq!(hex::encode(result.unwrap()), expected_value);
533}
534
535#[allow(dead_code)]
536fn assert_roundtrips_value(
544 value: &Params,
545 expected_decode: &Params,
546 expected_value: &str) {
547 let encode_result = encode_value(value);
548 assert_eq!(expected_value, hex::encode(encode_result.clone()));
549
550 let decode_result = decode(&encode_result).unwrap();
551 assert_eq!(expected_decode, &decode_result);
552}
553
554#[test]
555fn gtv_encode_value_null() {
556 assert_roundtrips_value(&Params::Null, &Params::Null, "a0020500")
557}
558
559#[test]
560fn gtv_encode_value_boolean() {
561 assert_roundtrips_value(&Params::Boolean(true), &Params::Integer(1), "a303020101");
562 assert_roundtrips_value(&Params::Boolean(false), &Params::Integer(0),"a303020100")
563}
564
565#[test]
566fn gtv_encode_value_integer() {
567 assert_roundtrips_value(&Params::Integer(999), &Params::Integer(999), "a304020203e7")
568}
569
570#[test]
571fn gtv_encode_value_decimal() {
572 use std::str::FromStr;
573 assert_roundtrips_value(&Params::Decimal(bigdecimal::BigDecimal::from_str("999.999").unwrap()), &Params::Text("999.999".to_string()), "a2090c073939392e393939")
574}
575
576#[test]
577fn gtv_encode_value_text() {
578 assert_roundtrips_value(&Params::Text("hello!".to_string()), &Params::Text("hello!".to_string()), "a2080c0668656c6c6f21")
579}
580
581#[test]
582fn gtv_encode_value_bytearray() {
583 assert_roundtrips_value(&Params::ByteArray(b"123456789".to_vec()), &Params::ByteArray(b"123456789".to_vec()), "a10b0409313233343536373839")
584}
585
586#[test]
587fn gtv_encode_value_array() {
588 let array = Params::Array(vec![
589 Params::Text("foo1".to_string()),
590 Params::Text("foo2".to_string()),
591 ]);
592 assert_roundtrips_value(&array, &array, "a5123010a2060c04666f6f31a2060c04666f6f32")
593}
594
595#[test]
596fn gtv_encode_value_dict() {
597 use std::collections::BTreeMap;
598 let mut data: BTreeMap<String, Params> = BTreeMap::new();
599 let mut data1: BTreeMap<String, Params> = BTreeMap::new();
600 let mut data2: BTreeMap<String, Params> = BTreeMap::new();
601
602 data2.insert("foo1_1_1".to_string(), Params::Integer(1000));
603
604 data1.insert("foo1_1".to_string(), Params::Dict(data2));
605 data1.insert("foo1_2".to_string(), Params::Text("hello!".to_string()));
606
607 data.insert("foo".to_string(), Params::Text("bar".to_string()));
608 data.insert("foo1".to_string(), Params::Dict(data1));
609
610 let dict = Params::Dict(data);
611 assert_roundtrips_value(&dict, &dict, "a450304e300c0c03666f6fa2050c03626172303e0c04666f6f31a4363034301e0c06666f6f315f31a414301230100c08666f6f315f315f31a304020203e830120c06666f6f315f32a2080c0668656c6c6f21")
612}
613
614#[test]
615fn gtv_encode_value_big_integer() {
616 use std::str::FromStr;
617
618 let max_i128: i128 = i128::MAX;
619 let data = num_bigint::BigInt::from_str(max_i128.to_string().as_str()).unwrap();
620 assert_roundtrips_value(&Params::BigInteger(data.clone()), &Params::BigInteger(data), "a61202107fffffffffffffffffffffffffffffff");
621}
622
623#[test]
624fn gtv_test_sequence_with_empty() {
625 assert_roundtrips(None, "a4023000");
626}
627
628#[test]
629fn gtv_test_sequence_with_boolean() {
630 assert_roundtrips(Some(&mut vec![("foo", Params::Boolean(true))]),
631 "a40e300c300a0c03666f6fa303020101");
632}
633
634#[test]
635fn gtv_test_sequence_with_string() {
636 assert_roundtrips(Some(&mut vec![("foo", Params::Text("bar".to_string()))]),
637 "a410300e300c0c03666f6fa2050c03626172");
638}
639
640#[test]
641fn gtv_test_sequence_with_octet_string() {
642 assert_roundtrips(Some(&mut vec![("foo", Params::ByteArray("bar".as_bytes().to_vec()))]),
643 "a410300e300c0c03666f6fa1050403626172");
644}
645
646#[test]
647fn gtv_test_sequence_with_number() {
648 assert_roundtrips(Some(&mut vec![("foo", Params::Integer(9999))]),
649 "a40f300d300b0c03666f6fa3040202270f");
650}
651
652#[test]
653fn gtv_test_sequence_with_negative_number() {
654 assert_roundtrips(Some(&mut vec![("foo", Params::Integer(-9999))]),
655 "a40f300d300b0c03666f6fa3040202d8f1");
656}
657
658#[test]
659fn gtv_test_sequence_with_decimal() {
660 use std::str::FromStr;
661 assert_roundtrips(Some(&mut vec![("foo", Params::Decimal(bigdecimal::BigDecimal::from_str("99.99").unwrap()))]),
662 "a4123010300e0c03666f6fa2070c0539392e3939");
663}
664
665#[test]
666fn gtv_test_sequence_with_negative_decimal() {
667 use std::str::FromStr;
668 assert_roundtrips(Some(&mut vec![("foo", Params::Decimal(bigdecimal::BigDecimal::from_str("-99.99").unwrap()))]),
669 "a4133011300f0c03666f6fa2080c062d39392e3939");
670}
671
672#[test]
673fn gtv_test_sequence_with_json() {
674 let data = serde_json::json!({
675 "foo": "bar",
676 "bar": 9,
677 "foo": 9.00
678 }).to_string();
679 assert_roundtrips(Some(&mut vec![("foo", Params::Text(data))]),
680 "a420301e301c0c03666f6fa2150c137b22626172223a392c22666f6f223a392e307d");
681}
682
683#[test]
684fn gtv_test_sequence_with_big_integer() {
685 use std::str::FromStr;
686
687 let max_i128: i128 = i128::MAX;
688 let data = num_bigint::BigInt::from_str(max_i128.to_string().as_str()).unwrap();
689 assert_roundtrips(Some(&mut vec![("foo", Params::BigInteger(data))]),
690 "a41d301b30190c03666f6fa61202107fffffffffffffffffffffffffffffff");
691}
692
693#[test]
694fn gtv_test_sequence_with_negative_big_integer() {
695 use std::str::FromStr;
696
697 let min_i128: i128 = i128::MIN;
698 let data = num_bigint::BigInt::from_str(min_i128.to_string().as_str()).unwrap();
699 assert_roundtrips(Some(&mut vec![("foo", Params::BigInteger(data))]),
700 "a41d301b30190c03666f6fa612021080000000000000000000000000000000");
701
702 let h_data = "a41d301b30190c03666f6fa6120210ff123b1a8199614ad13ab29a33fba0eb";
703
704 let data = num_bigint::BigInt::from_str("-1234567890123456789123456789123456789").unwrap();
705 assert_roundtrips(Some(&mut vec![("foo", Params::BigInteger(data.clone()))]),
706 h_data);
707
708 let hex_decode_data = hex::decode(h_data).unwrap();
709 let result = decode(&hex_decode_data).unwrap();
710
711 if let Params::Dict(dict) = result {
712 let bi: num_bigint::BigInt = dict["foo"].clone().into();
713 assert_eq!(data, bi);
714 }
715}
716
717#[test]
718fn gtv_test_sequence_with_array() {
719 let data = &mut vec![(
720 "foo",
721 Params::Array(vec![
722 Params::Text("bar1".to_string()),
723 Params::Text("bar2".to_string()),
724 ]),
725 )];
726 assert_roundtrips(Some(data),
727 "a41d301b30190c03666f6fa5123010a2060c0462617231a2060c0462617232");
728}
729
730#[test]
731fn gtv_test_sequence_with_dict() {
732 use std::collections::BTreeMap;
733
734 let mut params: BTreeMap<String, Params> = BTreeMap::new();
735 params.insert("foo".to_string(), Params::Text("bar".to_string()));
736 params.insert("foo1".to_string(), Params::Text("bar1".to_string()));
737
738 let data = &mut vec![("foo", Params::Dict(params))];
739
740 assert_roundtrips(Some(data),
741 "a42b302930270c03666f6fa420301e300c0c03666f6fa2050c03626172300e0c04666f6f31a2060c0462617231");
742}
743
744#[test]
745fn gtv_test_sequence_with_nested_dict() {
746 use std::collections::BTreeMap;
747
748 let mut dict1: BTreeMap<String, Params> = BTreeMap::new();
749 let mut dict2: BTreeMap<String, Params> = BTreeMap::new();
750 let dict3: BTreeMap<String, Params> = BTreeMap::new();
751
752 dict1.insert("dict1_foo".to_string(), Params::Text("dict1_bar".to_string()));
753
754 dict2.insert("dict2_foo".to_string(), Params::Text("dict2_bar".to_string()));
755 dict2.insert("dict2_foo1".to_string(), Params::Text("dict2_bar1".to_string()));
756
757 dict2.insert("dict3_empty_data".to_string(), Params::Dict(dict3));
758
759 dict1.insert("dict2_data".to_string(), Params::Dict(dict2));
760
761 let data = &mut vec![("foo", Params::Dict(dict1))];
762
763 assert_roundtrips(Some(data),
764 "a481893081863081830c03666f6fa47c307a30180c0964696374315f666f6fa20b0c0964696374315f626172305e0c0a64696374325f64617461a450304e30180c0964696374325f666f6fa20b0c0964696374325f626172301a0c0a64696374325f666f6f31a20c0c0a64696374325f6261723130160c1064696374335f656d7074795f64617461a4023000");
765}
766
767#[test]
768fn gtv_test_sequence_with_nested_dict_array() {
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 mut dict3: BTreeMap<String, Params> = BTreeMap::new();
774
775 dict2.insert("dict2_foo".to_string(), Params::Text("dict2_bar".to_string()));
776 dict3.insert("dict3_foo".to_string(), Params::Text("dict3_bar".to_string()));
777
778 let array1 = vec![
779 Params::Dict(dict2), Params::Dict(dict3)];
780
781 dict1.insert("array1".to_string(), Params::Array(array1));
782
783 let data = &mut vec![("foo", Params::Dict(dict1))];
784
785 assert_roundtrips(Some(data),
786 "a457305530530c03666f6fa44c304a30480c06617272617931a53e303ca41c301a30180c0964696374325f666f6fa20b0c0964696374325f626172a41c301a30180c0964696374335f666f6fa20b0c0964696374335f626172");
787}
788
789#[allow(dead_code)]
790fn assert_roundtrips_simple(op: Params, expected_value: &str) {
797 let result = asn1::write(|writer| {
798 op.to_writer(writer)?;
799 Ok(())
800 });
801 assert_eq!(hex::encode(result.unwrap()), expected_value);
802}
803
804#[test]
805fn gtv_test_simple_null() {
806 assert_roundtrips_simple(Params::Null, "a0020500");
807}
808
809#[test]
810fn gtv_test_simple_boolean() {
811 assert_roundtrips_simple(Params::Boolean(true), "a303020101");
812 assert_roundtrips_simple(Params::Boolean(false), "a303020100");
813}
814
815#[test]
816fn gtv_test_simple_integer() {
817 assert_roundtrips_simple(Params::Integer(99999), "a305020301869f");
818}
819
820#[test]
821fn gtv_test_simple_big_integer() {
822 assert_roundtrips_simple(Params::BigInteger(num_bigint::BigInt::from(1234567890123456789_i128)), "a60a0208112210f47de98115");
823}
824
825#[test]
826fn gtv_test_simple_decimal() {
827 use std::str::FromStr;
828 assert_roundtrips_simple(Params::Decimal(bigdecimal::BigDecimal::from_str("99.999").unwrap()), "a2080c0639392e393939");
829}
830
831#[test]
832fn gtv_test_simple_string() {
833 assert_roundtrips_simple(Params::Text("abcABC123".to_string()), "a20b0c09616263414243313233");
834 assert_roundtrips_simple(Params::Text("utf-8 unicode Trái Tim Ngục Tù ...!@#$%^&*()".to_string()), "a2320c307574662d3820756e69636f6465205472c3a1692054696d204e67e1bba5632054c3b9202e2e2e21402324255e262a2829");
835}
836
837#[test]
838fn gtv_test_simple_byte_array() {
839 assert_roundtrips_simple(Params::ByteArray(b"123456abcedf".to_vec()), "a10e040c313233343536616263656466");
840}
841
842#[test]
843fn gtv_test_simple_array() {
844 assert_roundtrips_simple(Params::Array(vec![
845 Params::Text("foo".to_string()), Params::Integer(1)
846 ]), "a50e300ca2050c03666f6fa303020101");
847}
848
849#[test]
850fn gtv_test_simple_dict() {
851 use std::collections::BTreeMap;
852 let mut data: BTreeMap<String, Params> = BTreeMap::new();
853 data.insert("foo".to_string(), Params::Text("bar".to_string()));
854 assert_roundtrips_simple(Params::Dict(data), "a410300e300c0c03666f6fa2050c03626172");
855}
856
857#[allow(dead_code)]
858fn assert_roundtrips_simple_decode(data: &str, expected_value: Params) {
865 let hex_decode_data = hex::decode(data).unwrap();
866 let result = decode(&hex_decode_data).unwrap();
867 assert_eq!(result, expected_value);
868}
869
870#[test]
871fn gtv_test_simple_null_decode() {
872 assert_roundtrips_simple_decode("a0020500", Params::Null);
873}
874
875#[test]
876fn gtv_test_simple_big_integer_decode() {
877 assert_roundtrips_simple_decode("a60a0208112210f47de98115",
878 Params::BigInteger(num_bigint::BigInt::from(1234567890123456789_i128)));
879}
880
881#[test]
882fn gtv_test_simple_integer_decode() {
883 assert_roundtrips_simple_decode("a305020301869f", Params::Integer(99999));
884}
885
886#[test]
887fn gtv_test_simple_decimal_decode() {
888 assert_roundtrips_simple_decode("a2080c0639392e393939", Params::Text("99.999".to_string()));
889}
890
891#[test]
892fn gtv_test_simple_string_decode() {
893 assert_roundtrips_simple_decode("a2320c307574662d3820756e69636f6465205472c3a1692054696d204e67e1bba5632054c3b9202e2e2e21402324255e262a2829",
894 Params::Text("utf-8 unicode Trái Tim Ngục Tù ...!@#$%^&*()".to_string()))
895}
896
897#[test]
898fn gtv_test_simple_bytearray_with_hex_decode() {
899 assert_roundtrips_simple_decode("a53b3039a5373035a12304210373599a61cc6b3bc02a78c34313e1737ae9cfd56b9bb24360b437d469efdf3b15a20e0c0c73616d706c655f76616c7565",
900 Params::Array(vec![
901 Params::Array(vec![
902 Params::ByteArray(hex::decode("0373599A61CC6B3BC02A78C34313E1737AE9CFD56B9BB24360B437D469EFDF3B15").unwrap()),
903 Params::Text("sample_value".to_string())
904 ])
905 ]))
906}
907
908#[test]
909fn gtv_test_sequence_simple_array_decode() {
910 let data = Params::Array(vec![
911 Params::Text("foo".to_string()), Params::Integer(1),
912 Params::Text("bar".to_string()), Params::Integer(2),
913 Params::Array(vec![]),
914 Params::Text("ca".to_string()), Params::Integer(3),
915 Params::Array(vec![
916 Params::Integer(1111),
917 Params::Array(vec![
918 Params::Integer(2222),
919 Params::Integer(3333),
920 ])
921 ]),
922 ]);
923
924 let result = asn1::write(|writer| {
925 data.to_writer(writer)?; Ok(()) }).unwrap();
926
927 assert_eq!(data, decode(result.as_slice()).unwrap());
928}
929
930#[test]
931fn gtv_test_sequence_simple_dict_decode() {
932 let mut data_btreemap: BTreeMap<String, Params> = BTreeMap::new();
933
934 data_btreemap.insert("foo".to_string(), Params::Text("bar".to_string()));
935 data_btreemap.insert("status".to_string(), Params::ByteArray("OK".as_bytes().to_vec()));
936
937 let data = Params::Dict(data_btreemap);
938
939 let result = asn1::write(|writer| {
940 data.to_writer(writer)?; Ok(()) }).unwrap();
941
942 assert_eq!(data, decode(result.as_slice()).unwrap());
943}
944
945#[test]
946fn gtv_test_sequence_complex_mix_dict_array_decode() {
947 use std::collections::BTreeMap;
948 let mut data_btreemap: BTreeMap<String, Params> = BTreeMap::new();
949 let mut dict_in: BTreeMap<String, Params> = BTreeMap::new();
950
951 dict_in.insert("foo".to_string(), Params::Text("bar".to_string()));
952
953 data_btreemap.insert("status".to_string(), Params::Text("dict_bar".to_string()));
954 data_btreemap.insert("command".to_string(), Params::Text("dict_bar2".to_string()));
955 data_btreemap.insert("state".to_string(), Params::Integer(123));
956 data_btreemap.insert("dict".to_string(), Params::Dict(dict_in));
957 data_btreemap.insert("array".to_string(), Params::Array(vec![
958 Params::Text("test array".to_string()),
959 Params::BigInteger(num_bigint::BigInt::from(123456_i128)),
960 Params::Array(vec![
961 Params::Text("test array 2".to_string())
962 ])
963 ]));
964
965 let data = Params::Dict(data_btreemap);
966
967 let result = asn1::write(|writer| {
968 data.to_writer(writer)?; Ok(()) }).unwrap();
969
970 assert_eq!(data, decode(result.as_slice()).unwrap());
971}