1use std::collections::{BTreeMap, LinkedList};
12use std::i64;
13use types::Tag;
14
15#[derive(Clone, Debug, PartialEq, PartialOrd)]
17pub enum Value {
18 Array(Vec<Value>),
19 Bool(bool),
20 Break,
21 Bytes(Bytes),
22 F32(f32),
23 F64(f64),
24 I8(i8),
25 I16(i16),
26 I32(i32),
27 I64(i64),
28 Int(Int),
29 Map(BTreeMap<Key, Value>),
30 Null,
31 Simple(Simple),
32 Tagged(Tag, Box<Value>),
33 Text(Text),
34 U8(u8),
35 U16(u16),
36 U32(u32),
37 U64(u64),
38 Undefined
39}
40
41#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
48pub enum Int {
49 Neg(u64),
50 Pos(u64)
51}
52
53impl Int {
54 pub fn from_u64(n: u64) -> Int {
55 Int::Pos(n)
56 }
57
58 pub fn from_i64(n: i64) -> Int {
59 if n < 0 {
60 Int::Neg(i64::abs(n) as u64 - 1)
61 } else {
62 Int::Pos(n as u64)
63 }
64 }
65
66 pub fn i64(&self) -> Option<i64> {
69 match *self {
70 Int::Neg(n) if n <= i64::MAX as u64 => Some(-1 - n as i64),
71 Int::Pos(n) if n <= i64::MAX as u64 => Some(n as i64),
72 _ => None
73 }
74 }
75
76 pub fn u64(&self) -> Option<u64> {
79 match *self {
80 Int::Pos(n) => Some(n),
81 _ => None
82 }
83 }
84}
85
86#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
88pub enum Text {
89 Text(String),
90 Chunks(LinkedList<String>)
91}
92
93#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
95pub enum Bytes {
96 Bytes(Vec<u8>),
97 Chunks(LinkedList<Vec<u8>>)
98}
99
100#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
104pub enum Simple {
105 Unassigned(u8),
106 Reserved(u8)
107}
108
109#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
112pub enum Key {
113 Bool(bool),
114 Bytes(Bytes),
115 Int(Int),
116 Text(Text)
117}
118
119impl Key {
120 pub fn u64(n: u64) -> Key {
121 Key::Int(Int::from_u64(n))
122 }
123
124 pub fn i64(n: i64) -> Key {
125 Key::Int(Int::from_i64(n))
126 }
127}
128
129pub struct Cursor<'r> {
133 value: Option<&'r Value>
134}
135
136impl<'r> Cursor<'r> {
137 pub fn new(v: &'r Value) -> Cursor<'r> {
138 Cursor { value: Some(v) }
139 }
140
141 fn of(v: Option<&'r Value>) -> Cursor<'r> {
142 Cursor { value: v }
143 }
144
145 pub fn at(&self, i: usize) -> Cursor<'r> {
146 match self.value {
147 Some(&Value::Array(ref a)) => Cursor::of(a.get(i)),
148 _ => Cursor::of(None)
149 }
150 }
151
152 pub fn get(&self, k: Key) -> Cursor<'r> {
153 match self.value {
154 Some(&Value::Map(ref m)) => Cursor::of(m.get(&k)),
155 _ => Cursor::of(None)
156 }
157 }
158
159 pub fn field(&self, s: &str) -> Cursor<'r> {
160 self.get(Key::Text(Text::Text(String::from(s))))
161 }
162
163 pub fn value(&self) -> Option<&Value> {
164 self.value
165 }
166
167 pub fn opt(&self) -> Option<Cursor<'r>> {
168 match self.value {
169 Some(&Value::Null) => None,
170 Some(ref v) => Some(Cursor::new(v)),
171 _ => None
172 }
173 }
174
175 pub fn maybe(&self) -> Option<Cursor<'r>> {
176 match self.value {
177 Some(&Value::Undefined) => None,
178 Some(ref v) => Some(Cursor::new(v)),
179 _ => None
180 }
181 }
182
183 pub fn bool(&self) -> Option<bool> {
184 match self.value {
185 Some(&Value::Bool(x)) => Some(x),
186 _ => None
187 }
188 }
189
190 pub fn bytes(&self) -> Option<&Bytes> {
191 match self.value {
192 Some(&Value::Bytes(ref x)) => Some(x),
193 _ => None
194 }
195 }
196
197 pub fn bytes_plain(&self) -> Option<&Vec<u8>> {
198 match self.value {
199 Some(&Value::Bytes(Bytes::Bytes(ref x))) => Some(x),
200 _ => None
201 }
202 }
203
204 pub fn bytes_chunked(&self) -> Option<&LinkedList<Vec<u8>>> {
205 match self.value {
206 Some(&Value::Bytes(Bytes::Chunks(ref x))) => Some(x),
207 _ => None
208 }
209 }
210
211 pub fn text(&self) -> Option<&Text> {
212 match self.value {
213 Some(&Value::Text(ref x)) => Some(x),
214 _ => None
215 }
216 }
217
218 pub fn text_plain(&self) -> Option<&String> {
219 match self.value {
220 Some(&Value::Text(Text::Text(ref x))) => Some(x),
221 _ => None
222 }
223 }
224
225 pub fn text_chunked(&self) -> Option<&LinkedList<String>> {
226 match self.value {
227 Some(&Value::Text(Text::Chunks(ref x))) => Some(x),
228 _ => None
229 }
230 }
231
232 pub fn float32(&self) -> Option<f32> {
233 match self.value {
234 Some(&Value::F32(x)) => Some(x),
235 _ => None
236 }
237 }
238
239 pub fn float64(&self) -> Option<f64> {
240 match self.value {
241 Some(&Value::F64(x)) => Some(x),
242 _ => None
243 }
244 }
245
246 pub fn u8(&self) -> Option<u8> {
247 match self.value {
248 Some(&Value::U8(x)) => Some(x),
249 _ => None
250 }
251 }
252
253 pub fn u16(&self) -> Option<u16> {
254 match self.value {
255 Some(&Value::U16(x)) => Some(x),
256 _ => None
257 }
258 }
259
260 pub fn u32(&self) -> Option<u32> {
261 match self.value {
262 Some(&Value::U32(x)) => Some(x),
263 _ => None
264 }
265 }
266
267 pub fn u64(&self) -> Option<u64> {
268 match self.value {
269 Some(&Value::U64(x)) => Some(x),
270 _ => None
271 }
272 }
273
274 pub fn i8(&self) -> Option<i8> {
275 match self.value {
276 Some(&Value::I8(x)) => Some(x),
277 _ => None
278 }
279 }
280
281 pub fn i16(&self) -> Option<i16> {
282 match self.value {
283 Some(&Value::I16(x)) => Some(x),
284 _ => None
285 }
286 }
287
288 pub fn i32(&self) -> Option<i32> {
289 match self.value {
290 Some(&Value::I32(x)) => Some(x),
291 _ => None
292 }
293 }
294
295 pub fn i64(&self) -> Option<i64> {
296 match self.value {
297 Some(&Value::I64(x)) => Some(x),
298 _ => None
299 }
300 }
301}
302
303pub fn check(value: &Value) -> bool {
307 fn fun(t: Tag, b: &Value) -> bool {
308 match (t, b) {
309 (Tag::DateTime, &Value::Text(_)) => true,
310 (Tag::Timestamp, &Value::U8(_)) => true,
311 (Tag::Timestamp, &Value::U16(_)) => true,
312 (Tag::Timestamp, &Value::U32(_)) => true,
313 (Tag::Timestamp, &Value::U64(_)) => true,
314 (Tag::Timestamp, &Value::I8(_)) => true,
315 (Tag::Timestamp, &Value::I16(_)) => true,
316 (Tag::Timestamp, &Value::I32(_)) => true,
317 (Tag::Timestamp, &Value::I64(_)) => true,
318 (Tag::Timestamp, &Value::F32(_)) => true,
319 (Tag::Timestamp, &Value::F64(_)) => true,
320 (Tag::Bignum, &Value::Bytes(_)) => true,
321 (Tag::NegativeBignum, &Value::Bytes(_)) => true,
322 (Tag::ToBase64, _) => true,
323 (Tag::ToBase64Url, _) => true,
324 (Tag::ToBase16, _) => true,
325 (Tag::Cbor, &Value::Bytes(_)) => true,
326 (Tag::Uri, &Value::Text(_)) => true,
327 (Tag::Base64, &Value::Text(_)) => true,
328 (Tag::Base64Url, &Value::Text(_)) => true,
329 (Tag::Regex, &Value::Text(_)) => true,
330 (Tag::Mime, &Value::Text(_)) => true,
331 (Tag::CborSelf, _) => true,
332 (Tag::Decimal, &Value::Array(ref a))
333 | (Tag::Bigfloat, &Value::Array(ref a)) => {
334 if a.len() != 2 {
335 return false
336 }
337 let is_integral = |v: &Value| {
338 match *v {
339 Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => true,
340 Value::I8(_) | Value::I16(_) | Value::I32(_) | Value::I64(_) => true,
341 _ => false
342 }
343 };
344 let is_bignum = |v: &Value| {
345 fun(Tag::Bignum, v) || fun(Tag::NegativeBignum, v)
346 };
347 let ref e = a[0];
348 let ref m = a[1];
349 is_integral(e) && (is_integral(m) || is_bignum(m))
350 }
351 (Tag::Unassigned(_), _) => true,
352 _ => false
353 }
354 }
355
356 match *value {
357 Value::Tagged(t, ref b) => fun(t, &*b),
358 _ => false
359 }
360}