doson/
lib.rs

1//! doson - DataValue Parser
2//!
3//! ```
4//! use doson::DataValue;
5//! use std::collections::HashMap;
6//!
7//! DataValue::String("Hello World".to_string());
8//! DataValue::Number(1_f64);
9//! DataValue::Boolean(true);
10//! DataValue::List(vec![
11//!     DataValue::Number(3.14_f64),
12//! ]);
13//! DataValue::Dict(HashMap::new());
14//! DataValue::Tuple((
15//!     Box::new(DataValue::Number(1_f64)),
16//!     Box::new(DataValue::Number(2_f64)),
17//! ));
18//!
19//! ```
20
21pub 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 Value
39    ///
40    /// Just use for deserialize.
41    None,
42
43    /// String Value
44    ///
45    /// ```
46    /// use doson::DataValue;
47    /// DataValue::String("hello world".to_string());
48    /// ```
49    String(String),
50
51    /// Number Value
52    ///
53    /// ```
54    /// use doson::DataValue;
55    /// DataValue::Number(10_f64);
56    /// ```
57    Number(f64),
58
59    /// Boolean Value
60    ///
61    /// ```
62    /// use doson::DataValue;
63    /// DataValue::Boolean(true);
64    /// ```
65    Boolean(bool),
66
67    /// List Value
68    ///
69    /// ```
70    /// use doson::DataValue;
71    ///     DataValue::List(vec![
72    ///     DataValue::Number(1.0),
73    ///     DataValue::Number(2.0),
74    ///     DataValue::Number(3.0)
75    /// ]);
76    /// ```
77    List(Vec<DataValue>),
78
79    /// Dict Value
80    ///
81    /// ```
82    /// use doson::DataValue;
83    /// DataValue::Dict(std::collections::HashMap::new());
84    /// ```
85    Dict(HashMap<String, DataValue>),
86
87    /// Tuple Value
88    ///
89    /// ```
90    /// use doson::DataValue;
91    /// DataValue::Tuple(
92    ///     (
93    ///         Box::new(DataValue::Boolean(true)),
94    ///         Box::new(DataValue::Boolean(false))
95    ///     )
96    /// );
97    /// ```
98    Tuple((Box<DataValue>, Box<DataValue>)),
99
100    /// Binary Value
101    /// 
102    /// ```
103    /// use doson::DataValue;
104    /// use doson::binary::Binary;
105    /// 
106    /// DataValue::Binary(
107    ///     Binary::build(vec![72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100])
108    /// )
109    /// 
110    /// // or
111    /// 
112    /// let from_base64: = "SGVsbG8gV29ybGQ=";
113    /// 
114    /// DataValue::Binary(
115    ///     Binary::from_base64(from_base64)
116    /// )
117    /// 
118    /// ```
119    /// 
120    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    /// parse `&str` to `DataValue` type:
195    /// - String: "xxx"
196    /// - Number: 114514
197    /// - Boolean: true
198    /// - List: \[1,2,3,4,5\]
199    /// - dict: {"hello": "world"}
200    /// - tuple: (1,2)
201    /// ```
202    /// use doson::DataValue;
203    ///
204    /// assert_eq!(
205    ///     DataValue::from("[1,2,3]"),
206    ///     DataValue::List(vec![
207    ///         DataValue::Number(1_f64),
208    ///         DataValue::Number(2_f64),
209    ///         DataValue::Number(3_f64),
210    ///     ])
211    /// );
212    /// ```
213    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    // 数据权值计算
239    // Number(f64) 的权值等于它本身
240    // 其他基本类型的权值为 f64::MAX
241    // 复合类型则会进行递归计算
242    // 权值主要用于排序等操作
243    pub fn weight(&self) -> f64 {
244
245        if let DataValue::Number(n) = self {
246            return *n;
247        }
248
249        // 计算数组的权重值
250        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            // 元组值0
274            let mut temp = v.0.weight();
275            if temp == f64::MAX { temp = 0_f64; }
276            total += temp;
277
278            // 元组值1
279            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}