1pub mod binary;
22
23use binary::Binary;
24use serde::{Deserialize, Serialize};
25use std::collections::HashMap;
26
27use nom::{
28 IResult, branch::alt,
29 bytes::complete::{escaped, tag, tag_no_case, take_till1, take_while_m_n},
30 character::complete::multispace0, combinator::{map, peek, value as n_value},
31 error::context, multi::separated_list0, number::complete::double,
32 sequence::{delimited, preceded, separated_pair}
33};
34use std::cmp::Ordering;
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub enum DataValue {
38 None,
42
43 String(String),
50
51 Number(f64),
58
59 Boolean(bool),
66
67 List(Vec<DataValue>),
78
79 Dict(HashMap<String, DataValue>),
86
87 Tuple((Box<DataValue>, Box<DataValue>)),
99
100 Binary(binary::Binary),
121}
122
123impl std::string::ToString for DataValue {
124 fn to_string(&self) -> String {
125 match self {
126 DataValue::None => "none".to_string(),
127 DataValue::String(s) => format!("\"{}\"", s),
128 DataValue::Number(n) => n.to_string(),
129 DataValue::Boolean(bool) => match bool {
130 true => "true".to_string(),
131 false => "false".to_string(),
132 },
133 DataValue::List(l) => {
134 let mut res = String::from("[");
135
136 for v in l {
137 res += &format!("{},", v.to_string());
138 }
139
140 if res.len() > 1 { res = res[..res.len() - 1].to_string(); }
141
142 res += "]";
143
144 res
145 }
146 DataValue::Dict(d) => {
147 let mut res = String::from("{");
148
149 for v in d {
150 res += &format!("\"{}\":{},", v.0, v.1.to_string());
151 }
152
153 if res.len() > 1 { res = res[..res.len() - 1].to_string(); }
154
155 res += "}";
156
157 res
158 }
159 DataValue::Tuple(v) => {
160 let first = v.0.to_string();
161 let second = v.1.to_string();
162
163 format!("({},{})", first, second)
164 },
165 DataValue::Binary(v) => {
166 v.to_string()
167 }
168 }
169 }
170}
171
172impl std::cmp::Ord for DataValue {
173 fn cmp(&self, other: &Self) -> Ordering {
174 self.weight().partial_cmp(&other.weight()).unwrap_or(Ordering::Equal)
175 }
176}
177
178impl std::cmp::PartialOrd for DataValue {
179 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
180 Some(self.cmp(other))
181 }
182}
183
184impl std::cmp::PartialEq for DataValue {
185 fn eq(&self, other: &Self) -> bool {
186 self.to_string() == other.to_string()
187 }
188}
189
190impl std::cmp::Eq for DataValue {}
191
192impl DataValue {
193
194 pub fn from(data: &str) -> Self {
214
215 let mut data = data.to_string();
216 if data.len() >= 3 {
217 if &data[0..2] == "b:" && &data[data.len() - 1..] == ":" {
218 let temp = &data[2 .. data.len() - 1];
219 let temp = base64::decode(temp).unwrap_or(vec![]);
220 data = String::from_utf8(temp).unwrap_or(String::new());
221 }
222 }
223
224 match ValueParser::parse(&data) {
225 Ok((_, v)) => v,
226 Err(_) => Self::None,
227 }
228 }
229
230 pub fn from_json(data: &str) -> Self {
231 serde_json::from_str(data).unwrap_or(Self::None)
232 }
233
234 pub fn to_json(&self) -> String {
235 serde_json::to_string(&self).unwrap_or(String::from("None"))
236 }
237
238 pub fn weight(&self) -> f64 {
244
245 if let DataValue::Number(n) = self {
246 return *n;
247 }
248
249 if let DataValue::List(l) = self {
251 let mut total = 0_f64;
252 for item in l {
253 let mut temp = item.weight();
254 if temp == f64::MAX { temp = 0_f64; }
255 total += temp;
256 }
257 return total;
258 }
259
260 if let DataValue::Dict(d) = self {
261 let mut total = 0_f64;
262 for (_, item) in d {
263 let mut temp = item.weight();
264 if temp == f64::MAX { temp = 0_f64; }
265 total += temp;
266 }
267 return total;
268 }
269
270 if let DataValue::Tuple(v) = self {
271 let mut total = 0_f64;
272
273 let mut temp = v.0.weight();
275 if temp == f64::MAX { temp = 0_f64; }
276 total += temp;
277
278 let mut temp = v.1.weight();
280 if temp == f64::MAX { temp = 0_f64; }
281 total += temp;
282
283 return total;
284 }
285
286 f64::MAX
287 }
288
289 pub fn size(&self) -> usize {
290 match self {
291 DataValue::None => 0,
292 DataValue::String(str) => str.len(),
293 DataValue::Number(_) => 8,
294 DataValue::Boolean(_) => 1,
295
296 DataValue::List(list) => {
297 let mut result = 0;
298
299 for item in list {
300 result += item.size();
301 }
302
303 result
304 }
305 DataValue::Dict(dict) => {
306 let mut result = 0;
307
308 for item in dict {
309 result += item.1.size();
310 }
311
312 result
313 }
314
315 DataValue::Tuple(tuple) => tuple.0.size() + tuple.1.size(),
316 DataValue::Binary(bin) => bin.size(),
317 }
318 }
319
320 pub fn datatype(&self) -> String {
321 return match self {
322 DataValue::None => "None",
323 DataValue::String(_) => "String",
324 DataValue::Number(_) => "Number",
325 DataValue::Boolean(_) => "Boolean",
326 DataValue::List(_) => "List",
327 DataValue::Dict(_) => "Dict",
328 DataValue::Tuple(_) => "Tuple",
329 DataValue::Binary(_) => "Binary",
330 }.to_string();
331 }
332
333 pub fn as_string(&self) -> Option<String> {
334 return match self {
335 DataValue::String(val) => Some(val.to_string()),
336 _ => None
337 }
338 }
339
340
341 pub fn as_number(&self) -> Option<f64> {
342 return match self {
343 DataValue::Number(val) => Some(*val),
344 _ => None
345 }
346 }
347
348
349 pub fn as_bool(&self) -> Option<bool> {
350 return match self {
351 DataValue::Boolean(val) => Some(*val),
352 _ => None
353 }
354 }
355
356 pub fn as_tuple(&self) -> Option<(Box<DataValue>, Box<DataValue>)> {
357 return match self {
358 DataValue::Tuple(val) => Some(val.clone()),
359 _ => None
360 }
361 }
362
363 pub fn as_list(&self) -> Option<Vec<DataValue>> {
364 return match self {
365 DataValue::List(val) => Some(val.clone()),
366 _ => None
367 }
368 }
369
370 pub fn as_dict(&self) -> Option<HashMap<String, DataValue>> {
371 return match self {
372 DataValue::Dict(val) => Some(val.clone()),
373 _ => None
374 }
375 }
376
377}
378
379struct ValueParser {}
380impl ValueParser {
381
382 fn normal(message: &str) -> IResult<&str, &str> {
383 take_till1(|c: char| c == '\\' || c == '"' || c.is_ascii_control())(message)
384 }
385
386 fn escapable(i: &str) -> IResult<&str, &str> {
387 context(
388 "escaped",
389 alt((
390 tag("\""),
391 tag("\\"),
392 tag("/"),
393 tag("b"),
394 tag("f"),
395 tag("n"),
396 tag("r"),
397 tag("t"),
398 ValueParser::parse_hex,
399 )),
400 )(i)
401 }
402
403 fn string_format(message: &str) -> IResult<&str, &str> {
404 escaped(ValueParser::normal, '\\', ValueParser::escapable)(message)
405 }
406
407 fn parse_hex(message: &str) -> IResult<&str, &str> {
408 context(
409 "hex string",
410 preceded(
411 peek(tag("u")),
412 take_while_m_n(5, 5, |c: char| c.is_ascii_hexdigit() || c == 'u'),
413 ),
414 )(message)
415 }
416
417 fn parse_string(message: &str) -> IResult<&str, &str> {
418 context(
419 "string",
420 alt((
421 tag("\"\""),
422 delimited(tag("\""), ValueParser::string_format, tag("\"")),
423 )),
424 )(message)
425 }
426
427 fn parse_binary(message: &str) -> IResult<&str, Binary> {
428
429 let result: (&str, &str) = context(
430 "binary",
431 alt((
432 tag("binary!()"),
433 delimited(
434 tag("binary!("),
435 take_till1(|c: char| c == '\\' || c == ')' || c.is_ascii_control()),
436 tag(")")
437 )
438 ))
439 )(message)?;
440
441 Ok((
442 result.0,
443 Binary::from_b64(result.1.to_string()).unwrap_or(Binary::build(vec![]))
444 ))
445 }
446
447 fn parse_number(message: &str) -> IResult<&str, f64> {
448 double(message)
449 }
450
451 fn parse_boolean(message: &str) -> IResult<&str, bool> {
452 let parse_true = n_value(true, tag_no_case("true"));
453 let parse_false = n_value(false, tag_no_case("false"));
454 alt((parse_true, parse_false))(message)
455 }
456
457 fn parse_list(message: &str) -> IResult<&str, Vec<DataValue>> {
458 context(
459 "list",
460 delimited(
461 tag("["),
462 separated_list0(
463 tag(","),
464 delimited(multispace0, ValueParser::parse, multispace0),
465 ),
466 tag("]"),
467 ),
468 )(message)
469 }
470
471 fn parse_dict(message: &str) -> IResult<&str, HashMap<String, DataValue>> {
472 context(
473 "object",
474 delimited(
475 tag("{"),
476 map(
477 separated_list0(
478 tag(","),
479 separated_pair(
480 delimited(multispace0, ValueParser::parse_string, multispace0),
481 tag(":"),
482 delimited(multispace0, ValueParser::parse, multispace0),
483 ),
484 ),
485 |tuple_vec: Vec<(&str, DataValue)>| {
486 tuple_vec
487 .into_iter()
488 .map(|(k, v)| (String::from(k), v))
489 .collect()
490 },
491 ),
492 tag("}"),
493 ),
494 )(message)
495 }
496
497 fn parse_tuple(message: &str) -> IResult<&str, (Box<DataValue>, Box<DataValue>)> {
498 context(
499 "tuple",
500 delimited(
501 tag("("),
502 map(
503 separated_pair(
504 delimited(multispace0, ValueParser::parse, multispace0),
505 tag(","),
506 delimited(multispace0, ValueParser::parse, multispace0),
507 ),
508 |pair: (DataValue, DataValue)| (Box::new(pair.0), Box::new(pair.1)),
509 ),
510 tag(")"),
511 ),
512 )(message)
513 }
514
515 fn parse(message: &str) -> IResult<&str, DataValue> {
516
517 context(
518 "value",
519 delimited(
520 multispace0,
521 alt((
522 map(ValueParser::parse_number, DataValue::Number),
523 map(ValueParser::parse_boolean, DataValue::Boolean),
524 map(ValueParser::parse_string, |s| {
525 DataValue::String(String::from(s))
526 }),
527 map(ValueParser::parse_list, DataValue::List),
528 map(ValueParser::parse_dict, DataValue::Dict),
529 map(ValueParser::parse_tuple, DataValue::Tuple),
530 map(ValueParser::parse_binary, DataValue::Binary)
531 )),
532 multispace0,
533 ),
534 )(&message)
535 }
536}
537
538#[cfg(test)]
539mod test {
540
541 use crate::{DataValue, ValueParser, binary::Binary};
542
543 #[test]
544 fn list() {
545 let value = "[1, 2, 3, 4, 5, 6]";
546 assert_eq!(
547 ValueParser::parse(value),
548 Ok((
549 "",
550 DataValue::List(vec![
551 DataValue::Number(1_f64),
552 DataValue::Number(2_f64),
553 DataValue::Number(3_f64),
554 DataValue::Number(4_f64),
555 DataValue::Number(5_f64),
556 DataValue::Number(6_f64),
557 ])
558 ))
559 );
560 }
561
562 #[test]
563 fn tuple() {
564 let value = "(true,1)";
565 assert_eq!(
566 ValueParser::parse(value),
567 Ok((
568 "",
569 DataValue::Tuple((
570 Box::new(DataValue::Boolean(true)),
571 Box::new(DataValue::Number(1_f64))
572 ))
573 ))
574 );
575 }
576
577 #[test]
578 fn binary() {
579 let message = "binary!(SGVsbG8gV29ybGQ=)";
580 assert_eq!(
581 ValueParser::parse(message),
582 Ok(
583 (
584 "", DataValue::Binary(Binary::build(
585 [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100].to_vec()
586 ))
587 )
588 )
589 )
590 }
591
592 #[test]
593 fn to_json() {
594 let value = DataValue::List(vec![
595 DataValue::Number(1.0),
596 DataValue::Number(2.0),
597 DataValue::Number(3.0)
598 ]);
599
600 assert_eq!(
601 value.to_json(),
602 String::from("{\"List\":[{\"Number\":1.0},{\"Number\":2.0},{\"Number\":3.0}]}")
603 )
604 }
605}