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}