1use crate::output::Digits;
6use crate::types::Numeric;
7use chrono_tz::Tz;
8use serde_derive::Serialize;
9use std::fmt;
10
11mod def;
12mod expr;
13mod query;
14#[cfg(test)]
15mod test;
16
17pub use def::{DatePattern, Def, DefEntry, Defs, ExprString, Property};
18pub use expr::{Expr, Precedence};
19pub use query::{Conversion, Query};
20
21#[derive(Debug, Clone, Serialize, Copy, Eq, PartialEq)]
22#[serde(rename_all = "camelCase")]
23pub enum Degree {
24 Celsius,
25 Fahrenheit,
26 Reaumur,
27 Romer,
28 Delisle,
29 Newton,
30}
31
32#[derive(Debug, Clone, Serialize, PartialEq)]
33pub enum DateToken {
34 Literal(String),
35 Number(String, Option<String>),
36 Colon,
37 Dash,
38 Space,
39 Plus,
40 Error(String),
41}
42
43#[derive(Debug, Clone, Serialize, Copy, Eq, PartialEq)]
44#[serde(rename_all = "camelCase")]
45pub enum BinOpType {
46 Add,
47 Sub,
48 Frac,
49 Pow,
50 Equals,
51 ShiftL,
52 ShiftR,
53 Mod,
54 And,
55 Or,
56 Xor,
57}
58
59impl BinOpType {
60 pub fn symbol(self) -> &'static str {
61 match self {
62 BinOpType::Add => " + ",
63 BinOpType::Sub => " - ",
64 BinOpType::Frac => " / ",
65 BinOpType::Pow => "^",
66 BinOpType::Equals => " = ",
67 BinOpType::ShiftL => " << ",
68 BinOpType::ShiftR => " >> ",
69 BinOpType::Mod => " mod ",
70 BinOpType::And => " and ",
71 BinOpType::Or => " or ",
72 BinOpType::Xor => " xor ",
73 }
74 }
75}
76
77#[derive(Debug, Clone, Serialize, PartialEq)]
78pub struct BinOpExpr {
79 pub op: BinOpType,
80 pub left: Box<Expr>,
81 pub right: Box<Expr>,
82}
83
84#[derive(Debug, Clone, Serialize, Copy, Eq, PartialEq)]
85#[serde(rename_all = "camelCase")]
86#[serde(untagged)]
87pub enum UnaryOpType {
88 Negative,
89 Positive,
90 Degree(Degree),
91}
92
93#[derive(Debug, Clone, Serialize, PartialEq)]
94pub struct UnaryOpExpr {
95 pub op: UnaryOpType,
96 pub expr: Box<Expr>,
97}
98
99#[derive(Debug, Clone, Copy, Serialize, PartialEq)]
100#[serde(rename_all = "camelCase")]
101pub enum Function {
102 Sqrt,
103 Exp,
104 Ln,
105 Log2,
106 Log10,
107 Sin,
108 Cos,
109 Tan,
110 Asin,
111 Acos,
112 Atan,
113 Sinh,
114 Cosh,
115 Tanh,
116 Asinh,
117 Acosh,
118 Atanh,
119 Log,
120 Hypot,
121 Atan2,
122}
123
124impl Function {
125 pub fn name(&self) -> &str {
126 match *self {
127 Function::Sqrt => "sqrt",
128 Function::Exp => "exp",
129 Function::Ln => "ln",
130 Function::Log2 => "log2",
131 Function::Log10 => "log10",
132 Function::Sin => "sin",
133 Function::Cos => "cos",
134 Function::Tan => "tan",
135 Function::Asin => "asin",
136 Function::Acos => "acos",
137 Function::Atan => "atan",
138 Function::Sinh => "sinh",
139 Function::Cosh => "cosh",
140 Function::Tanh => "tanh",
141 Function::Asinh => "asinh",
142 Function::Acosh => "acosh",
143 Function::Atanh => "atanh",
144 Function::Log => "log",
145 Function::Hypot => "hypot",
146 Function::Atan2 => "atan2",
147 }
148 }
149
150 pub fn from_name(s: &str) -> Option<Self> {
151 let func = match s {
152 "sqrt" => Function::Sqrt,
153 "exp" => Function::Exp,
154 "ln" => Function::Ln,
155 "log2" => Function::Log2,
156 "log10" => Function::Log10,
157 "sin" => Function::Sin,
158 "cos" => Function::Cos,
159 "tan" => Function::Tan,
160 "asin" => Function::Asin,
161 "acos" => Function::Acos,
162 "atan" => Function::Atan,
163 "sinh" => Function::Sinh,
164 "cosh" => Function::Cosh,
165 "tanh" => Function::Tanh,
166 "asinh" => Function::Asinh,
167 "acosh" => Function::Acosh,
168 "atanh" => Function::Atanh,
169 "log" => Function::Log,
170 "hypot" => Function::Hypot,
171 "atan2" => Function::Atan2,
172 _ => return None,
173 };
174 Some(func)
175 }
176}
177
178impl fmt::Display for Degree {
179 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
180 match *self {
181 Degree::Celsius => write!(fmt, "°C"),
182 Degree::Fahrenheit => write!(fmt, "°F"),
183 Degree::Newton => write!(fmt, "°N"),
184 Degree::Reaumur => write!(fmt, "°Ré"),
185 Degree::Romer => write!(fmt, "°Rø"),
186 Degree::Delisle => write!(fmt, "°De"),
187 }
188 }
189}
190
191impl Degree {
192 pub fn name_base_scale(&self) -> (&str, &str, &str) {
193 match *self {
194 Degree::Celsius => ("C", "zerocelsius", "kelvin"),
195 Degree::Fahrenheit => ("F", "zerofahrenheit", "degrankine"),
196 Degree::Reaumur => ("Ré", "zerocelsius", "reaumur_absolute"),
197 Degree::Romer => ("Rø", "zeroromer", "romer_absolute"),
198 Degree::Delisle => ("De", "zerodelisle", "delisle_absolute"),
199 Degree::Newton => ("N", "zerocelsius", "newton_absolute"),
200 }
201 }
202}
203
204impl fmt::Display for DateToken {
205 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
206 match *self {
207 DateToken::Literal(ref l) => write!(fmt, "{}", l),
208 DateToken::Number(ref i, None) => write!(fmt, "{}", i),
209 DateToken::Number(ref i, Some(ref f)) => write!(fmt, "{}.{}", i, f),
210 DateToken::Colon => write!(fmt, ":"),
211 DateToken::Dash => write!(fmt, "-"),
212 DateToken::Space => write!(fmt, " "),
213 DateToken::Plus => write!(fmt, "+"),
214 DateToken::Error(ref e) => write!(fmt, "<{}>", e),
215 }
216 }
217}
218
219#[cfg(test)]
220mod tests {
221 use crate::ast::DateToken;
222
223 use super::Function;
224
225 const FUNCTIONS: &'static [Function] = &[
226 Function::Sqrt,
227 Function::Exp,
228 Function::Ln,
229 Function::Log2,
230 Function::Log10,
231 Function::Sin,
232 Function::Cos,
233 Function::Tan,
234 Function::Asin,
235 Function::Acos,
236 Function::Atan,
237 Function::Sinh,
238 Function::Cosh,
239 Function::Tanh,
240 Function::Asinh,
241 Function::Acosh,
242 Function::Atanh,
243 Function::Log,
244 Function::Hypot,
245 Function::Atan2,
246 ];
247
248 #[test]
249 fn roundtrip_function_names() {
250 for &func in FUNCTIONS {
251 assert_eq!(Function::from_name(func.name()), Some(func));
252 }
253 }
254
255 #[test]
256 fn date_tokens_display() {
257 assert_eq!(DateToken::Colon.to_string(), ":");
258 assert_eq!(DateToken::Dash.to_string(), "-");
259 assert_eq!(DateToken::Space.to_string(), " ");
260 assert_eq!(DateToken::Plus.to_string(), "+");
261 assert_eq!(DateToken::Literal("a".to_owned()).to_string(), "a");
262 assert_eq!(DateToken::Number("123".to_owned(), None).to_string(), "123");
263 assert_eq!(
264 DateToken::Number("123".to_owned(), Some("456".to_owned())).to_string(),
265 "123.456"
266 );
267 assert_eq!(DateToken::Error("test".to_owned()).to_string(), "<test>");
268 }
269}