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 && (type_str == TYPE_BYTES || type_str == TYPE_BUFFER)
27 {
28 return general_purpose::STANDARD.decode(data).ok();
29 }
30 None
31}
32
33pub fn encode_bytes_as_json(bytes: &[u8], type_marker: &str) -> Value {
37 let base64_str = general_purpose::STANDARD.encode(bytes);
38 let mut map = JsonMap::new();
39 map.insert(
40 TYPE_MARKER_KEY.to_string(),
41 Value::String(type_marker.to_string()),
42 );
43 map.insert(DATA_KEY.to_string(), Value::String(base64_str));
44 Value::Object(map)
45}
46
47pub fn encode_bytes_python(bytes: &[u8]) -> Value {
49 encode_bytes_as_json(bytes, TYPE_BYTES)
50}
51
52pub fn encode_bytes_nodejs(bytes: &[u8]) -> Value {
54 encode_bytes_as_json(bytes, TYPE_BUFFER)
55}
56
57pub fn bytes_to_base64(bytes: &[u8]) -> String {
59 general_purpose::STANDARD.encode(bytes)
60}
61
62pub fn base64_to_bytes(encoded: &str) -> Result<Vec<u8>, base64::DecodeError> {
64 general_purpose::STANDARD.decode(encoded)
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_encode_decode_bytes_roundtrip() {
73 let original = vec![1u8, 2, 3, 4, 5, 255, 0, 128];
74
75 let encoded = encode_bytes_python(&original);
77 if let Value::Object(obj) = &encoded {
78 let decoded = try_decode_bytes_object(obj).expect("Should decode");
79 assert_eq!(decoded, original);
80 } else {
81 panic!("Expected object");
82 }
83
84 let encoded_node = encode_bytes_nodejs(&original);
86 if let Value::Object(obj) = &encoded_node {
87 let decoded = try_decode_bytes_object(obj).expect("Should decode");
88 assert_eq!(decoded, original);
89 } else {
90 panic!("Expected object");
91 }
92 }
93
94 #[test]
95 fn test_regular_object_not_decoded() {
96 let mut obj = JsonMap::new();
97 obj.insert("key".to_string(), Value::String("value".to_string()));
98
99 assert!(try_decode_bytes_object(&obj).is_none());
100 }
101
102 #[test]
103 fn test_base64_roundtrip() {
104 let original = b"Hello, World!";
105 let encoded = bytes_to_base64(original);
106 let decoded = base64_to_bytes(&encoded).expect("Should decode");
107 assert_eq!(decoded, original);
108 }
109}