1use crate::node::{Node, Token};
6use crate::value::{Map, Value};
7use num_bigint::BigInt;
8use regex::Regex;
9
10#[derive(Clone, Debug)]
12pub enum Spec {
13 Node(Box<Node>),
15 Token(Token),
17 Value(Value),
19 Obj(Vec<(String, Spec)>),
21 Arr(Vec<Spec>),
23 Regex(Regex),
25 Regexp(String),
28}
29
30impl From<Node> for Spec {
31 fn from(n: Node) -> Self {
32 Spec::Node(Box::new(n))
33 }
34}
35impl From<Token> for Spec {
36 fn from(t: Token) -> Self {
37 Spec::Token(t)
38 }
39}
40impl From<Value> for Spec {
41 fn from(v: Value) -> Self {
42 Spec::Value(v)
43 }
44}
45impl From<Regex> for Spec {
46 fn from(r: Regex) -> Self {
47 Spec::Regex(r)
48 }
49}
50impl From<&str> for Spec {
51 fn from(s: &str) -> Self {
52 Spec::Value(Value::from(s))
53 }
54}
55impl From<String> for Spec {
56 fn from(s: String) -> Self {
57 Spec::Value(Value::from(s))
58 }
59}
60impl From<bool> for Spec {
61 fn from(b: bool) -> Self {
62 Spec::Value(Value::from(b))
63 }
64}
65impl From<f64> for Spec {
66 fn from(n: f64) -> Self {
67 Spec::Value(Value::from(n))
68 }
69}
70impl From<i64> for Spec {
71 fn from(n: i64) -> Self {
72 Spec::Value(Value::from(n))
73 }
74}
75impl From<i32> for Spec {
76 fn from(n: i32) -> Self {
77 Spec::Value(Value::from(n))
78 }
79}
80impl From<BigInt> for Spec {
81 fn from(b: BigInt) -> Self {
82 Spec::Value(Value::from(b))
83 }
84}
85impl From<Vec<Spec>> for Spec {
86 fn from(a: Vec<Spec>) -> Self {
87 Spec::Arr(a)
88 }
89}
90impl<const N: usize> From<[Spec; N]> for Spec {
91 fn from(a: [Spec; N]) -> Self {
92 Spec::Arr(a.to_vec())
93 }
94}
95impl<const N: usize> From<[(&str, Spec); N]> for Spec {
96 fn from(pairs: [(&str, Spec); N]) -> Self {
97 Spec::Obj(pairs.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
98 }
99}
100impl From<Vec<(String, Spec)>> for Spec {
101 fn from(pairs: Vec<(String, Spec)>) -> Self {
102 Spec::Obj(pairs)
103 }
104}
105
106pub fn obj<K: Into<String>, S: Into<Spec>>(pairs: impl IntoIterator<Item = (K, S)>) -> Spec {
108 Spec::Obj(
109 pairs
110 .into_iter()
111 .map(|(k, v)| (k.into(), v.into()))
112 .collect(),
113 )
114}
115
116pub fn arr<S: Into<Spec>>(items: impl IntoIterator<Item = S>) -> Spec {
119 Spec::Arr(items.into_iter().map(Into::into).collect())
120}
121
122pub fn null() -> Spec {
124 Spec::Value(Value::Null)
125}
126
127pub fn from_map(m: Map) -> Spec {
129 Spec::Value(Value::Obj(m))
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn conversions() {
138 assert!(matches!(Spec::from(Node::default()), Spec::Node(_)));
139 assert!(matches!(
140 Spec::from(Token::String),
141 Spec::Token(Token::String)
142 ));
143 assert!(matches!(Spec::from(Value::Null), Spec::Value(Value::Null)));
144 assert!(matches!(
145 Spec::from(Regex::new("a").unwrap()),
146 Spec::Regex(_)
147 ));
148 assert!(matches!(Spec::from("s"), Spec::Value(Value::Str(_))));
149 assert!(matches!(
150 Spec::from(String::from("s")),
151 Spec::Value(Value::Str(_))
152 ));
153 assert!(matches!(Spec::from(true), Spec::Value(Value::Bool(true))));
154 assert!(matches!(Spec::from(1.5), Spec::Value(Value::Num(_))));
155 assert!(matches!(Spec::from(1i64), Spec::Value(Value::Num(_))));
156 assert!(matches!(Spec::from(1i32), Spec::Value(Value::Num(_))));
157 assert!(matches!(
158 Spec::from(BigInt::from(1)),
159 Spec::Value(Value::BigInt(_))
160 ));
161 assert!(matches!(Spec::from(vec![Spec::from(1)]), Spec::Arr(_)));
162 assert!(matches!(Spec::from([Spec::from(1)]), Spec::Arr(_)));
163 assert!(matches!(Spec::from([("a", Spec::from(1))]), Spec::Obj(_)));
164 assert!(matches!(
165 Spec::from(vec![("a".to_string(), Spec::from(1))]),
166 Spec::Obj(_)
167 ));
168 assert!(matches!(obj([("a", 1)]), Spec::Obj(_)));
169 assert!(matches!(arr([Token::String]), Spec::Arr(_)));
170 assert!(matches!(null(), Spec::Value(Value::Null)));
171 assert!(matches!(from_map(Map::new()), Spec::Value(Value::Obj(_))));
172 }
173}