1use std::io::Read;
10
11use ciborium::de::Error as DeserializeError;
12use ciborium::ser::Error as SerializeError;
13use serde::{Deserialize, Serialize};
14use thiserror::Error;
15
16pub fn encode_cbor<T: Serialize>(value: &T) -> Result<Vec<u8>, EncodeError> {
18 let mut bytes = Vec::new();
19 ciborium::ser::into_writer(value, &mut bytes).map_err(Into::<EncodeError>::into)?;
20 Ok(bytes)
21}
22
23pub fn decode_cbor<T: for<'a> Deserialize<'a>, R: Read>(reader: R) -> Result<T, DecodeError> {
25 let value = ciborium::from_reader::<T, R>(reader).map_err(Into::<DecodeError>::into)?;
26 Ok(value)
27}
28
29#[derive(Debug, Error)]
31pub enum EncodeError {
32 #[error("an error occurred while reading bytes: {0}")]
36 Io(std::io::Error),
37
38 #[error("an error occurred while deserializing value: {0}")]
42 Value(String),
43}
44
45impl From<SerializeError<std::io::Error>> for EncodeError {
46 fn from(value: SerializeError<std::io::Error>) -> Self {
47 match value {
48 SerializeError::Io(err) => EncodeError::Io(err),
49 SerializeError::Value(err) => EncodeError::Value(err),
50 }
51 }
52}
53
54#[derive(Debug, Error)]
56pub enum DecodeError {
57 #[error("an error occurred while reading bytes: {0}")]
61 Io(std::io::Error),
62
63 #[error("an error occurred while parsing bytes at position {0}")]
67 Syntax(usize),
68
69 #[error("an error occurred while processing a parsed value at position {0:?}: {1}")]
74 Semantic(Option<usize>, String),
75
76 #[error("recursion limit exceeded while decoding")]
80 RecursionLimitExceeded,
81}
82
83impl From<DeserializeError<std::io::Error>> for DecodeError {
84 fn from(value: DeserializeError<std::io::Error>) -> Self {
85 match value {
86 DeserializeError::Io(err) => DecodeError::Io(err),
87 DeserializeError::Syntax(offset) => DecodeError::Syntax(offset),
88 DeserializeError::Semantic(offset, description) => {
89 DecodeError::Semantic(offset, description)
90 }
91 DeserializeError::RecursionLimitExceeded => DecodeError::RecursionLimitExceeded,
92 }
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use crate::{Body, Header, PrivateKey};
99
100 use super::{decode_cbor, encode_cbor};
101
102 #[test]
103 fn encode_decode() {
104 let private_key = PrivateKey::new();
105 let body = Body::new(&[1, 2, 3]);
106 let mut header = Header::<()> {
107 public_key: private_key.public_key(),
108 payload_size: body.size(),
109 payload_hash: Some(body.hash()),
110 ..Default::default()
111 };
112 header.sign(&private_key);
113
114 let bytes = encode_cbor(&header).unwrap();
115 let header_again: Header<()> = decode_cbor(&bytes[..]).unwrap();
116
117 assert_eq!(header.hash(), header_again.hash());
118 }
119}