1extern crate num_bigint;
29
30use std::{collections::BTreeMap, fmt::Debug};
31use num_bigint::BigInt;
32use bigdecimal::BigDecimal;
33use std::str::FromStr;
34use base64::{Engine as _, engine::general_purpose};
35
36#[allow(unused_imports)]
37use postchain_client_derive::StructMetadata;
38
39pub trait StructMetadata {
40 fn field_names_and_types() -> std::collections::BTreeMap<String, String>;
41}
42
43#[derive(Clone, Debug, PartialEq)]
49pub enum Params {
50 Null,
52 Boolean(bool),
54 Integer(i64),
56 BigInteger(BigInt),
58 Decimal(BigDecimal),
60 Text(String),
62 ByteArray(Vec<u8>),
64 Array(Vec<Params>),
66 Dict(BTreeMap<String, Params>)
68}
69
70pub type QueryParams = Params;
71pub type OperationParams = Params;
72
73#[allow(dead_code)]
84fn deserialize_bigint<'de, D>(deserializer: D) -> Result<BigInt, D::Error>
85where
86 D: serde::Deserializer<'de>,
87{
88 let de_str: String = serde::Deserialize::deserialize(deserializer)?;
89
90 BigInt::parse_bytes(de_str.as_bytes(), 10)
91 .ok_or(serde::de::Error::custom("Failed to parse BigInt"))
92}
93
94#[allow(dead_code)]
105fn deserialize_byte_array<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
106where
107 D: serde::Deserializer<'de>,
108{
109 let base64_str: String = serde::Deserialize::deserialize(deserializer)?;
110 general_purpose::STANDARD.decode(&base64_str).map_err(serde::de::Error::custom)
111}
112
113
114#[allow(dead_code)]
126fn serialize_bigint<S>(bigint: &BigInt, serializer: S) -> Result<S::Ok, S::Error>
127where
128 S: serde::Serializer,
129{
130 let bigint_str = bigint.to_string();
131 serializer.serialize_str(&bigint_str)
132}
133
134#[allow(dead_code)]
159fn serialize_bigdecimal<S>(bigdecimal: &BigDecimal, serializer: S) -> Result<S::Ok, S::Error>
160where
161 S: serde::Serializer,
162{
163 serializer.serialize_str(&bigdecimal.to_string())
164}
165
166#[allow(dead_code)]
189fn deserialize_bigdecimal<'de, D>(deserializer: D) -> Result<BigDecimal, D::Error>
190where
191 D: serde::Deserializer<'de>,
192{
193 let s: String = serde::Deserialize::deserialize(deserializer)?;
194 BigDecimal::from_str(&s)
195 .map_err(serde::de::Error::custom)
196}
197
198#[derive(Clone, Debug, PartialEq)]
203pub struct Operation<'a> {
204 pub dict: Option<Vec<(&'a str, Params)>>,
208 pub list: Option<Vec<Params>>,
209 pub operation_name: Option<&'a str>,
210}
211
212impl<'a> Default for Operation<'a> {
213 fn default() -> Self {
214 Self {
215 dict: None,
216 list: None,
217 operation_name: None,
218 }
219 }
220}
221
222fn is_vec_u8(value: &Vec<serde_json::Value>) -> bool {
230 value.iter().all(|v| {
231 if let serde_json::Value::Number(n) = v {
232 n.is_u64() && n.as_u64().unwrap() <= u8::MAX as u64
233 } else {
234 false
235 }
236 })
237}
238
239impl<'a> Operation<'a> {
240 pub fn from_dict(operation_name: &'a str, params: Vec<(&'a str, Params)>) -> Self {
249 Self {
250 dict: Some(params),
251 operation_name: Some(operation_name),
252 ..Default::default()
253 }
254 }
255
256 pub fn from_list(operation_name: &'a str, params: Vec<Params>) -> Self {
265 Self {
266 list: Some(params),
267 operation_name: Some(operation_name),
268 ..Default::default()
269 }
270 }
271}
272
273impl Params {
274 pub fn decimal_to_string(val: Box<f64>) -> String {
282 val.to_string()
283 }
284
285 pub fn dict_to_array(self) -> Vec<Params> {
296 match self {
297 Params::Dict(dict) => {
298 let values: Vec<Params> = dict.into_iter()
299 .filter_map(|(_, value)| {
300 Some(value)
301 })
302 .collect();
303 values
304 },
305 _ => panic!("Expected Params::Dict, found {:?}", self),
306 }
307 }
308
309 pub fn is_empty(self) -> bool {
319 match self {
320 Params::Array(array) => array.is_empty(),
321 Params::Dict(dict) => dict.is_empty(),
322 Params::ByteArray(bytearray) => bytearray.is_empty(),
323 Params::Text(text) => text.is_empty(),
324 _ => panic!("Cannot check empty of this type {:?}", self)
325 }
326 }
327
328 pub fn len(self) -> usize {
338 match self {
339 Params::Array(array) => array.len(),
340 Params::Dict(dict) => dict.len(),
341 Params::ByteArray(bytearray) => bytearray.len(),
342 Params::Text(text) => text.len(),
343 _ => panic!("Cannot get length of this type {:?}", self)
344 }
345 }
346
347 pub fn to_struct<T>(&self) -> Result<T, String>
367 where
368 T: Default + std::fmt::Debug + for<'de> serde::Deserialize<'de>,
369 {
370 match self {
371 Params::Dict(_) => {
372 let json_value = self.to_json_value();
373
374 serde_json::from_value(json_value)
375 .map_err(|e| format!("Failed to convert Params to struct: {}", e))
376 },
377 _ => Err(format!("Expected Params::Dict, found {:?}", self)),
378 }
379 }
380
381 pub fn to_json_value(&self) -> serde_json::Value {
389 match *self {
390 Params::Null => serde_json::Value::Null,
391 Params::Boolean(b) => serde_json::Value::Bool(b),
392 Params::Integer(i) => serde_json::Value::Number(serde_json::Number::from(i)),
393 Params::BigInteger(ref big_int) => serde_json::Value::String(big_int.to_string()),
394 Params::Decimal(ref big_decimal) => serde_json::Value::String(big_decimal.to_string()),
395 Params::Text(ref text) => serde_json::Value::String(text.to_string()),
396 Params::ByteArray(ref bytearray) => {
397 if bytearray.len() == 33 {
398 serde_json::Value::String(hex::encode(bytearray))
399 } else {
400 let base64_encoded = general_purpose::STANDARD.encode(bytearray);
401 serde_json::Value::String(base64_encoded)
402 }
403 },
404 Params::Array(ref array) => {
405 let json_array: Vec<serde_json::Value> = array.iter().map(|param| param.to_json_value()).collect();
406 serde_json::Value::Array(json_array)
407 },
408 Params::Dict(ref dict) => {
409 let json_object: serde_json::Map<String, serde_json::Value> = dict.iter()
410 .map(|(key, value)| (key.to_string(), value.to_json_value()))
411 .collect();
412 serde_json::Value::Object(json_object)
413 },
414 }
415 }
416
417 pub fn from_struct<T>(struct_instance: &T) -> Params
440 where
441 T: std::fmt::Debug + serde::Serialize + StructMetadata,
442 {
443 let json_value = serde_json::to_value(struct_instance)
444 .expect("Failed to convert struct to JSON value");
445
446 let fnat = T::field_names_and_types();
447
448 Params::Dict(Self::json_value_to_params_dict(json_value, fnat))
449 }
450
451 fn json_value_to_params_dict(value: serde_json::Value, fnat: BTreeMap<String, String>) -> BTreeMap<String, Params> {
465 let mut dict: BTreeMap<String, Params> = BTreeMap::new();
466
467 if let serde_json::Value::Object(map) = value {
468 for (key, val) in map {
469 let f_type = fnat.get(&key).cloned();
470 dict.insert(key, Self::value_to_params(val, f_type));
471 }
472 }
473
474 dict
475 }
476
477 pub fn from_struct_to_list<T>(struct_instance: &T) -> Vec<Params>
491 where
492 T: std::fmt::Debug + serde::Serialize + StructMetadata,
493 {
494 let json_value = serde_json::to_value(struct_instance)
495 .expect("Failed to convert struct to JSON value");
496
497 let mut vec = Vec::new();
498
499 let fnat = T::field_names_and_types();
500
501 if let serde_json::Value::Object(map) = json_value {
502 for (key, val) in map {
503 let f_type = fnat.get(&key).cloned();
504 vec.push(Self::value_to_params(val, f_type));
505 }
506 }
507
508 vec
509 }
510
511 pub fn from_struct_to_vec<T>(struct_instance: &T) -> Vec<(String, Params)>
522 where
523 T: std::fmt::Debug + serde::Serialize,
524 {
525 let json_value = serde_json::to_value(struct_instance)
526 .expect("Failed to convert struct to JSON value");
527
528 let mut vec = Vec::new();
529
530 if let serde_json::Value::Object(map) = json_value {
531 for (key, val) in map {
532 vec.push((key, Self::value_to_params(val, None)));
533 }
534 }
535
536 vec
537 }
538
539 fn value_to_params(value: serde_json::Value, field_type: Option<String>) -> Params {
558 match value {
559 serde_json::Value::Null => Params::Null,
560 serde_json::Value::Bool(b) => Params::Boolean(b),
561 serde_json::Value::Number(n) => {
562 if let Some(i) = n.as_i64() {
563 Params::Integer(i)
564 } else {
565 Params::Null
566 }
567 },
568 serde_json::Value::String(s) => {
569 match field_type {
570 Some(val) if val.contains("BigInt") => {
571 match BigInt::parse_bytes(s.as_bytes(), 10) {
572 Some(big_int) => Params::BigInteger(big_int),
573 None => panic!("Required field is not a valid BigInteger"),
574 }
575 },
576 Some(val) if val.contains("BigDecimal") => {
577 match BigDecimal::parse_bytes(s.as_bytes(), 10) {
578 Some(big_decimal) => Params::Decimal(big_decimal),
579 None => panic!("Required field is not a valid BigDecimal"),
580 }
581 },
582 _ => Params::Text(s)
583 }
584 },
585 serde_json::Value::Array(arr) => {
586 let is_vec_u8 = is_vec_u8(&arr);
587 if is_vec_u8 {
588 let barr: Vec<u8> = arr.iter().map(|v|{v.as_u64().unwrap() as u8}).collect();
589 return Params::ByteArray(barr)
590 }
591 let params_array: Vec<Params> = arr.into_iter().map(|x|{
592 Self::value_to_params(x, None)
593 }).collect();
594 Params::Array(params_array)
595 },
596 serde_json::Value::Object(dict) => {
597 let params_dict: BTreeMap<String, Params> = dict.into_iter().map(|(k, v)| ( k, Self::value_to_params(v, None))).collect();
598 Params::Dict(params_dict)
599 }
600 }
601 }
602
603 #[cfg(debug_assertions)]
611 pub fn debug_print(&self) {
612 match self {
613 Params::Array(array) => {
614 for item in array {
615 item.debug_print();
616 }
617 }
618 Params::Dict(dict) => {
619 for item in dict {
620 eprintln!("key = {}", item.0);
621 eprintln!("value = ");
622 item.1.debug_print();
623 }
624 }
625 Params::ByteArray(val) => {
626 eprintln!("{:?}", hex::encode(val));
627 }
628 _ =>
629 eprintln!("{:?}", self)
630 }
631 }
632}
633
634impl From<Params> for bool {
639 fn from(value: Params) -> Self {
640 match value {
641 Params::Boolean(val) => val,
642 _ => panic!("Cannot convert {:?} to bool", value)
643 }
644 }
645}
646
647impl From<Params> for i64 {
652 fn from(value: Params) -> Self {
653 match value {
654 Params::Integer(val) => val,
655 _ => panic!("Cannot convert {:?} to i64", value)
656 }
657 }
658}
659
660impl From<Params> for BigInt {
665 fn from(value: Params) -> Self {
666 match value {
667 Params::BigInteger(val) => val,
668 _ => panic!("Cannot convert {:?} to BigInt", value)
669 }
670 }
671}
672
673impl From<Params> for BigDecimal {
678 fn from(value: Params) -> Self {
679 match value {
680 Params::Decimal(val) => val,
681 _ => panic!("Cannot convert {:?} to BigDecimal", value)
682 }
683 }
684}
685
686impl From<Params> for String {
691 fn from(value: Params) -> Self {
692 match value {
693 Params::Text(val) => val,
694 _ => panic!("Cannot convert {:?} to String", value)
695 }
696 }
697}
698
699impl From<Params> for Vec<u8> {
704 fn from(value: Params) -> Self {
705 match value {
706 Params::ByteArray(val) => val,
707 _ => panic!("Cannot convert {:?} to Vec<u8>", value)
708 }
709 }
710}
711
712impl Into<Vec<Params>> for Params {
720 fn into(self) -> Vec<Params> {
721 match self {
722 Params::Array(array) => array,
723 _ => panic!("Cannot convert {:?} into Vec<Params>", self),
724 }
725 }
726}
727
728impl Into<BTreeMap<String, Params>> for Params {
736 fn into(self) -> BTreeMap<String, Params> {
737 match self {
738 Params::Dict(dict) => dict,
739 _ => panic!("Cannot convert {:?} into BTreeMap", self),
740 }
741 }
742}
743
744#[test]
745fn test_serialize_struct_to_param_dict() {
746 #[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq)]
747 struct TestStruct2 {
748 foo: String
749 }
750
751 #[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq, StructMetadata)]
752 struct TestStruct1 {
753 foo: String,
754 bar: i64,
755 #[serde(serialize_with = "serialize_bigint", deserialize_with = "deserialize_bigint")]
756 bigint: num_bigint::BigInt,
757 ok: bool,
758 nested_struct: TestStruct2,
759 #[serde(deserialize_with="deserialize_byte_array")]
760 bytearray: Vec<u8>,
761 }
762
763 let ts1 = TestStruct1 {
764 foo: "foo".to_string(), bar: 1, ok: true,
765 bigint: num_bigint::BigInt::from(170141183460469231731687303715884105727 as i128),
766 nested_struct: TestStruct2{foo: "bar".to_string()}, bytearray: vec![1, 2, 3, 4, 5]
767 };
768
769 let r: Params = Params::from_struct(&ts1);
770
771 let m: Result<TestStruct1, String> = r.to_struct();
772
773 assert_eq!(ts1, m.unwrap());
774
775}
776
777#[test]
778fn test_deserialize_param_dict_to_struct() {
779 use std::str::FromStr;
780
781 #[derive(Debug, Default, serde::Deserialize, PartialEq)]
786 struct TestNestedStruct {
787 bigint_as_string: String,
788 #[serde(deserialize_with = "deserialize_bigint")]
789 bigint_as_num_bigint: num_bigint::BigInt
790 }
791
792 #[derive(Debug, Default, serde::Deserialize, PartialEq)]
793 struct TestStruct {
794 x: i64,
795 y: i64,
796 z: String,
797 l: bool,
798 n: BigDecimal,
799 m: String,
800 dict: TestNestedStruct,
801 array: Vec<serde_json::Value>,
802 t: Option<bool>
803 }
804
805 let bigint = num_bigint::BigInt::from(100000000000000000000000 as i128);
806 let bytearray_value = b"1234";
807 let bytearray_base64_encoded = general_purpose::STANDARD.encode(bytearray_value);
808
809 let ts = TestStruct{
810 t: None,
811 x: 1, y: 2, z: "foo".to_string(), dict: TestNestedStruct {
812 bigint_as_string: bigint.to_string(),
813 bigint_as_num_bigint: (100000000000000000000000 as i128).into()
814 }, l: true, n: BigDecimal::from_str("3.14").unwrap(), m: bytearray_base64_encoded, array: vec![
815 serde_json::Value::Number(serde_json::Number::from(1 as i64)),
816 serde_json::Value::String("foo".to_string()),
817 ]
818 };
819
820 let mut nested_params: BTreeMap<String, Params> = BTreeMap::new();
821 nested_params.insert("bigint_as_string".to_string(), Params::BigInteger(bigint.clone()));
822 nested_params.insert("bigint_as_num_bigint".to_string(), Params::BigInteger(bigint.clone()));
823
824 let mut params: BTreeMap<String, Params> = BTreeMap::new();
825 params.insert("t".to_string(), Params::Null);
826 params.insert("x".to_string(), Params::Integer(1));
827 params.insert("y".to_string(), Params::Integer(2));
828 params.insert("z".to_string(), Params::Text("foo".to_string()));
829 params.insert("dict".to_string(), Params::Dict(nested_params));
830 params.insert("l".to_string(), Params::Boolean(true));
831 params.insert("n".to_string(), Params::Decimal(BigDecimal::from_str("3.14").unwrap()));
832 params.insert("m".to_string(), Params::ByteArray(bytearray_value.to_vec()));
833 params.insert("array".to_string(), Params::Array(vec![Params::Integer(1), Params::Text("foo".to_string())]));
834
835 let params_dict = Params::Dict(params);
836 let result: Result<TestStruct, String> = params_dict.to_struct();
837
838 if let Ok(val) = result {
839 assert_eq!(ts, val);
840 } else {
841 panic!("Error deserializing params: {}", result.unwrap_err());
842 }
843}
844
845#[test]
846fn test_serialize_deserialize_bigint() {
847 let large_int_str = "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
848 let large_int = BigInt::parse_bytes(large_int_str.as_bytes(), 10).unwrap();
849
850 #[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq, StructMetadata)]
851 struct TestStruct {
852 #[serde(serialize_with = "serialize_bigint", deserialize_with = "deserialize_bigint")]
853 bigint1: num_bigint::BigInt,
854 }
855
856 let ts = TestStruct {
857 bigint1: large_int.clone(),
858 };
859
860 let mut params: BTreeMap<String, Params> = BTreeMap::new();
861 params.insert("bigint1".to_string(), Params::BigInteger(large_int));
862
863 let result: Result<TestStruct, String> = Params::Dict(params).to_struct();
864
865 if let Ok(val) = result {
866 assert_eq!(ts, val);
867 } else {
868 panic!("Error deserializing params: {}", result.unwrap_err());
869 }
870}
871
872#[test]
873fn test_serialize_deserialize_bigdecimal() {
874 use std::str::FromStr;
875
876 let large_int_str = "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
877 let large_int = BigInt::parse_bytes(large_int_str.as_bytes(), 10).unwrap();
878
879 #[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq, StructMetadata)]
880 struct TestStruct {
881 no_number: String,
882 #[serde(serialize_with = "serialize_bigint", deserialize_with = "deserialize_bigint")]
883 bigint: BigInt,
884 #[serde(serialize_with = "serialize_bigdecimal", deserialize_with = "deserialize_bigdecimal")]
885 bigdecimal: BigDecimal
886 }
887
888 let ts = TestStruct {
889 no_number: "Hello!".to_string(),
890 bigdecimal: BigDecimal::from_str(".02").unwrap(),
891 bigint: large_int
892 };
893
894 let r: Params = Params::from_struct(&ts);
895
896 let m: Result<TestStruct, String> = r.to_struct();
897
898 assert_eq!(ts, m.unwrap());
899}
900
901#[test]
902fn test_struct_metadata_derive() {
903 #[derive(Debug, Default, serde::Serialize, serde::Deserialize, PartialEq, StructMetadata)]
904 struct TestStruct {
905 text: String,
906 #[serde(serialize_with = "serialize_bigint", deserialize_with = "deserialize_bigint")]
907 bigint: BigInt,
908 #[serde(serialize_with = "serialize_bigdecimal", deserialize_with = "deserialize_bigdecimal")]
909 bigdecimal: BigDecimal
910 }
911
912 let ts = TestStruct {
913 text: "Hello!".to_string(),
914 bigdecimal: BigDecimal::parse_bytes("55.77e-5".as_bytes(), 10).unwrap(),
915 bigint: BigInt::parse_bytes("123".as_bytes(), 10).unwrap()
916 };
917
918 let r: Params = Params::from_struct(&ts);
919 let m = r.to_struct::<TestStruct>().unwrap();
920
921 assert_eq!(m.bigdecimal, BigDecimal::parse_bytes("55.77e-5".as_bytes(), 10).unwrap());
922 assert_eq!(m.bigint, BigInt::parse_bytes("123".as_bytes(), 10).unwrap());
923}