jacs_binding_core/
conversion.rs1use base64::{Engine as _, engine::general_purpose};
8use serde_json::{Map as JsonMap, Value};
9
10pub const TYPE_MARKER_KEY: &str = "__type__";
12pub const DATA_KEY: &str = "data";
14pub const TYPE_BYTES: &str = "bytes";
16pub const TYPE_BUFFER: &str = "buffer";
18
19pub fn try_decode_bytes_object(obj: &serde_json::Map<String, Value>) -> Option<Vec<u8>> {
24 if let (Some(Value::String(type_str)), Some(Value::String(data))) =
25 (obj.get(TYPE_MARKER_KEY), obj.get(DATA_KEY))
26 {
27 if type_str == TYPE_BYTES || type_str == TYPE_BUFFER {
28 return general_purpose::STANDARD.decode(data).ok();
29 }
30 }
31 None
32}
33
34pub fn encode_bytes_as_json(bytes: &[u8], type_marker: &str) -> Value {
38 let base64_str = general_purpose::STANDARD.encode(bytes);
39 let mut map = JsonMap::new();
40 map.insert(
41 TYPE_MARKER_KEY.to_string(),
42 Value::String(type_marker.to_string()),
43 );
44 map.insert(DATA_KEY.to_string(), Value::String(base64_str));
45 Value::Object(map)
46}
47
48pub fn encode_bytes_python(bytes: &[u8]) -> Value {
50 encode_bytes_as_json(bytes, TYPE_BYTES)
51}
52
53pub fn encode_bytes_nodejs(bytes: &[u8]) -> Value {
55 encode_bytes_as_json(bytes, TYPE_BUFFER)
56}
57
58pub fn bytes_to_base64(bytes: &[u8]) -> String {
60 general_purpose::STANDARD.encode(bytes)
61}
62
63pub fn base64_to_bytes(encoded: &str) -> Result<Vec<u8>, base64::DecodeError> {
65 general_purpose::STANDARD.decode(encoded)
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_encode_decode_bytes_roundtrip() {
74 let original = vec![1u8, 2, 3, 4, 5, 255, 0, 128];
75
76 let encoded = encode_bytes_python(&original);
78 if let Value::Object(obj) = &encoded {
79 let decoded = try_decode_bytes_object(obj).expect("Should decode");
80 assert_eq!(decoded, original);
81 } else {
82 panic!("Expected object");
83 }
84
85 let encoded_node = encode_bytes_nodejs(&original);
87 if let Value::Object(obj) = &encoded_node {
88 let decoded = try_decode_bytes_object(obj).expect("Should decode");
89 assert_eq!(decoded, original);
90 } else {
91 panic!("Expected object");
92 }
93 }
94
95 #[test]
96 fn test_regular_object_not_decoded() {
97 let mut obj = JsonMap::new();
98 obj.insert("key".to_string(), Value::String("value".to_string()));
99
100 assert!(try_decode_bytes_object(&obj).is_none());
101 }
102
103 #[test]
104 fn test_base64_roundtrip() {
105 let original = b"Hello, World!";
106 let encoded = bytes_to_base64(original);
107 let decoded = base64_to_bytes(&encoded).expect("Should decode");
108 assert_eq!(decoded, original);
109 }
110}