hff_core/utilities/
hierarchical.rs

1use crate::{Ecc, Endian, Error, Result, BE, LE, NE};
2use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
3use std::io::{Read, Write};
4
5/// A simple hierarchical storage system for strings.
6#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
7pub struct Hierarchical {
8    /// The primary string key for this level of the hierarchy.
9    key: String,
10    /// The content of this level.
11    content: Vec<String>,
12    /// The optional children.
13    children: Vec<Hierarchical>,
14}
15
16impl Hierarchical {
17    /// Ecc identifier type.
18    const ID: Ecc = Ecc::new("STR_HIER");
19
20    /// Create a new hierarchical structure.
21    pub fn new<T: Into<String>>(key: T, content: Vec<String>, children: Vec<Self>) -> Self {
22        Self {
23            key: key.into(),
24            content,
25            children,
26        }
27    }
28
29    /// Get the key value.
30    pub fn key(&self) -> &str {
31        &self.key
32    }
33
34    /// Get the key mutably.
35    pub fn key_mut(&mut self) -> &mut String {
36        &mut self.key
37    }
38
39    /// Get the content.
40    pub fn content(&self) -> &[String] {
41        &self.content
42    }
43
44    /// Get the content mutably.
45    pub fn content_mut(&mut self) -> &mut Vec<String> {
46        &mut self.content
47    }
48
49    /// Push a new content item.
50    pub fn push<T: Into<String>>(&mut self, item: T) {
51        self.content.push(item.into());
52    }
53
54    /// Get the children.
55    pub fn children(&self) -> &[Self] {
56        &self.children
57    }
58
59    /// Get the children mutably.
60    pub fn children_mut(&mut self) -> &mut Vec<Self> {
61        &mut self.children
62    }
63
64    /// Push a child hierarchy.
65    pub fn push_child(&mut self, item: Self) {
66        self.children.push(item);
67    }
68
69    /// Convert the hierarhcy into a byte buffer.
70    pub fn to_bytes<E: ByteOrder>(self) -> Result<Vec<u8>> {
71        // Create the output buffer to write to.
72        let mut bytes = vec![];
73        let writer: &mut dyn Write = &mut bytes;
74
75        // Write the identification ID.
76        Self::ID.write::<E>(writer)?;
77
78        // Write the structure.
79        self.write_structure::<E>(writer)?;
80
81        // Bytes is now filled and nothing went wrong.
82        // Likely the only real issues possible are running out of memory
83        // due to incorrect content or strings > 65k.
84        Ok(bytes)
85    }
86
87    /// Write a hierarchical structure recursively.
88    fn write_structure<E: ByteOrder>(self, writer: &mut dyn Write) -> Result<()> {
89        // Write the key value.
90        Self::write_string::<E>(&self.key, writer)?;
91
92        // Write the count of content strings.
93        writer.write_u32::<E>(self.content.len() as u32)?;
94        // Write each content string.
95        for s in self.content {
96            Self::write_string::<E>(&s, writer)?;
97        }
98
99        // Write each child.
100        // Write the count of children.
101        writer.write_u32::<E>(self.children.len() as u32)?;
102        for c in self.children {
103            c.write_structure::<E>(writer)?;
104        }
105
106        Ok(())
107    }
108
109    // Write a string into the given stream.
110    fn write_string<E: ByteOrder>(value: &str, writer: &mut dyn Write) -> Result<()> {
111        // Write the key value.
112        if value.len() > core::u16::MAX as usize {
113            return Err(Error::Invalid("String length greater than max u16!".into()));
114        }
115        writer.write_u16::<E>(value.len() as u16)?;
116        writer.write_all(value.as_bytes())?;
117
118        Ok(())
119    }
120
121    /// Create a hierarchical structure from the given bytes.
122    /// TODO: Should probably just give this a reader rather than taking
123    /// the bytes directly..  Hmmm
124    pub fn from_bytes(mut bytes: &[u8]) -> Result<Self> {
125        // Create a reader.
126        let reader: &mut dyn Read = &mut bytes;
127
128        // Detect endian by reading in local endian.
129        let id = Ecc::from(reader.read_u64::<NE>()?);
130        match id.endian(Self::ID) {
131            Some(Endian::Big) => Ok(Self::from_reader::<BE>(reader)?),
132            Some(Endian::Little) => Ok(Self::from_reader::<LE>(reader)?),
133            None => Err(Error::Invalid("Not a valid hierarchical.".into())),
134        }
135    }
136
137    // Read the hierarchy with the given endian.
138    fn from_reader<E: ByteOrder>(reader: &mut dyn Read) -> Result<Self> {
139        // Read the key.
140        let key = Self::read_string::<E>(reader)?;
141
142        // Read the content.
143        let content_count = reader.read_u32::<E>()?;
144        let mut content = vec![];
145        for _ in 0..content_count {
146            content.push(Self::read_string::<E>(reader)?);
147        }
148
149        // Read the children.
150        let child_count = reader.read_u32::<E>()?;
151        let mut children = vec![];
152        for _ in 0..child_count {
153            children.push(Self::from_reader::<E>(reader)?);
154        }
155
156        Ok(Self {
157            key,
158            content,
159            children,
160        })
161    }
162
163    // Read a string from the given reader.
164    fn read_string<E: ByteOrder>(reader: &mut dyn Read) -> Result<String> {
165        let len = reader.read_u16::<E>()?;
166        let mut buffer = vec![0; len as usize];
167        reader.read_exact(buffer.as_mut_slice())?;
168
169        Ok(std::str::from_utf8(buffer.as_slice())?.into())
170    }
171}
172
173#[cfg(test)]
174mod test {
175    use super::*;
176
177    #[test]
178    fn test_serialization() {
179        let test = Hierarchical::new(
180            "Bah",
181            vec![String::from("1"), String::from("2")],
182            vec![Hierarchical::new(
183                "Humbug",
184                vec![String::from("3"), String::from("4")],
185                vec![],
186            )],
187        );
188
189        let bytes = test.clone().to_bytes::<NE>().unwrap();
190        let result = Hierarchical::from_bytes(bytes.as_slice()).unwrap();
191        assert_eq!(test, result);
192    }
193}