changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate rust/lib/sxp/src/tok.rs

changeset 698: 96958d3eb5b0
parent: 3d78bed56188
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
1
 //! tok.rs --- SXP Tokens
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
2
 /// all possible Tokens. Note that we do not explicitly declare a
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
3
 /// 'nil' variant. The modern rules of S-expressions are implicit in
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
4
 /// the SXP specification.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
5
 use crate::{fmt::WriteFormatter, Error};
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
6
 use serde::{
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
7
   de::{self, Unexpected, Visitor},
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
8
   forward_to_deserialize_any, Deserialize, Deserializer, Serialize, Serializer,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
9
 };
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
10
 use std::{
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
11
   fmt::{self, Debug, Display},
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
12
   hash::{Hash, Hasher},
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
13
   io::{self, Write},
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
14
   str::FromStr,
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
15
 };
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
16
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
17
 /// Token types collected from the output of a type which implements
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
18
 /// Read+Format.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
19
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
20
 pub enum Token {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
21
   ListStart,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
22
   ListEnd,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
23
   Sym(String),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
24
   Str(String),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
25
   Num(String),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
26
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
27
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
28
 impl Display for Token {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
29
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
30
     match self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
31
       Token::ListStart => f.write_str("( "),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
32
       Token::ListEnd => f.write_str(")\n"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
33
       Token::Sym(s) => f.write_str(&format!("{} ", &s)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
34
       Token::Str(s) => f.write_str(&format!("\"{}\" ", &s)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
35
       Token::Num(n) => Display::fmt(&n, f),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
36
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
37
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
38
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
39
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
40
 impl FromStr for Token {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
41
   type Err = Error;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
42
   fn from_str(s: &str) -> Result<Self, Self::Err> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
43
     match s {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
44
       "(" => Ok(Token::ListStart),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
45
       ")" => Ok(Token::ListEnd),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
46
       s => {
189
3d78bed56188 apply clippy fixes
Richard Westhaver <ellis@rwest.io>
parents: 67
diff changeset
47
         if s.starts_with('\"') {
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
48
           Ok(Token::Str(s.trim_matches('"').to_owned()))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
49
         } else if s.chars().next().unwrap().is_numeric() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
50
           Ok(Token::Num(s.to_owned()))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
51
         } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
52
           Ok(Token::Sym(s.to_owned()))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
53
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
54
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
55
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
56
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
57
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
58
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
59
 /// Potential Number
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
60
 #[derive(Copy, Clone)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
61
 pub enum PotNum {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
62
   PosInt(u64),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
63
   NegInt(i64),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
64
   Float(f64),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
65
   // Complex,Rational,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
66
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
67
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
68
 impl PartialEq for PotNum {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
69
   fn eq(&self, other: &Self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
70
     match (self, other) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
71
       (Self::PosInt(a), Self::PosInt(b)) => a == b,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
72
       (Self::NegInt(a), Self::NegInt(b)) => a == b,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
73
       (Self::Float(a), Self::Float(b)) => a == b,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
74
       _ => false,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
75
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
76
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
77
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
78
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
79
 impl Eq for PotNum {}
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
80
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
81
 impl Hash for PotNum {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
82
   fn hash<H: Hasher>(&self, h: &mut H) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
83
     match *self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
84
       PotNum::PosInt(i) => i.hash(h),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
85
       PotNum::NegInt(i) => i.hash(h),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
86
       PotNum::Float(f) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
87
         if f == 0.0f64 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
88
           // use same hash for +/-0.0
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
89
           0.0f64.to_bits().hash(h);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
90
         } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
91
           f.to_bits().hash(h);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
92
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
93
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
94
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
95
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
96
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
97
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
98
 /// String
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
99
 #[derive(Clone, PartialEq, Eq, Hash)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
100
 pub struct Str(std::string::String);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
101
 /// Symbol
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
102
 #[derive(Clone, PartialEq, Eq, Hash)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
103
 pub struct Sym(std::string::String);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
104
 /// Number
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
105
 #[derive(Clone, PartialEq, Eq, Hash)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
106
 pub struct Num(PotNum);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
107
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
108
 impl Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
109
   /// Returns true if the `Number` is an integer between `i64::MIN` and
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
110
   /// `i64::MAX`.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
111
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
112
   /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
113
   /// return the integer value.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
114
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
115
   pub fn is_i64(&self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
116
     // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
117
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
118
       PotNum::PosInt(v) => v <= i64::max_value() as u64,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
119
       PotNum::NegInt(_) => true,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
120
       PotNum::Float(_) => false,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
121
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
122
     // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
123
     // self.as_i64().is_some()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
124
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
125
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
126
   /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
127
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
128
   /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
129
   /// return the integer value.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
130
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
131
   pub fn is_u64(&self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
132
     // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
133
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
134
       PotNum::PosInt(_) => true,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
135
       PotNum::NegInt(_) | PotNum::Float(_) => false,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
136
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
137
     // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
138
     // self.as_u64().is_some()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
139
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
140
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
141
   /// Returns true if the `Number` can be represented by f64.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
142
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
143
   /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
144
   /// return the floating point value.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
145
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
146
   /// Currently this function returns true if and only if both `is_i64` and
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
147
   /// `is_u64` return false but this is not a guarantee in the future.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
148
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
149
   pub fn is_f64(&self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
150
     // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
151
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
152
       PotNum::Float(_) => true,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
153
       PotNum::PosInt(_) | PotNum::NegInt(_) => false,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
154
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
155
     // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
156
     // {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
157
     //     for c in self.n.chars() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
158
     //         if c == '.' || c == 'e' || c == 'E' {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
159
     //             return self.n.parse::<f64>().ok().map_or(false,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
160
     // f64::is_finite);         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
161
     //     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
162
     //     false
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
163
     // }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
164
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
165
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
166
   /// If the `Number` is an integer, represent it as i64 if possible. Returns
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
167
   /// None otherwise.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
168
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
169
   pub fn as_i64(&self) -> Option<i64> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
170
     // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
171
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
172
       PotNum::PosInt(n) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
173
         if n <= i64::max_value() as u64 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
174
           Some(n as i64)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
175
         } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
176
           None
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
177
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
178
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
179
       PotNum::NegInt(n) => Some(n),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
180
       PotNum::Float(_) => None,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
181
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
182
     // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
183
     // self.n.parse().ok()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
184
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
185
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
186
   /// If the `Number` is an integer, represent it as u64 if possible. Returns
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
187
   /// None otherwise.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
188
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
189
   pub fn as_u64(&self) -> Option<u64> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
190
     // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
191
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
192
       PotNum::PosInt(n) => Some(n),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
193
       PotNum::NegInt(_) | PotNum::Float(_) => None,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
194
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
195
     // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
196
     // self.0.parse().ok()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
197
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
198
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
199
   /// Represents the number as f64 if possible. Returns None otherwise.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
200
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
201
   pub fn as_f64(&self) -> Option<f64> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
202
     // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
203
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
204
       PotNum::PosInt(n) => Some(n as f64),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
205
       PotNum::NegInt(n) => Some(n as f64),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
206
       PotNum::Float(n) => Some(n),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
207
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
208
     // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
209
     // self.n.parse::<f64>().ok().filter(|float| float.is_finite())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
210
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
211
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
212
   /// Converts a finite `f64` to a `Number`. Infinite or NaN values are not SXP
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
213
   /// numbers.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
214
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
215
   pub fn from_f64(f: f64) -> Option<Num> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
216
     if f.is_finite() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
217
       let n = PotNum::Float(f);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
218
       // {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
219
       // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
220
       //#[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
221
       // {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
222
       // ryu::Buffer::new().format_finite(f).to_owned()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
223
       // }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
224
       // };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
225
       Some(Num(n))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
226
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
227
       None
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
228
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
229
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
230
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
231
   pub fn as_f32(&self) -> Option<f32> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
232
     // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
233
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
234
       PotNum::PosInt(n) => Some(n as f32),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
235
       PotNum::NegInt(n) => Some(n as f32),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
236
       PotNum::Float(n) => Some(n as f32),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
237
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
238
     // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
239
     // self.n.parse::<f32>().ok().filter(|float| float.is_finite())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
240
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
241
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
242
   pub fn from_f32(f: f32) -> Option<Num> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
243
     if f.is_finite() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
244
       let n = PotNum::Float(f as f64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
245
       // {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
246
       // #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
247
       // #[cfg(feature = "arbitrary_precision")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
248
       // {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
249
       // ryu::Buffer::new().format_finite(f).to_owned()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
250
       // }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
251
       //};
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
252
       Some(Num(n))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
253
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
254
       None
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
255
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
256
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
257
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
258
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
259
 impl Display for Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
260
   fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
261
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
262
       PotNum::PosInt(u) => formatter.write_str(itoa::Buffer::new().format(u)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
263
       PotNum::NegInt(i) => formatter.write_str(itoa::Buffer::new().format(i)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
264
       PotNum::Float(f) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
265
         formatter.write_str(ryu::Buffer::new().format_finite(f))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
266
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
267
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
268
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
269
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
270
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
271
 impl Debug for Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
272
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
273
   fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
274
     write!(formatter, "NUM({})", self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
275
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
276
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
277
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
278
 impl Serialize for Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
279
   fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
280
   where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
281
     S: Serializer,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
282
   {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
283
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
284
       PotNum::PosInt(u) => serializer.serialize_u64(u),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
285
       PotNum::NegInt(i) => serializer.serialize_i64(i),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
286
       PotNum::Float(f) => serializer.serialize_f64(f),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
287
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
288
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
289
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
290
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
291
 impl<'de> Deserialize<'de> for Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
292
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
293
   fn deserialize<D: Deserializer<'de>>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
294
     deserializer: D,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
295
   ) -> Result<Num, D::Error> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
296
     struct NumVisitor;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
297
     impl<'de> Visitor<'de> for NumVisitor {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
298
       type Value = Num;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
299
       fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
300
         formatter.write_str("a SXP number")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
301
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
302
       #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
303
       fn visit_i64<E>(self, value: i64) -> Result<Num, E> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
304
         Ok(value.into())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
305
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
306
       #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
307
       fn visit_u64<E>(self, value: u64) -> Result<Num, E> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
308
         Ok(value.into())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
309
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
310
       #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
311
       fn visit_f64<E: de::Error>(self, value: f64) -> Result<Num, E> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
312
         Num::from_f64(value)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
313
           .ok_or_else(|| de::Error::custom("not a SXP number"))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
314
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
315
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
316
     deserializer.deserialize_any(NumVisitor)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
317
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
318
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
319
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
320
 macro_rules! deserialize_any {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
321
     (@expand [$($num_string:tt)*]) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
322
         #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
323
         fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
324
         where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
325
             V: Visitor<'de>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
326
         {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
327
             match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
328
                 PotNum::PosInt(u) => visitor.visit_u64(u),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
329
                 PotNum::NegInt(i) => visitor.visit_i64(i),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
330
                 PotNum::Float(f) => visitor.visit_f64(f),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
331
             }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
332
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
333
     };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
334
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
335
     (owned) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
336
         deserialize_any!(@expand [n]);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
337
     };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
338
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
339
     (ref) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
340
         deserialize_any!(@expand [n.clone()]);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
341
     };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
342
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
343
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
344
 macro_rules! deserialize_number {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
345
   ($deserialize:ident => $visit:ident) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
346
     #[cfg(not(feature = "arbitrary_precision"))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
347
     fn $deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
348
     where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
349
       V: Visitor<'de>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
350
     {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
351
       self.deserialize_any(visitor)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
352
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
353
   };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
354
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
355
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
356
 impl<'de> Deserializer<'de> for Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
357
   type Error = Error;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
358
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
359
   deserialize_any!(owned);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
360
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
361
   deserialize_number!(deserialize_i8 => visit_i8);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
362
   deserialize_number!(deserialize_i16 => visit_i16);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
363
   deserialize_number!(deserialize_i32 => visit_i32);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
364
   deserialize_number!(deserialize_i64 => visit_i64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
365
   deserialize_number!(deserialize_i128 => visit_i128);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
366
   deserialize_number!(deserialize_u8 => visit_u8);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
367
   deserialize_number!(deserialize_u16 => visit_u16);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
368
   deserialize_number!(deserialize_u32 => visit_u32);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
369
   deserialize_number!(deserialize_u64 => visit_u64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
370
   deserialize_number!(deserialize_u128 => visit_u128);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
371
   deserialize_number!(deserialize_f32 => visit_f32);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
372
   deserialize_number!(deserialize_f64 => visit_f64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
373
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
374
   forward_to_deserialize_any! {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
375
       bool char str string bytes byte_buf option unit unit_struct
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
376
       newtype_struct seq tuple tuple_struct map struct enum identifier
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
377
       ignored_any
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
378
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
379
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
380
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
381
 impl<'de, 'a> Deserializer<'de> for &'a Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
382
   type Error = Error;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
383
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
384
   deserialize_any!(ref);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
385
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
386
   deserialize_number!(deserialize_i8 => visit_i8);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
387
   deserialize_number!(deserialize_i16 => visit_i16);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
388
   deserialize_number!(deserialize_i32 => visit_i32);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
389
   deserialize_number!(deserialize_i64 => visit_i64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
390
   deserialize_number!(deserialize_i128 => visit_i128);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
391
   deserialize_number!(deserialize_u8 => visit_u8);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
392
   deserialize_number!(deserialize_u16 => visit_u16);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
393
   deserialize_number!(deserialize_u32 => visit_u32);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
394
   deserialize_number!(deserialize_u64 => visit_u64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
395
   deserialize_number!(deserialize_u128 => visit_u128);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
396
   deserialize_number!(deserialize_f32 => visit_f32);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
397
   deserialize_number!(deserialize_f64 => visit_f64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
398
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
399
   forward_to_deserialize_any! {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
400
       bool char str string bytes byte_buf option unit unit_struct
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
401
       newtype_struct seq tuple tuple_struct map struct enum identifier
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
402
       ignored_any
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
403
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
404
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
405
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
406
 macro_rules! impl_from_unsigned {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
407
     (
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
408
         $($ty:ty),*
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
409
     ) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
410
         $(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
411
             impl From<$ty> for Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
412
                 #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
413
                 fn from(u: $ty) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
414
                   let n = PotNum::PosInt(u as u64);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
415
                   Num(n)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
416
                 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
417
             }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
418
         )*
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
419
     };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
420
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
421
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
422
 macro_rules! impl_from_signed {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
423
     (
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
424
         $($ty:ty),*
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
425
     ) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
426
         $(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
427
             impl From<$ty> for Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
428
                 #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
429
                 fn from(i: $ty) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
430
                   let n =if i < 0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
431
                     PotNum::NegInt(i as i64)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
432
                   } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
433
                     PotNum::PosInt(i as u64)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
434
                   };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
435
                   Num(n)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
436
                 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
437
             }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
438
         )*
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
439
     };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
440
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
441
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
442
 impl_from_unsigned!(u8, u16, u32, u64, usize);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
443
 impl_from_signed!(i8, i16, i32, i64, isize);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
444
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
445
 impl Num {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
446
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
447
   pub fn unexpected(&self) -> Unexpected {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
448
     match self.0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
449
       PotNum::PosInt(u) => Unexpected::Unsigned(u),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
450
       PotNum::NegInt(i) => Unexpected::Signed(i),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
451
       PotNum::Float(f) => Unexpected::Float(f),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
452
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
453
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
454
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
455
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
456
 /// Represents a character escape code in a type-safe manner.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
457
 pub enum CharEscape {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
458
   /// An escaped quote `"`
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
459
   Quote,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
460
   /// An escaped reverse solidus `\`
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
461
   ReverseSolidus,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
462
   /// An escaped solidus `/`
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
463
   Solidus,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
464
   /// An escaped backspace character (usually escaped as `\b`)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
465
   Backspace,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
466
   /// An escaped form feed character (usually escaped as `\f`)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
467
   FormFeed,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
468
   /// An escaped line feed character (usually escaped as `\n`)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
469
   LineFeed,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
470
   /// An escaped carriage return character (usually escaped as `\r`)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
471
   CarriageReturn,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
472
   /// An escaped tab character (usually escaped as `\t`)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
473
   Tab,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
474
   /// An escaped ASCII plane control character (usually escaped as
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
475
   /// `\u00XX` where `XX` are two hex characters)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
476
   AsciiControl(u8),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
477
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
478
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
479
 impl CharEscape {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
480
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
481
   fn from_escape_table(escape: u8, byte: u8) -> CharEscape {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
482
     match escape {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
483
       self::BB => CharEscape::Backspace,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
484
       self::TT => CharEscape::Tab,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
485
       self::NN => CharEscape::LineFeed,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
486
       self::FF => CharEscape::FormFeed,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
487
       self::RR => CharEscape::CarriageReturn,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
488
       self::QU => CharEscape::Quote,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
489
       self::BS => CharEscape::ReverseSolidus,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
490
       self::UU => CharEscape::AsciiControl(byte),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
491
       _ => unreachable!(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
492
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
493
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
494
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
495
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
496
 pub fn format_escaped_str<W, F>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
497
   writer: &mut W,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
498
   formatter: &mut F,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
499
   value: &str,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
500
 ) -> io::Result<()>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
501
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
502
   W: ?Sized + Write,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
503
   F: ?Sized + WriteFormatter,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
504
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
505
   e!(formatter.begin_string(writer));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
506
   e!(format_escaped_str_contents(writer, formatter, value));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
507
   formatter.end_string(writer)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
508
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
509
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
510
 pub fn format_escaped_str_contents<W, F>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
511
   writer: &mut W,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
512
   formatter: &mut F,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
513
   value: &str,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
514
 ) -> io::Result<()>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
515
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
516
   W: ?Sized + io::Write,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
517
   F: ?Sized + WriteFormatter,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
518
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
519
   let bytes = value.as_bytes();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
520
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
521
   let mut start = 0;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
522
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
523
   for (i, &byte) in bytes.iter().enumerate() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
524
     let escape = ESCAPE[byte as usize];
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
525
     if escape == 0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
526
       continue;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
527
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
528
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
529
     if start < i {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
530
       e!(formatter.write_string_fragment(writer, &value[start..i]));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
531
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
532
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
533
     let char_escape = CharEscape::from_escape_table(escape, byte);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
534
     e!(formatter.write_char_escape(writer, char_escape));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
535
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
536
     start = i + 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
537
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
538
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
539
   if start == bytes.len() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
540
     return Ok(());
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
541
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
542
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
543
   formatter.write_string_fragment(writer, &value[start..])
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
544
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
545
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
546
 const BB: u8 = b'b'; // \x08
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
547
 const TT: u8 = b't'; // \x09
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
548
 const NN: u8 = b'n'; // \x0A
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
549
 const FF: u8 = b'f'; // \x0C
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
550
 const RR: u8 = b'r'; // \x0D
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
551
 const QU: u8 = b'"'; // \x22
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
552
 const BS: u8 = b'\\'; // \x5C
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
553
 const UU: u8 = b'u'; // \x00...\x1F except the ones above
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
554
 const __: u8 = 0;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
555
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
556
 // Lookup table of escape sequences. A value of b'x' at index i means that byte
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
557
 // i is escaped as "\x" in SXP. A value of 0 means that byte i is not escaped.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
558
 static ESCAPE: [u8; 256] = [
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
559
   //   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
560
   UU, UU, UU, UU, UU, UU, UU, UU, BB, TT, NN, UU, FF, RR, UU, UU, // 0
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
561
   UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, // 1
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
562
   __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
563
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
564
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
565
   __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
566
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
567
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
568
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
569
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
570
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
571
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
572
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
573
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
574
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
575
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
576
 ];