arknet_common/
serialization.rs1use borsh::{BorshDeserialize, BorshSerialize};
14use serde::{de::DeserializeOwned, Serialize};
15
16use crate::errors::{CommonError, Result};
17
18pub fn to_borsh<T: BorshSerialize>(value: &T) -> Result<Vec<u8>> {
26 borsh::to_vec(value).map_err(|e| CommonError::Borsh(e.to_string()))
27}
28
29pub fn from_borsh<T: BorshDeserialize>(bytes: &[u8]) -> Result<T> {
31 borsh::from_slice(bytes).map_err(|e| CommonError::Borsh(e.to_string()))
32}
33
34pub fn to_json<T: Serialize>(value: &T) -> Result<String> {
38 serde_json::to_string(value).map_err(Into::into)
39}
40
41pub fn to_json_pretty<T: Serialize>(value: &T) -> Result<String> {
43 serde_json::to_string_pretty(value).map_err(Into::into)
44}
45
46pub fn from_json<T: DeserializeOwned>(s: &str) -> Result<T> {
48 serde_json::from_str(s).map_err(Into::into)
49}
50
51pub fn to_hex(bytes: &[u8]) -> String {
55 hex::encode(bytes)
56}
57
58pub fn from_hex(s: &str) -> Result<Vec<u8>> {
60 let s = s.strip_prefix("0x").unwrap_or(s);
61 hex::decode(s).map_err(|e| CommonError::InvalidArgument(e.to_string()))
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use crate::types::{Address, PubKey, Signature, SignatureScheme};
68
69 #[test]
70 fn borsh_roundtrip_primitive() {
71 let v: u128 = 42_000_000_000;
72 let bytes = to_borsh(&v).unwrap();
73 let back: u128 = from_borsh(&bytes).unwrap();
74 assert_eq!(v, back);
75 }
76
77 #[test]
78 fn borsh_roundtrip_address() {
79 let a = Address::new([0xAB; 20]);
80 let bytes = to_borsh(&a).unwrap();
81 let back: Address = from_borsh(&bytes).unwrap();
82 assert_eq!(a, back);
83 }
84
85 #[test]
86 fn borsh_roundtrip_pubkey() {
87 let pk = PubKey::ed25519([0xCD; 32]);
88 let bytes = to_borsh(&pk).unwrap();
89 let back: PubKey = from_borsh(&bytes).unwrap();
90 assert_eq!(pk, back);
91 }
92
93 #[test]
94 fn borsh_is_deterministic() {
95 let sig = Signature::ed25519([0xFF; 64]);
96 let a = to_borsh(&sig).unwrap();
97 let b = to_borsh(&sig).unwrap();
98 assert_eq!(a, b, "borsh output must be bit-identical across calls");
99 }
100
101 #[test]
102 fn borsh_encodes_scheme_byte_first() {
103 let pk = PubKey::ed25519([0x00; 32]);
107 let bytes = to_borsh(&pk).unwrap();
108 assert_eq!(bytes[0], SignatureScheme::Ed25519 as u8);
109 }
110
111 #[test]
112 fn borsh_rejects_truncated_input() {
113 let pk = PubKey::ed25519([0xAA; 32]);
114 let mut bytes = to_borsh(&pk).unwrap();
115 bytes.truncate(bytes.len() - 1);
116 let res: Result<PubKey> = from_borsh(&bytes);
117 assert!(res.is_err(), "decoding truncated pubkey must fail");
118 }
119
120 #[test]
121 fn json_roundtrip() {
122 let a = Address::new([0x99; 20]);
123 let s = to_json(&a).unwrap();
124 let back: Address = from_json(&s).unwrap();
125 assert_eq!(a, back);
126 }
127
128 #[test]
129 fn json_pretty_differs_from_json() {
130 let a = Address::new([0x01; 20]);
131 let plain = to_json(&a).unwrap();
132 let pretty = to_json_pretty(&a).unwrap();
133 assert_ne!(plain, pretty);
134 }
135
136 #[test]
137 fn hex_roundtrip_with_and_without_prefix() {
138 let bytes = vec![0xde, 0xad, 0xbe, 0xef];
139 assert_eq!(to_hex(&bytes), "deadbeef");
140 assert_eq!(from_hex("deadbeef").unwrap(), bytes);
141 assert_eq!(from_hex("0xdeadbeef").unwrap(), bytes);
142 }
143
144 #[test]
145 fn hex_rejects_garbage() {
146 assert!(from_hex("not hex").is_err());
147 }
148}