Skip to main content

mnem_core/codec/
dagjson.rs

1//! DAG-JSON - a human-readable debug / export codec.
2//!
3//! **Never hashed, never canonical.** DAG-JSON is useful for
4//! `mnem cat-file --json`, test-vector inspection, and error messages.
5//! It must never appear on the hash input path - SPEC ยง3 says canonical
6//! encoding is DAG-CBOR and nothing else.
7
8use bytes::Bytes;
9use serde::{Serialize, de::DeserializeOwned};
10
11use crate::error::CodecError;
12
13/// Encode a value as DAG-JSON for debug / inspection.
14///
15/// # Errors
16///
17/// Returns [`CodecError::Encode`] if the value cannot be serialized.
18pub fn to_json_bytes<T: Serialize>(value: &T) -> Result<Bytes, CodecError> {
19    serde_ipld_dagjson::to_vec(value)
20        .map(Bytes::from)
21        .map_err(|e| CodecError::Encode(e.to_string()))
22}
23
24/// Decode a value from DAG-JSON bytes.
25///
26/// # Errors
27///
28/// Returns [`CodecError::Decode`] if the bytes are malformed or do not
29/// match the target type `T`.
30pub fn from_json_bytes<T: DeserializeOwned>(bytes: &[u8]) -> Result<T, CodecError> {
31    serde_ipld_dagjson::from_slice(bytes).map_err(|e| CodecError::Decode(e.to_string()))
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37    use crate::id::NodeId;
38    use serde::{Deserialize, Serialize};
39
40    #[derive(Serialize, Deserialize, PartialEq, Debug)]
41    struct Fixture {
42        id: NodeId,
43        label: String,
44    }
45
46    #[test]
47    fn json_round_trip_restores_value() {
48        let original = Fixture {
49            id: NodeId::from_bytes_raw([3u8; 16]),
50            label: "debug".into(),
51        };
52        let bytes = to_json_bytes(&original).expect("encode");
53        let decoded: Fixture = from_json_bytes(&bytes).expect("decode");
54        assert_eq!(original, decoded);
55    }
56}