Skip to main content

plugx_input/
rkyv.rs

1use crate::{Input, error::InputDeserializeError, position::InputPath};
2use rkyv::{from_bytes, rancor, to_bytes, util::AlignedVec};
3
4impl Input {
5    /// Serializes `self` to rkyv bytes. This cannot fail.
6    pub fn to_rkyv_bytes(&self) -> AlignedVec {
7        to_bytes::<rancor::Error>(self).expect("Input rkyv serialization cannot fail")
8    }
9
10    /// Deserializes `self` from rkyv bytes with structured errors.
11    pub fn from_rkyv_bytes(bytes: &[u8]) -> Result<Self, InputDeserializeError> {
12        from_bytes::<Input, rancor::Error>(bytes).map_err(|error| {
13            InputDeserializeError::InvalidArchive {
14                path: InputPath::root(),
15                message: error.to_string(),
16            }
17        })
18    }
19}
20
21#[cfg(test)]
22mod tests {
23    use super::*;
24    use crate::error::InputSerializeError;
25    use std::collections::HashMap;
26
27    #[test]
28    fn serialize_is_infallible() {
29        let input = Input::from("hello");
30        let _: Result<AlignedVec, InputSerializeError> = Ok(input.to_rkyv_bytes());
31    }
32
33    #[test]
34    fn roundtrip() {
35        let input = Input::from(HashMap::from([
36            ("name".to_string(), Input::from("plugx")),
37            ("enabled".to_string(), Input::from(true)),
38            ("count".to_string(), Input::from(3)),
39            ("ratio".to_string(), Input::from(0.5)),
40        ]));
41        let bytes = input.to_rkyv_bytes();
42        let decoded = Input::from_rkyv_bytes(&bytes).unwrap();
43        assert_eq!(input, decoded);
44    }
45
46    #[test]
47    fn deep_roundtrip() {
48        let input = Input::from(HashMap::from([(
49            "app".to_string(),
50            Input::from(HashMap::from([(
51                "logging".to_string(),
52                Input::from(HashMap::from([(
53                    "filters".to_string(),
54                    Input::from(HashMap::from([(
55                        "modules".to_string(),
56                        Input::from(HashMap::from([(
57                            "plugx".to_string(),
58                            Input::from(HashMap::from([(
59                                "input".to_string(),
60                                Input::from(HashMap::from([(
61                                    "rkyv".to_string(),
62                                    Input::from(true),
63                                )])),
64                            )])),
65                        )])),
66                    )])),
67                )])),
68            )])),
69        )]));
70
71        let bytes = input.to_rkyv_bytes();
72        let decoded = Input::from_rkyv_bytes(&bytes).unwrap();
73        assert_eq!(input, decoded);
74    }
75
76    #[test]
77    fn rejects_invalid_bytes() {
78        let error = Input::from_rkyv_bytes(&[0u8, 1, 2, 3]).unwrap_err();
79        assert!(matches!(
80            error,
81            InputDeserializeError::InvalidArchive { .. }
82        ));
83    }
84}