1use crate::time_serde::*;
14use crate::AvialError;
15use crate::Locutor;
16use crate::Operator;
17use crate::{Entity, Tag, Token};
18use ascii::AsciiChar;
19use ascii::AsciiString;
20use ascii::IntoAsciiString;
21use std::collections::HashMap;
22use std::num::IntErrorKind;
23use std::{cmp::PartialEq, fmt, str::FromStr};
24use thiserror::Error;
25use time::OffsetDateTime;
26
27#[derive(Clone, Debug, PartialEq)]
29pub struct UnimplementedValue(pub String);
30
31#[derive(Clone, PartialEq, Debug)]
32pub enum Value {
33 Null(String),
34 Avesterra(String),
35 Boolean(bool),
36 Character(AsciiChar),
37 String(AsciiString),
38 Text(String),
39 Integer(i64),
40 Float(f64),
41 Entity(Entity),
42 Time(OffsetDateTime),
43 Web(String),
44 Interchange(String),
45 Data(Vec<u8>),
46 Exception(AvialError),
47 Operator(Operator),
48 Function(Entity),
49 Measurement(UnimplementedValue),
50 Locutor(Box<Locutor>),
51 Authorization(Token),
52 Date(UnimplementedValue),
53 Aggregate(HashMap<String, Value>),
54 Array(Vec<Value>),
55 Variable(String, Box<Value>),
56}
57
58impl Value {
59 pub const NULL: Value = Value::Null(String::new());
60
61 pub fn is_null(&self) -> bool {
62 matches!(self, Value::Null(_))
63 }
64}
65
66#[derive(Error, Debug)]
67#[error("Value of type {actual:?} cannot be read as {expected:?}")]
68pub struct ConvertValueError {
69 expected: Tag,
70 actual: Tag,
71}
72
73#[derive(Error, Debug)]
74#[error("Fail to create value of type {tag:?} from string {string:?}: {error}")]
75pub struct ValueCreationError {
76 tag: Tag,
77 string: String,
78 error: Box<dyn std::error::Error + std::marker::Sync + std::marker::Send>,
79}
80
81impl Default for Value {
82 fn default() -> Self {
83 Self::Null(String::new())
84 }
85}
86
87macro_rules! getter {
88 ($name:ident, $tag:ident, $type:ty) => {
89 pub fn $name(self) -> Result<$type, ConvertValueError> {
90 match self {
91 Value::$tag(val) => Ok(val),
92 _ => Err(ConvertValueError {
93 expected: Tag::$tag,
94 actual: self.get_tag(),
95 }),
96 }
97 }
98 };
99}
100
101impl Value {
102 pub fn get_tag(&self) -> Tag {
103 match *self {
104 Value::Null(_) => Tag::Null,
105 Value::Avesterra(_) => Tag::Avesterra,
106 Value::Boolean(_) => Tag::Boolean,
107 Value::Character(_) => Tag::Character,
108 Value::String(_) => Tag::String,
109 Value::Text(_) => Tag::Text,
110 Value::Integer(_) => Tag::Integer,
111 Value::Float(_) => Tag::Float,
112 Value::Entity(_) => Tag::Entity,
113 Value::Time(_) => Tag::Time,
114 Value::Web(_) => Tag::Web,
115 Value::Interchange(_) => Tag::Interchange,
116 Value::Data(_) => Tag::Data,
117 Value::Exception(_) => Tag::Exception,
118 Value::Operator(_) => Tag::Operator,
119 Value::Function(_) => Tag::Function,
120 Value::Measurement(_) => Tag::Measurement,
121 Value::Locutor(_) => Tag::Locutor,
122 Value::Authorization(_) => Tag::Authorization,
123 Value::Date(_) => Tag::Date,
124 Value::Aggregate(_) => Tag::Aggregate,
125 Value::Array(_) => Tag::Array,
126 Value::Variable(_, _) => Tag::Variable,
127 }
128 }
129
130 getter!(null, Null, String);
131 getter!(avesterra, Avesterra, String);
132 getter!(boolean, Boolean, bool);
133 getter!(character, Character, AsciiChar);
134 getter!(string, String, AsciiString);
135 getter!(text, Text, String);
136 getter!(integer, Integer, i64);
137 getter!(float, Float, f64);
138 getter!(entity, Entity, Entity);
139 getter!(time, Time, OffsetDateTime);
140 getter!(web, Web, String);
141 getter!(interchange, Interchange, String);
142 getter!(data, Data, Vec<u8>);
143 getter!(exception, Exception, AvialError);
144 getter!(operator, Operator, Operator);
145 getter!(function, Function, Entity);
146 getter!(locutor, Locutor, Box<Locutor>);
148 getter!(authorization, Authorization, Token);
149 getter!(aggregate, Aggregate, HashMap<String, Value>);
151 getter!(array, Array, Vec<Value>);
152
153 pub fn variable(self) -> Result<(String, Box<Value>), ConvertValueError> {
154 match self {
155 Value::Variable(name, val) => Ok((name, val)),
156 _ => Err(ConvertValueError {
157 expected: Tag::Variable,
158 actual: self.get_tag(),
159 }),
160 }
161 }
162
163 pub(crate) fn new(tag: Tag, s: String) -> Result<Value, ValueCreationError> {
164 let result = match tag {
165 Tag::Null => Value::Null(s),
166 Tag::Avesterra => Value::Avesterra(s),
167 Tag::Boolean => Value::Boolean(bool::from_str(&s.to_lowercase()).map_err(|_| {
168 ValueCreationError {
169 tag,
170 string: s.to_owned(),
171 error: "provided string was not `true` or `false` (case insensitive)".into(),
172 }
173 })?),
174 Tag::Character => {
175 let mut b = s.bytes();
176 let char = match (b.next(), b.next()) {
177 (Some(b), None) => AsciiChar::from_ascii(b).map_err(|e| ValueCreationError {
178 tag,
179 string: s.to_owned(),
180 error: Box::new(e),
181 }),
182 _ => Err(ValueCreationError {
183 tag,
184 string: s.to_owned(),
185 error: "ascii character is not 1 byte".into(),
186 }),
187 };
188 Value::Character(char?)
189 }
190 Tag::String => {
191 Value::String(s.into_ascii_string().map_err(|e| ValueCreationError {
192 tag,
193 string: e.clone().into_source(),
194 error: Box::new(e),
195 })?)
196 }
197 Tag::Text => Value::Text(s),
198 Tag::Integer => Value::Integer(i64::from_str(&s).map_err(|e| ValueCreationError {
199 tag,
200 string: s.to_owned(),
201 error: match e.kind() {
202 IntErrorKind::PosOverflow | IntErrorKind::NegOverflow => {
203 "integer out of range, value does not fit in 64 bytes signed integer".into()
204 }
205 _ => Box::new(e),
206 },
207 })?),
208 Tag::Float => Value::Float(f64::from_str(&s).map_err(|e| ValueCreationError {
209 tag,
210 string: s.to_owned(),
211 error: Box::new(e),
212 })?),
213 Tag::Entity => {
214 Value::Entity(Entity::from_str_strict(&s).map_err(|e| ValueCreationError {
215 tag,
216 string: s.to_owned(),
217 error: Box::new(e),
218 })?)
219 }
220 Tag::Time => {
221 Value::Time(
222 unix_timestamp_string_to_time(&s).map_err(|e| ValueCreationError {
223 tag,
224 string: s.to_owned(),
225 error: Box::new(e),
226 })?,
227 )
228 }
229 Tag::Web => Value::Web(s),
230 Tag::Interchange => Value::Interchange(s),
231 Tag::Data => Value::Data(base16::decode(&s).map_err(|e| ValueCreationError {
232 tag,
233 string: s.to_owned(),
234 error: Box::new(e),
235 })?),
236 Tag::Exception => {
237 Value::Exception(serde_json::from_str(&s).map_err(|e| ValueCreationError {
238 tag,
239 string: s.to_owned(),
240 error: Box::new(e),
241 })?)
242 }
243 Tag::Operator => Value::Operator(
244 serde_json::from_value(serde_json::Value::String(s.clone())).map_err(|e| {
245 ValueCreationError {
246 tag,
247 string: s.to_owned(),
248 error: Box::new(e),
249 }
250 })?,
251 ),
252 Tag::Function => {
253 Value::Function(Entity::from_str_strict(&s).map_err(|e| ValueCreationError {
254 tag,
255 string: s.to_owned(),
256 error: Box::new(e),
257 })?)
258 }
259 Tag::Measurement => Value::Measurement(UnimplementedValue(s)),
260 Tag::Locutor => Value::Locutor(Box::new(serde_json::from_str(&s).map_err(|e| {
261 ValueCreationError {
262 tag,
263 string: s.to_owned(),
264 error: Box::new(e),
265 }
266 })?)),
267 Tag::Authorization => {
268 Value::Authorization(Token::from_str(&s).map_err(|e| ValueCreationError {
269 tag,
270 string: s.to_owned(),
271 error: Box::new(e),
272 })?)
273 }
274 Tag::Date => Value::Date(UnimplementedValue(s)),
275 Tag::Aggregate => {
276 Value::Aggregate(serde_json::from_str(&s).map_err(|e| ValueCreationError {
277 tag,
278 string: s.to_owned(),
279 error: Box::new(e),
280 })?)
281 }
282 Tag::Array => {
283 Value::Array(serde_json::from_str(&s).map_err(|e| ValueCreationError {
284 tag,
285 string: s.to_owned(),
286 error: Box::new(e),
287 })?)
288 }
289
290 Tag::Variable => {
291 let map: HashMap<String, Value> =
292 serde_json::from_str(&s).map_err(|e| ValueCreationError {
293 tag,
294 string: s.to_owned(),
295 error: Box::new(e),
296 })?;
297 if map.len() != 1 {
298 return Err(ValueCreationError {
299 tag,
300 string: s.to_owned(),
301 error: "variable must have exactly one key".into(),
302 });
303 }
304 let kvp = map.into_iter().next().unwrap();
305 Value::Variable(kvp.0, Box::new(kvp.1))
306 }
307 };
308 Ok(result)
309 }
310
311 #[rustfmt::skip]
312 pub(crate) fn get_bytes(&self) -> String {
314
315 match self {
324 Value::Null(v) => v.to_owned(),
325 Value::Avesterra(v) => v.to_owned(),
326 Value::Boolean(v) => v.to_string().to_ascii_uppercase(),
327 Value::Character(v) => v.as_char().to_string(),
328 Value::String(v) => v.to_string(),
329 Value::Text(v) => v.to_owned(),
330 Value::Integer(v) => v.to_string(),
331 Value::Float(v) => v.to_string(),
332 Value::Entity(v) => v.to_string(),
333 Value::Time(v) => time_to_unix_timestamp_string(v),
334 Value::Web(v) => v.to_string(),
335 Value::Interchange(v) => v.to_owned(), Value::Data(v) => base16::encode_upper(v),
337 Value::Exception(v) => serde_json::to_string(v).unwrap(),
338 Value::Operator(v) => serde_json::to_value(v).unwrap().as_str().unwrap().to_owned(),
339 Value::Function(v) => v.to_string(),
340 Value::Measurement(v) => v.0.clone(),
341 Value::Locutor(v) => serde_json::to_string(v).unwrap(),
342 Value::Authorization(v) => v.to_string(),
343 Value::Date(v) => v.0.clone(),
344 Value::Aggregate(v) => serde_json::to_string(v).unwrap(),
345 Value::Array(v) => serde_json::to_string(v).unwrap(),
346 Value::Variable(n, v) => serde_json::json!{ { n: v } }.to_string()
347 }
348 }
349}
350
351mod serde_impl {
352 use super::*;
353
354 use serde::de;
355 use serde::ser;
356 use serde::ser::SerializeMap;
357
358 use crate::Tag;
359
360 impl ser::Serialize for Value {
361 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
362 where
363 S: ser::Serializer,
364 {
365 let tag = self.get_tag();
366 let value = self.get_bytes();
367
368 let tagstr = serde_json::to_value(tag)
371 .unwrap()
372 .as_str()
373 .unwrap()
374 .strip_suffix("_TAG")
375 .unwrap()
376 .to_owned();
377
378 let mut state = serializer.serialize_map(Some(1))?;
379 state.serialize_entry(&tagstr, &value)?;
380 state.end()
381 }
382 }
383
384 struct ValueVisitor;
385 impl<'de> de::Visitor<'de> for ValueVisitor {
386 type Value = crate::Value;
387
388 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
389 formatter.write_str("a tag value pair")
390 }
391
392 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
393 where
394 A: de::MapAccess<'de>,
395 {
396 let (tag, value) = match (
397 map.next_entry::<Tag, String>()?,
398 map.next_entry::<String, String>()?,
399 ) {
400 (Some((tag, value)), None) => (tag, value),
401 (None, None) => return Err(serde::de::Error::custom("missing tag/value pair")),
402 (Some(_), Some(_)) => {
403 return Err(serde::de::Error::custom("expected only one tag/value pair"))
404 }
405 (None, Some(_)) => unreachable!(),
406 };
407 Value::new(tag, value).map_err(serde::de::Error::custom)
408 }
409 }
410
411 impl<'de> de::Deserialize<'de> for crate::Value {
412 fn deserialize<D>(deserializer: D) -> Result<crate::Value, D::Error>
413 where
414 D: de::Deserializer<'de>,
415 {
416 deserializer.deserialize_map(ValueVisitor)
417 }
418 }
419}
420
421impl fmt::Display for Value {
422 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423 let tag = self.get_tag();
424 let val = self.get_bytes();
425 write!(f, "Value({tag:?}, {val})")
426 }
427}
428
429#[cfg(test)]
430mod test {
431 use ascii::AsciiString;
432 use maplit::hashmap;
433 use serde_json::json;
434 use time::macros::datetime;
435
436 use super::*;
437 use crate::taxonomy::*;
438 use crate::AvialError;
439 use crate::String255;
440
441 macro_rules! test_ok {
442 ($value:expr, $json:expr $(,)?) => {
443 let jsonval = $json;
444 let v: Value = match serde_json::from_value(jsonval.clone()) {
445 Ok(v) => v,
446 Err(e) => panic!("unexpected error parsing json: {:?}", e),
447 };
448 assert_eq!(v, $value);
449
450 let endval = match serde_json::to_value(v) {
451 Ok(v) => v,
452 Err(e) => panic!("unexpected error serializing value: {:?}", e),
453 };
454 assert_eq!(endval, jsonval);
455 };
456 }
457
458 macro_rules! test_ok2 {
459 ($value:expr, $json_in:expr, $json_out:expr $(,)?) => {
460 let jsonval = $json_in;
461 let v: Value = match serde_json::from_value(jsonval.clone()) {
462 Ok(v) => v,
463 Err(e) => panic!("unexpected error parsing json: {:?}", e),
464 };
465 assert_eq!(v, $value);
466
467 let endval = match serde_json::to_value(v) {
468 Ok(v) => v,
469 Err(e) => panic!("unexpected error serializing value: {:?}", e),
470 };
471 let jsonval2 = $json_out;
472 assert_eq!(endval, jsonval2);
473 };
474 }
475
476 macro_rules! test_ok_nojsoncheck {
478 ($value:expr, $json:expr $(,)?) => {
479 let jsonval = $json;
480 let v: Value = match serde_json::from_value(jsonval.clone()) {
481 Ok(v) => v,
482 Err(e) => panic!("unexpected error parsing json: {:?}", e),
483 };
484 assert_eq!(v, $value);
485
486 let endjsonval = match serde_json::to_value(v.clone()) {
487 Ok(v) => v,
488 Err(e) => panic!("unexpected error serializing value: {:?}", e),
489 };
490
491 let v2: Value = match serde_json::from_value(endjsonval.clone()) {
492 Ok(v) => v,
493 Err(e) => panic!(
494 "unexpected error parsing json after re-creating it: {:?}",
495 e
496 ),
497 };
498 assert_eq!(v.clone(), v2, "value: {:?}, json: {:?}", v, endjsonval);
499 };
500 }
501
502 macro_rules! test_err {
503 ($json:expr) => {
504 match serde_json::from_value::<Value>($json) {
505 Ok(v) => panic!("expected error, got {:?}", v),
506 Err(e) => println!("OK: got expected error: {}", e),
507 };
508 };
509 }
510
511 #[test]
512 fn general_errors() {
513 test_err!(json!({}));
515 test_err!(json!({ "INTEGER": 42 })); test_err!(json!({ "BLAH": "Hi" }));
517 }
518
519 #[test]
520 fn null() {
521 test_ok!(Value::Null("".into()), json!({ "NULL": "" }));
522 test_ok!(
523 Value::Null("content im not sure is used anyways".into()),
524 json!({ "NULL": "content im not sure is used anyways" })
525 );
526 test_ok!(
527 Value::Null("你好世界".into()),
528 json!({ "NULL": "你好世界" })
529 );
530 }
531
532 #[test]
533 fn avesterra() {
534 test_ok!(Value::Avesterra("".into()), json!({ "AVESTERRA": "" }));
535 test_ok!(
536 Value::Avesterra("Example".into()),
537 json!({ "AVESTERRA": "Example" })
538 );
539 }
540
541 #[test]
542 fn boolean() {
543 test_ok!(Value::Boolean(true), json!({ "BOOLEAN": "TRUE" }));
544 test_ok!(Value::Boolean(false), json!({ "BOOLEAN": "FALSE" }));
545 test_err!(json!({ "BOOLEAN": "blah" }));
546 test_err!(json!({ "BOOLEAN": "" }));
547 }
548
549 #[test]
550 fn character() {
551 test_ok!(Value::Character(AsciiChar::a), json!({ "CHARACTER": "a" }));
552 test_ok!(Value::Character(AsciiChar::A), json!({ "CHARACTER": "A" }));
553 test_ok!(Value::Character(AsciiChar::_1), json!({ "CHARACTER": "1" }));
554 test_ok!(
555 Value::Character(AsciiChar::Space),
556 json!({ "CHARACTER": " " })
557 );
558 test_err!(json!({ "CHARACTER": "" }));
559 test_err!(json!({ "CHARACTER": "ab" }));
560 test_err!(json!({ "CHARACTER": "ä" }));
561 }
562
563 #[test]
564 fn string() {
565 test_ok!(Value::String(AsciiString::new()), json!({ "STRING": "" }));
566 test_ok!(
567 Value::String(AsciiString::from_ascii(r"Hello World!\u0007").unwrap()),
568 json!({ "STRING": r"Hello World!\u0007" })
569 );
570 test_err!(json!({ "STRING": "Hello world is 你好世界" }));
571 }
572
573 #[test]
574 fn text() {
575 test_ok!(Value::Text("".into()), json!({ "TEXT": "" }));
576 test_ok!(
577 Value::Text("ÅvësTêrrã".into()),
578 json!({ "TEXT": "ÅvësTêrrã" })
579 );
580 test_ok!(
581 Value::Text("Hello world is 你好世界".into()),
582 json!({ "TEXT": "Hello world is 你好世界" })
583 );
584 }
585
586 #[test]
587 fn integer() {
588 test_ok!(Value::Integer(0), json!({ "INTEGER": "0" }));
589 test_ok!(Value::Integer(42), json!({ "INTEGER": "42" }));
590 test_ok!(Value::Integer(-42), json!({ "INTEGER": "-42" }));
591 test_err!(json!({ "INTEGER": "42.0" }));
592 test_err!(json!({ "INTEGER": "" }));
593 test_err!(json!({ "INTEGER": "three" }));
594 test_ok!(
595 Value::Integer(9_223_372_036_854_775_807),
596 json!({ "INTEGER": "9223372036854775807" })
597 );
598 test_ok!(
599 Value::Integer(-9_223_372_036_854_775_808),
600 json!({ "INTEGER": "-9223372036854775808" })
601 );
602 test_err!(json!({ "INTEGER": "9223372036854775808" }));
603 test_err!(json!({ "INTEGER": "-9223372036854775809" }));
604 }
605
606 #[test]
607 #[allow(clippy::approx_constant)]
608 fn float() {
609 test_ok2!(
612 Value::Float(3.14159),
613 json!({ "FLOAT":"3.14159000000000000E+00" }),
614 json!({ "FLOAT":"3.14159" })
615 );
616 test_err!(json!({ "FLOAT": "" }));
617 test_err!(json!({ "FLOAT": "hello" }));
618 }
619
620 #[test]
621 fn entity() {
622 test_ok!(
623 Value::Entity(Entity {
624 pid: 0,
625 hid: 0,
626 uid: 24
627 }),
628 json!({ "ENTITY": "<0|0|24>" })
629 );
630 test_ok!(
631 Value::Entity(Entity {
632 pid: 0,
633 hid: 0,
634 uid: 24
635 }),
636 json!({ "ENTITY": "<0|0|24>" })
637 );
638
639 test_err!(json!({ "ENTITY": "" }));
640 test_err!(json!({ "ENTITY": "<0|0|>" }));
641 test_err!(json!({ "ENTITY": "<0|0|24" }));
642 test_err!(json!({ "ENTITY": "<0|0|24|>" }));
643 test_err!(json!({ "ENTITY": "<0|0|24|24>" }));
644 test_err!(json!({ "ENTITY": "0|0|24>" }));
645
646 test_err!(json!({ "ENTITY": "<24>" }));
649 }
650
651 #[test]
652 fn time() {
653 test_ok!(
654 Value::Time(datetime!(1970-01-01 00:00:00 UTC)),
655 json!({ "TIME": "0" })
656 );
657 test_ok!(
658 Value::Time(datetime!(2010-01-11 00:00:22 UTC)),
659 json!({ "TIME": "1263168022" })
660 );
661 test_ok!(
662 Value::Time(datetime!(1895-07-15 09:25:51 UTC)),
663 json!({ "TIME": "-2349873249" })
664 );
665 test_err!(json!({ "TIME": "" }));
666 test_err!(json!({ "TIME": "안녕" }));
667 test_err!(json!({ "TIME": "9223372036854775808" })); test_err!(json!({ "TIME": "9223372036854775807" })); }
670
671 #[test]
672 fn web() {
673 test_ok!(
674 Value::Web("https://example.com".into()),
675 json!({ "WEB": "https://example.com" }),
676 );
677
678 test_ok!(
679 Value::Web("https://example.com/%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C".into()),
680 json!({ "WEB": "https://example.com/%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C" }),
681 );
682
683 test_ok!(
684 Value::Web("www.example.com".into()),
685 json!({ "WEB": "www.example.com" })
686 );
687
688 test_ok!(Value::Web("".into()), json!({ "WEB": "" }));
691 }
692
693 #[test]
694 fn interchange() {} #[test]
697 fn data() {
698 test_ok!(
699 Value::Data(vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
700 json!({ "DATA": "000102030405" })
701 );
702 test_ok!(
703 Value::Data(vec![0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]),
704 json!({ "DATA": "0A0B0C0D0E0F" })
705 );
706 test_ok2!(
707 Value::Data(vec![0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]),
708 json!({ "DATA": "0a0b0c0d0e0f" }),
709 json!({ "DATA": "0A0B0C0D0E0F" }),
710 );
711 test_ok!(
712 Value::Data(String::from(r#"Example Data ~!@#$%^&*()_+"'"#).into_bytes()),
713 json!({ "DATA": "4578616D706C652044617461207E21402324255E262A28295F2B2227" })
714 );
715
716 test_ok!(Value::Data(vec![]), json!({ "DATA": "" }));
717 test_err!(json!({ "DATA": "0G" }));
718 test_err!(json!({ "DATA": ".f" }));
719 test_err!(json!({ "DATA": "3" }));
720 }
721
722 #[test]
723 fn exception() {
724 test_ok!(
725 Value::Exception(AvialError {
726 error: Error::Halt,
727 message: "The machine has halted".into()
728 }),
729 json!({ "EXCEPTION": r#"{"ERROR":"HALT_ERROR","MESSAGE":"The machine has halted"}"# })
730 );
731 test_ok!(
732 Value::Exception(AvialError {
733 error: Error::Adapter,
734 message: "There was an error".into()
735 }),
736 json!({ "EXCEPTION": r#"{"ERROR":"ADAPTER_ERROR","MESSAGE":"There was an error"}"# }),
737 );
738 test_ok2!(
739 Value::Exception(AvialError {
740 error: Error::Network,
741 message: "Connection lost".into()
742 }),
743 json!({ "EXCEPTION" : r#" { "ERROR" : "NETWORK_ERROR" , "MESSAGE" : "Connection lost" } "# }),
744 json!({ "EXCEPTION": r#"{"ERROR":"NETWORK_ERROR","MESSAGE":"Connection lost"}"# }),
745 );
746
747 test_err!(json!({ "EXCEPTION": r#"{"ERROR":"IDONTEXIST_ERROR","MESSAGE":"Oh no"}"# }));
748 test_err!(json!({ "EXCEPTION": r#"{"ERR":"ADAPTER_ERROR","MESSAGE":"Oh no no o"}"# }));
749 test_err!(json!({ "EXCEPTION": r#"{"ERROR":"ADAPTER_ERROR","MSG":"Oh no no no "}"# }));
750 test_err!(json!({ "EXCEPTION": r#"{"MESSAGE":"Oh no no no no no no no no no no"}"# }));
751 test_err!(json!({ "EXCEPTION": r#"{"ERROR":"ADAPTER_ERROR"}"# }));
752 test_err!(json!({ "EXCEPTION": r#"{}"# }));
753 test_err!(json!({ "EXCEPTION": r#"[]"# }));
754 test_err!(json!({ "EXCEPTION": r#""# }));
755 }
756
757 #[test]
758 fn operator() {
759 test_ok!(
760 Value::Operator(Operator::Halt),
761 json!( { "OPERATOR": "HALT_OPERATOR" })
762 );
763
764 test_ok2!(
766 Value::Operator(Operator::Return),
767 json!( { "OPERATOR": "RETURN" }),
768 json!( { "OPERATOR": "RETURN_OPERATOR" }),
769 );
770
771 test_err!(json!({ "OPERATOR": "" }));
772 test_err!(json!({ "OPERATOR": "YOUSHALLNOTPASS" }));
773 }
774
775 #[test]
776 fn function() {
777 test_ok!(
778 Value::Function(Entity {
779 pid: 0,
780 hid: 0,
781 uid: 24
782 }),
783 json!({ "FUNCTION": "<0|0|24>" })
784 );
785 test_ok!(
786 Value::Function(Entity {
787 pid: 0,
788 hid: 0,
789 uid: 24
790 }),
791 json!({ "FUNCTION": "<0|0|24>" })
792 );
793
794 test_err!(json!({ "FUNCTION": "" }));
795 test_err!(json!({ "FUNCTION": "<0|0|>" }));
796 test_err!(json!({ "FUNCTION": "<0|0|24" }));
797 test_err!(json!({ "FUNCTION": "<0|0|24|>" }));
798 test_err!(json!({ "FUNCTION": "<0|0|24|24>" }));
799 test_err!(json!({ "FUNCTION": "0|0|24>" }));
800
801 test_err!(json!({ "FUNCTION": "<24>" }));
804 }
805
806 #[test]
807 fn authorization() {
808 test_ok!(
809 Value::Authorization(Token::from_str("2d754e46-6259-45f6-ac46-745f42f02558").unwrap()),
810 json!({ "AUTHORIZATION": "2d754e46-6259-45f6-ac46-745f42f02558" }),
811 );
812 test_ok!(
813 Value::Authorization(Token::from_str("d1159412-e368-4694-9289-5ce02979c523").unwrap()),
814 json!({ "AUTHORIZATION": "d1159412-e368-4694-9289-5ce02979c523" }),
815 );
816
817 test_ok2!(
818 Value::Authorization(Token::NOAUTH),
819 json!({ "AUTHORIZATION": "********-****-****-****-************" }),
820 json!({ "AUTHORIZATION": "ffffffff-ffff-ffff-ffff-ffffffffffff" }),
821 );
822 test_ok!(
823 Value::Authorization(Token::NOAUTH),
824 json!({ "AUTHORIZATION": "ffffffff-ffff-ffff-ffff-ffffffffffff" }),
825 );
826 test_ok!(
827 Value::Authorization(Token::NULL),
828 json!({ "AUTHORIZATION": "00000000-0000-0000-0000-000000000000" }),
829 );
830
831 test_err!(json!({ "AUTHORIZATION": "" }));
832 test_err!(json!({ "AUTHORIZATION": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }));
833 test_err!(json!({ "AUTHORIZATION": "hello world" }));
834 test_err!(json!({ "AUTHORIZATION": "你好" }));
835 test_err!(json!({ "AUTHORIZATION": 0}));
836 test_err!(json!({ "AUTHORIZATION": {}}));
837 }
838
839 #[test]
840 fn date() {
841 test_ok!(
842 Value::Authorization(Token::from_str("2d754e46-6259-45f6-ac46-745f42f02558").unwrap()),
843 json!({ "AUTHORIZATION": "2d754e46-6259-45f6-ac46-745f42f02558" }),
844 );
845
846 test_ok!(
847 Value::Measurement(UnimplementedValue(
848 "{\"YEAR\": 1960,\"MONTH\": 10,\"DAY\": 1}".to_string()
849 )),
850 json!(
851 {
852 "MEASUREMENT": "{\"YEAR\": 1960,\"MONTH\": 10,\"DAY\": 1}"
853 }),
854 );
855 }
856
857 #[test]
858 fn aggregate() {
859 test_ok_nojsoncheck!(
860 Value::Aggregate(hashmap! {
861 "Boolean Variable".to_owned() => Value::Boolean(true),
862 "Integer Variable".to_owned() => Value::Integer(42),
863 }),
864 json!({
865 "AGGREGATE": "{\"Boolean Variable\":{\"BOOLEAN\":\"TRUE\"},\"Integer Variable\":{\"INTEGER\":\"42\"}}"
866 }),
867 );
868
869 test_ok!(
870 Value::Aggregate(hashmap! {}),
871 json!({
872 "AGGREGATE": "{}"
873 }),
874 );
875
876 test_ok!(
877 Value::Aggregate(hashmap! {
878 "Nested".to_owned() => Value::Aggregate(hashmap! {}),
879 }),
880 json!({
881 "AGGREGATE": "{\"Nested\":{\"AGGREGATE\":\"{}\"}}"
882 }),
883 );
884
885 test_err!(json!({ "AGGREGATE": "" }));
886 test_err!(json!({ "AGGREGATE": "}" }));
887 test_err!(json!({ "AGGREGATE": "32" }));
888 test_err!(json!({ "AGGREGATE": "[]" }));
889 test_err!(json!({ "AGGREGATE": "hi" }));
890 test_err!(json!({ "AGGREGATE": "\"MyValue\": {\"INTEGER\": \"string!\"}" }));
891 }
892
893 #[test]
894 fn array() {
895 test_ok!(
896 Value::Array(vec![
897 Value::Entity(Entity {
898 pid: 0,
899 hid: 0,
900 uid: 24,
901 }),
902 Value::Integer(42),
903 ]),
904 json!({
905 "ARRAY": "[{\"ENTITY\":\"<0|0|24>\"},{\"INTEGER\":\"42\"}]"
906 }),
907 );
908
909 test_ok!(
910 Value::Array(vec![
911 Value::String(AsciiString::from_ascii("Hello").unwrap()),
912 Value::Float(7.2939),
913 Value::Array(vec![Value::Character(AsciiChar::A), Value::Boolean(true),]),
914 Value::Entity(Entity {
915 pid: 0,
916 hid: 0,
917 uid: 24
918 }),
919 ]),
920 json!({
921 "ARRAY": "[{\"STRING\":\"Hello\"},{\"FLOAT\":\"7.2939\"},{\"ARRAY\":\"[{\\\"CHARACTER\\\":\\\"A\\\"},{\\\"BOOLEAN\\\":\\\"TRUE\\\"}]\"},{\"ENTITY\":\"<0|0|24>\"}]"
922 }),
923 );
924
925 test_ok!(
926 Value::Array(vec![
927 Value::String(AsciiString::from_ascii("Hello").unwrap()),
928 Value::Float(7.2939),
929 Value::Aggregate(hashmap! {
930 "Key".to_owned() => Value::Character(AsciiChar::A)
931 }),
932 Value::Entity(Entity {
933 pid: 0,
934 hid: 0,
935 uid: 24
936 }),
937 ]),
938 json!({
939 "ARRAY": "[{\"STRING\":\"Hello\"},{\"FLOAT\":\"7.2939\"},{\"AGGREGATE\":\"{\\\"Key\\\":{\\\"CHARACTER\\\":\\\"A\\\"}}\"},{\"ENTITY\":\"<0|0|24>\"}]"
940 }),
941 );
942
943 test_ok!(
944 Value::Array(vec![
945 Value::String(AsciiString::from_ascii("Hello").unwrap()),
946 Value::Float(7.2939),
947 Value::Array(vec![Value::Character(AsciiChar::A), Value::Boolean(true),]),
948 ]),
949 json!({
950 "ARRAY": "[{\"STRING\":\"Hello\"},{\"FLOAT\":\"7.2939\"},{\"ARRAY\":\"[{\\\"CHARACTER\\\":\\\"A\\\"},{\\\"BOOLEAN\\\":\\\"TRUE\\\"}]\"}]"
951 }),
952 );
953
954 test_ok!(
955 Value::Array(vec![]),
956 json!({
957 "ARRAY": "[]"
958 }),
959 );
960
961 test_err!(json!({ "ARRAY": "" }));
962 test_err!(json!({ "ARRAY": "}" }));
963 test_err!(json!({ "ARRAY": "32" }));
964 test_err!(json!({ "ARRAY": "{}" }));
965 test_err!(json!({ "ARRAY": "hi" }));
966 }
967
968 #[test]
969 fn variable() {
970 test_ok!(
971 Value::Variable(
972 "City Variable".to_owned(),
973 Box::new(Value::String(
974 AsciiString::from_ascii("Washington, D.C.").unwrap()
975 ))
976 ),
977 json!({
978 "VARIABLE": "{\"City Variable\":{\"STRING\":\"Washington, D.C.\"}}"
979 }),
980 );
981
982 test_ok!(
983 Value::Variable("MyVariable".to_owned(), Box::new(Value::Array(vec![]))),
984 json!({
985 "VARIABLE": "{\"MyVariable\":{\"ARRAY\":\"[]\"}}"
986 }),
987 );
988
989 test_ok_nojsoncheck!(
990 Value::Variable(
991 "MyVariable".to_owned(),
992 Box::new(Value::Aggregate(hashmap! {
993 "Thing 1".to_owned() => Value::Integer(21),
994 "Thing 2".to_owned() => Value::Boolean(true),
995 }))
996 ),
997 json!({
998 "VARIABLE": "{\"MyVariable\":{\"AGGREGATE\":\"{\\\"Thing 1\\\":{\\\"INTEGER\\\":\\\"21\\\"},\\\"Thing 2\\\":{\\\"BOOLEAN\\\":\\\"TRUE\\\"}}\"}}"
999 }),
1000 );
1001
1002 test_err!(json!({ "VARIABLE": "" }));
1003 test_err!(json!({ "VARIABLE": "}" }));
1004 test_err!(json!({ "VARIABLE": "32" }));
1005 test_err!(json!({ "VARIABLE": "{}" }));
1006 test_err!(json!({ "VARIABLE": "hi" }));
1007 }
1008
1009 #[test]
1010 fn locutor() {
1011 test_ok_nojsoncheck!(
1012 Value::Locutor(Box::new(Locutor {
1013 entity: Entity::new(0, 0, 24),
1014 outlet: Entity::new(0, 0, 11),
1015 auxiliary: Entity::new(0, 0, 1),
1016 ancillary: Entity::new(0, 0, 2),
1017 context: Context::Avesterra,
1018 category: Category::Avesterra,
1019 class: Class::Avesterra,
1020 method: Method::Avesterra,
1021 attribute: Attribute::Avesterra,
1022 instance: 1,
1023 offset: 0,
1024 parameter: -1,
1025 resultant: 0,
1026 count: 123,
1027 index: 1,
1028 event: Event::Avesterra,
1029 mode: Mode::Avesterra,
1030 state: State::Null,
1031 condition: Condition::Null,
1032 precedence: 8,
1033 time: OffsetDateTime::from_unix_timestamp(0).unwrap(),
1034 timeout: 60,
1035 aspect: Aspect::Avesterra,
1036 template: Template::Null,
1037 scheme: Scheme::Null,
1038 name: String255::unchecked("Example Name"),
1039 label: String::new(),
1040 key: String255::NULL,
1041 value: Value::String(AsciiString::from_str("Example String").unwrap()),
1042 format: Format::Null,
1043 authority: Token::from_str("********-****-****-****-************").unwrap(),
1044 authorization: Token::NULL,
1045 })),
1046 json!(
1047 {
1048 "LOCUTOR": "{\"ENTITY\": \"<0|0|24>\",\"OUTLET\": \"<0|0|11>\",\"AUXILIARY\": \"<0|0|1>\",\"ANCILLARY\": \"<0|0|2>\",\"CONTEXT\": \"AVESTERRA_CONTEXT\",\"CATEGORY\": \"AVESTERRA_CATEGORY\",\"CLASS\": \"AVESTERRA_CLASS\",\"METHOD\": \"AVESTERRA_METHOD\",\"ATTRIBUTE\": \"AVESTERRA_ATTRIBUTE\",\"INSTANCE\": 1,\"NAME\": \"Example Name\",\"VALUE\": \"Example String\",\"VALUE_TAG\": \"STRING_TAG\",\"INDEX\": 1,\"COUNT\": 123,\"PRECEDENCE\": \" 8\",\"PARAMETER\": -1,\"MODE\": \"AVESTERRA_MODE\",\"EVENT\": \"AVESTERRA_EVENT\",\"TIMEOUT\": 60,\"ASPECT\": \"AVESTERRA_ASPECT\",\"AUTHORITY\": \"********-****-****-****-************\"}"
1049 }),
1050 );
1051
1052 test_err!(json!({ "LOCUTOR": "" }));
1053 test_err!(json!({ "LOCUTOR": "}" }));
1054 test_err!(json!({ "LOCUTOR": "32" }));
1055 test_err!(json!({ "LOCUTOR": "hi" }));
1056 }
1057
1058 #[test]
1059 fn measurement() {
1060 test_ok!(
1061 Value::Measurement(UnimplementedValue("{\"FLOAT\": 4.20000000000000E+01,\"UNIT\": \"GRAM_UNIT\",\"PREFIX\": \"MICRO_PREFIX\",\"CONFIDENCE\": 9.99000015258789E+01,\"UNCERTAINTY\": 1.00000001490116E-01}".to_string())),
1062 json!(
1063 {
1064 "MEASUREMENT": "{\"FLOAT\": 4.20000000000000E+01,\"UNIT\": \"GRAM_UNIT\",\"PREFIX\": \"MICRO_PREFIX\",\"CONFIDENCE\": 9.99000015258789E+01,\"UNCERTAINTY\": 1.00000001490116E-01}"
1065 }),
1066 );
1067 }
1068}