use serde_json::Value;
pub(crate) fn wrap_envelope(document: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(document.len() + 96);
out.extend_from_slice(br#"{"type":""#);
out.extend_from_slice(trust_tasks_tsp::ENVELOPE_TYPE.as_bytes());
out.extend_from_slice(br#"","document":"#);
out.extend_from_slice(document);
out.push(b'}');
out
}
pub(crate) fn open_envelope(payload: &[u8]) -> Result<Vec<u8>, String> {
let envelope: Value =
serde_json::from_slice(payload).map_err(|e| format!("TSP payload is not JSON: {e}"))?;
let envelope_type = envelope
.get("type")
.and_then(Value::as_str)
.unwrap_or_default();
if envelope_type != trust_tasks_tsp::ENVELOPE_TYPE {
return Err(format!(
"TSP payload is not a `{}` envelope (got `{envelope_type}`)",
trust_tasks_tsp::ENVELOPE_TYPE
));
}
let document = envelope
.get("document")
.ok_or_else(|| "TSP envelope carries no `document`".to_string())?;
serde_json::to_vec(document).map_err(|e| format!("re-serialise the document: {e}"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn wrapping_and_opening_returns_the_same_document_bytes() {
let document = br#"{"id":"urn:uuid:1","payload":{"a":1,"b":[2,3]}}"#;
let opened = open_envelope(&wrap_envelope(document)).expect("opens");
assert_eq!(
serde_json::from_slice::<serde_json::Value>(&opened).unwrap(),
serde_json::from_slice::<serde_json::Value>(document).unwrap(),
);
}
}