Skip to main content

secure_exec_sidecar_core/
bridge_bytes.rs

1use base64::Engine;
2use serde_json::{json, Value};
3
4pub fn encoded_bytes_value(bytes: &[u8]) -> Value {
5    json!({
6        "__agentOSType": "bytes",
7        "base64": base64::engine::general_purpose::STANDARD.encode(bytes),
8    })
9}
10
11pub fn decode_encoded_bytes_value(value: &Value) -> Result<Vec<u8>, String> {
12    let Some(base64_value) = value
13        .get("__agentOSType")
14        .and_then(Value::as_str)
15        .filter(|kind| *kind == "bytes")
16        .and_then(|_| value.get("base64"))
17        .and_then(Value::as_str)
18    else {
19        return Err(String::from("must be a string or encoded bytes payload"));
20    };
21
22    decode_base64(base64_value)
23}
24
25pub fn bridge_buffer_value(bytes: &[u8]) -> Value {
26    json!({
27        "__type": "buffer",
28        "value": base64::engine::general_purpose::STANDARD.encode(bytes),
29    })
30}
31
32pub fn decode_bridge_buffer_value(value: &Value) -> Result<Vec<u8>, String> {
33    let base64_value = value
34        .as_object()
35        .filter(|object| object.get("__type").and_then(Value::as_str) == Some("buffer"))
36        .and_then(|object| object.get("value"))
37        .and_then(Value::as_str)
38        .ok_or_else(|| String::from("must be a serialized bridge buffer"))?;
39
40    decode_base64(base64_value)
41}
42
43pub fn decode_base64(value: &str) -> Result<Vec<u8>, String> {
44    base64::engine::general_purpose::STANDARD
45        .decode(value)
46        .map_err(|error| format!("contains invalid base64: {error}"))
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn round_trips_encoded_bytes_payload() {
55        let value = encoded_bytes_value(b"hello");
56
57        assert_eq!(decode_encoded_bytes_value(&value), Ok(b"hello".to_vec()));
58    }
59
60    #[test]
61    fn round_trips_bridge_buffer_payload() {
62        let value = bridge_buffer_value(b"secret");
63
64        assert_eq!(decode_bridge_buffer_value(&value), Ok(b"secret".to_vec()));
65    }
66
67    #[test]
68    fn rejects_wrong_payload_shapes() {
69        assert_eq!(
70            decode_encoded_bytes_value(&json!({ "__agentOSType": "text", "base64": "aGk=" })),
71            Err(String::from("must be a string or encoded bytes payload"))
72        );
73        assert_eq!(
74            decode_bridge_buffer_value(&json!({ "__type": "bytes", "value": "aGk=" })),
75            Err(String::from("must be a serialized bridge buffer"))
76        );
77    }
78
79    #[test]
80    fn labels_invalid_base64() {
81        assert!(decode_base64("not base64!")
82            .expect_err("invalid base64 should fail")
83            .starts_with("contains invalid base64:"));
84    }
85}