1mod type_id;
2
3const MAX_TUPLE: u8 = 250;
4#[derive(Debug, Clone, PartialOrd, PartialEq)]
10pub enum Key {
11 Boolean(bool),
12 Number(ordered_float::NotNan<f64>),
13 String(String),
14 Table(Vec<(Key, Value)>),
15}
16
17impl Key {
18 pub fn get_bool(&self) -> Option<bool> {
19 match self {
20 Key::Boolean(inner) => Some(*inner),
21 _ => None,
22 }
23 }
24
25 pub fn get_number(&self) -> Option<ordered_float::NotNan<f64>> {
26 match self {
27 Key::Number(inner) => Some(*inner),
28 _ => None,
29 }
30 }
31
32 pub fn get_string(&self) -> Option<&str> {
33 match self {
34 Key::String(inner) => Some(inner.as_str()),
35 _ => None,
36 }
37 }
38
39 pub fn get_table(&self) -> Option<&[(Key, Value)]> {
40 match self {
41 Key::Table(inner) => Some(inner.as_slice()),
42 _ => None,
43 }
44 }
45}
46
47#[derive(Debug, Clone, PartialOrd, PartialEq)]
48pub enum Value {
49 Nil,
50 Boolean(bool),
51 Number(f64),
52 String(String),
53 Table(Vec<(Key, Value)>),
54}
55
56impl Value {
57 pub fn get_nil(&self) -> Option<()> {
58 match self {
59 Value::Nil => Some(()),
60 _ => None,
61 }
62 }
63
64 pub fn get_bool(&self) -> Option<bool> {
65 match self {
66 Value::Boolean(inner) => Some(*inner),
67 _ => None,
68 }
69 }
70
71 pub fn get_number(&self) -> Option<f64> {
72 match self {
73 Value::Number(inner) => Some(*inner),
74 _ => None,
75 }
76 }
77
78 pub fn get_string(&self) -> Option<&str> {
79 match self {
80 Value::String(inner) => Some(inner.as_str()),
81 _ => None,
82 }
83 }
84
85 pub fn get_table(&self) -> Option<&[(Key, Value)]> {
86 match self {
87 Value::Table(inner) => Some(inner.as_slice()),
88 _ => None,
89 }
90 }
91}
92
93fn load_element_count(data: &[u8]) -> nom::IResult<&[u8], u8> {
94 let (data, count) = nom::number::complete::u8(data)?;
95 if count > MAX_TUPLE {
96 Err(nom::Err::Error(nom::error::make_error(
97 data,
98 nom::error::ErrorKind::LengthValue,
99 )))
100 } else {
101 Ok((data, count))
102 }
103}
104
105fn load_type_id(data: &[u8]) -> nom::IResult<&[u8], type_id::TypeIdentifier> {
106 nom::combinator::map_res(nom::number::complete::u8, std::convert::TryInto::try_into)(data)
107}
108
109fn load_key_value(data: &[u8]) -> nom::IResult<&[u8], (Key, Value)> {
110 let (data, key) = load_key(data)?;
111 let (data, value) = load_value(data)?;
112 Ok((data, (key, value)))
113}
114
115fn load_string(data: &[u8]) -> nom::IResult<&[u8], String> {
116 let (data, count) = nom::number::complete::le_u32(data)?;
117 let (data, str) =
118 nom::combinator::map_res(nom::bytes::complete::take(count), std::str::from_utf8)(data)?;
119 Ok((data, str.to_owned()))
120}
121
122fn load_table(data: &[u8]) -> nom::IResult<&[u8], Vec<(Key, Value)>> {
123 let (data, array_size) = nom::number::complete::le_u32(data)?;
124 let (data, hash_size) = nom::number::complete::le_u32(data)?;
125 let total_size = array_size + hash_size;
126 nom::multi::count(load_key_value, total_size as usize)(data)
129}
130
131fn load_key(data: &[u8]) -> nom::IResult<&[u8], Key> {
132 use type_id::TypeIdentifier;
133
134 let (data, ty) = load_type_id(data)?;
135 match ty {
136 TypeIdentifier::NIL => Err(nom::Err::Error(nom::error::make_error(
137 data,
138 nom::error::ErrorKind::Digit,
139 ))),
140 TypeIdentifier::FALSE => Ok((data, Key::Boolean(false))),
141 TypeIdentifier::TRUE => Ok((data, Key::Boolean(true))),
142 TypeIdentifier::NUMBER => {
143 fn parse_non_nan(n: f64) -> Result<Key, nom::error::ErrorKind> {
144 let n = std::convert::TryFrom::try_from(n)
145 .map_err(|_err| nom::error::ErrorKind::Digit)?;
146 Ok(Key::Number(n))
147 }
148 nom::combinator::map_res(nom::number::complete::le_f64, parse_non_nan)(data)
149 }
150 TypeIdentifier::STRING => load_string(data).map(|(data, value)| (data, Key::String(value))),
151 TypeIdentifier::TABLE => load_table(data).map(|(data, table)| (data, Key::Table(table))),
152 }
153}
154
155fn load_value(data: &[u8]) -> nom::IResult<&[u8], Value> {
156 use type_id::TypeIdentifier;
157
158 let (data, ty) = load_type_id(data)?;
159 match ty {
160 TypeIdentifier::NIL => Ok((data, Value::Nil)),
161 TypeIdentifier::FALSE => Ok((data, Value::Boolean(false))),
162 TypeIdentifier::TRUE => Ok((data, Value::Boolean(true))),
163 TypeIdentifier::NUMBER => {
164 nom::combinator::map(nom::number::complete::le_f64, |n| Value::Number(n.into()))(data)
165 }
166 TypeIdentifier::STRING => {
167 load_string(data).map(|(data, string)| (data, Value::String(string)))
168 }
169 TypeIdentifier::TABLE => load_table(data).map(|(data, table)| (data, Value::Table(table))),
170 }
171}
172
173fn save_table(result: &mut Vec<u8>, table: &[(Key, Value)]) {
174 fn array_size(table: &[(Key, Value)]) -> usize {
177 let mut size = 0;
178 for index in 1..=(table.len()) {
179 let v = table.iter().find(|(key, _value)| {
180 if let Some(v) = key.get_number() {
181 index == v.into_inner() as usize
182 } else {
183 false
184 }
185 });
186 if v.is_some() {
187 size = index;
188 } else {
189 break;
190 }
191 }
192 size
193 }
194
195 let array = array_size(table);
196 let hash_size = table.len() - array;
197 result.push(type_id::TypeIdentifier::TABLE as u8);
198 result.extend_from_slice(&((array as u32).to_le_bytes()));
199 result.extend_from_slice(&((hash_size as u32).to_le_bytes()));
200
201 for (key, value) in table {
203 save_key(result, key);
204 save_value(result, value);
205 }
206}
207
208fn save_key(result: &mut Vec<u8>, key: &Key) {
209 match key {
210 Key::Boolean(inner) => match *inner {
211 true => result.push(type_id::TypeIdentifier::TRUE as u8),
212 false => result.push(type_id::TypeIdentifier::FALSE as u8),
213 },
214 Key::Number(inner) => {
215 result.push(type_id::TypeIdentifier::NUMBER as u8);
216 result.extend_from_slice(&inner.into_inner().to_le_bytes());
217 }
218 Key::String(inner) => {
219 result.push(type_id::TypeIdentifier::STRING as u8);
220 result.extend_from_slice(&(inner.len() as u32).to_le_bytes());
221 result.extend_from_slice(inner.as_bytes());
222 }
223 Key::Table(table) => save_table(result, table),
224 }
225}
226
227fn save_value(result: &mut Vec<u8>, value: &Value) {
228 match value {
229 Value::Nil => result.push(type_id::TypeIdentifier::NIL as u8),
230 Value::Boolean(inner) => match *inner {
231 true => result.push(type_id::TypeIdentifier::TRUE as u8),
232 false => result.push(type_id::TypeIdentifier::FALSE as u8),
233 },
234 Value::Number(inner) => {
235 result.push(type_id::TypeIdentifier::NUMBER as u8);
236 result.extend_from_slice(&inner.to_le_bytes());
237 }
238 Value::String(inner) => {
239 result.push(type_id::TypeIdentifier::STRING as u8);
240 result.extend_from_slice(&(inner.len() as u32).to_le_bytes());
241 result.extend_from_slice(inner.as_bytes());
242 }
243 Value::Table(table) => save_table(result, table),
244 }
245}
246
247pub fn load(data: &[u8]) -> nom::IResult<&[u8], Vec<Value>> {
248 nom::multi::length_count(load_element_count, load_value)(data)
249}
250
251pub fn save(data: &[Value]) -> Vec<u8> {
252 let mut result = Vec::new();
253 result.push(data.len() as u8);
254 for datum in data {
255 save_value(&mut result, datum);
256 }
257 result
258}