Skip to main content

plugx_input/
rkyv.rs

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