1use std::borrow::Cow;
3use std::cmp::Ordering;
4use std::ops::{Add, Sub};
5use std::str::FromStr;
6use std::{fmt, net};
7
8use chrono::{DateTime, Datelike, Duration, LocalResult, NaiveDateTime, TimeZone, Utc};
9use enumset::EnumSet;
10use relay_protocol::{
11 Annotated, Array, Empty, Error, ErrorKind, FromValue, IntoValue, Meta, Object,
12 SkipSerialization, Value,
13};
14use serde::{Deserialize, Deserializer, Serialize, Serializer};
15
16use crate::processor::{
17 process_value, ProcessValue, ProcessingResult, ProcessingState, Processor, ValueType,
18};
19
20#[derive(Clone, Debug, PartialEq, Empty, IntoValue, ProcessValue)]
22#[metastructure(process_func = "process_values")]
23pub struct Values<T> {
24 #[metastructure(required = true, skip_serialization = "empty_deep")]
26 pub values: Annotated<Array<T>>,
27
28 #[metastructure(additional_properties)]
30 pub other: Object<Value>,
31}
32
33impl<T> Default for Values<T> {
34 fn default() -> Values<T> {
35 Values::new(Vec::new())
37 }
38}
39
40impl<T> Values<T> {
41 pub fn new(values: Array<T>) -> Values<T> {
43 Values {
44 values: Annotated::new(values),
45 other: Object::default(),
46 }
47 }
48}
49
50impl<T: FromValue> FromValue for Values<T> {
51 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
52 match value {
53 Annotated(Some(Value::Array(items)), meta) => Annotated(
56 Some(Values {
57 values: Annotated(
58 Some(items.into_iter().map(FromValue::from_value).collect()),
59 meta,
60 ),
61 other: Object::new(),
62 }),
63 Meta::default(),
64 ),
65 Annotated(Some(Value::Object(mut obj)), meta) => {
66 if obj.is_empty() {
67 Annotated(None, meta)
71 } else if let Some(values) = obj.remove("values") {
72 Annotated(
75 Some(Values {
76 values: FromValue::from_value(values),
77 other: obj,
78 }),
79 meta,
80 )
81 } else {
82 Annotated(
85 Some(Values {
86 values: Annotated(
87 Some(vec![FromValue::from_value(Annotated(
88 Some(Value::Object(obj)),
89 meta,
90 ))]),
91 Meta::default(),
92 ),
93 other: Object::new(),
94 }),
95 Meta::default(),
96 )
97 }
98 }
99 Annotated(None, meta) => Annotated(None, meta),
100 Annotated(Some(value), mut meta) => {
101 meta.add_error(Error::expected("a list or values object"));
102 meta.set_original_value(Some(value));
103 Annotated(None, meta)
104 }
105 }
106 }
107}
108
109pub trait AsPair {
111 type Key: AsRef<str>;
112 type Value: ProcessValue;
113
114 fn from_pair(pair: (Annotated<Self::Key>, Annotated<Self::Value>)) -> Self;
116
117 fn into_pair(self) -> (Annotated<Self::Key>, Annotated<Self::Value>);
119
120 fn as_pair(&self) -> (&Annotated<Self::Key>, &Annotated<Self::Value>);
122
123 fn as_pair_mut(&mut self) -> (&mut Annotated<Self::Key>, &mut Annotated<Self::Value>);
125
126 fn key(&self) -> Option<&str> {
128 self.as_pair().0.as_str()
129 }
130
131 fn value(&self) -> Option<&Self::Value> {
133 self.as_pair().1.value()
134 }
135}
136
137impl<K, V> AsPair for (Annotated<K>, Annotated<V>)
138where
139 K: AsRef<str>,
140 V: ProcessValue,
141{
142 type Key = K;
143 type Value = V;
144
145 fn from_pair(pair: (Annotated<Self::Key>, Annotated<Self::Value>)) -> Self {
146 pair
147 }
148
149 fn into_pair(self) -> (Annotated<Self::Key>, Annotated<Self::Value>) {
150 self
151 }
152
153 fn as_pair(&self) -> (&Annotated<Self::Key>, &Annotated<Self::Value>) {
154 (&self.0, &self.1)
155 }
156
157 fn as_pair_mut(&mut self) -> (&mut Annotated<Self::Key>, &mut Annotated<Self::Value>) {
158 (&mut self.0, &mut self.1)
159 }
160}
161
162#[derive(Clone, Debug, Default, PartialEq, Empty, IntoValue)]
164pub struct PairList<T>(pub Array<T>);
165
166impl<T, K, V> PairList<T>
167where
168 K: AsRef<str>,
169 V: ProcessValue,
170 T: AsPair<Key = K, Value = V>,
171{
172 pub fn position<Q>(&self, key: Q) -> Option<usize>
174 where
175 Q: AsRef<str>,
176 {
177 let key = key.as_ref();
178 self.0
179 .iter()
180 .filter_map(Annotated::value)
181 .position(|entry| entry.as_pair().0.as_str() == Some(key))
182 }
183
184 pub fn get<'a, Q>(&'a self, key: Q) -> Option<&'a Annotated<V>>
189 where
190 Q: AsRef<str>,
191 K: 'a,
192 {
193 self.position(key)
194 .and_then(|pos| self.0.get(pos))
195 .and_then(Annotated::value)
196 .map(|pair| pair.as_pair().1)
197 }
198
199 pub fn get_value<'a, Q>(&'a self, key: Q) -> Option<&'a V>
204 where
205 Q: AsRef<str>,
206 K: 'a,
207 {
208 self.get(key).and_then(Annotated::value)
209 }
210
211 pub fn contains<Q>(&self, key: Q) -> bool
213 where
214 Q: AsRef<str>,
215 {
216 self.position(key).is_some()
217 }
218
219 pub fn remove<Q>(&mut self, key: Q) -> Option<Annotated<V>>
221 where
222 Q: AsRef<str>,
223 {
224 self.position(key)
225 .and_then(|index| self.0.remove(index).0)
226 .map(|entry| entry.into_pair().1)
227 }
228
229 pub fn insert(&mut self, key: K, value: Annotated<V>) -> Option<Annotated<V>> {
231 match self.position(key.as_ref()) {
232 Some(index) => self
233 .get_mut(index)
234 .and_then(|annotated| annotated.value_mut().as_mut())
235 .map(|pair| std::mem::replace(pair.as_pair_mut().1, value)),
236 None => {
237 self.push(Annotated::new(T::from_pair((Annotated::new(key), value))));
238 None
239 }
240 }
241 }
242}
243
244impl<T> std::ops::Deref for PairList<T> {
245 type Target = Array<T>;
246
247 fn deref(&self) -> &Self::Target {
248 &self.0
249 }
250}
251
252impl<T> std::ops::DerefMut for PairList<T> {
253 fn deref_mut(&mut self) -> &mut Self::Target {
254 &mut self.0
255 }
256}
257
258impl<A> FromIterator<Annotated<A>> for PairList<A> {
259 fn from_iter<T>(iter: T) -> Self
260 where
261 T: IntoIterator<Item = Annotated<A>>,
262 {
263 PairList(FromIterator::from_iter(iter))
264 }
265}
266
267impl<T> From<Array<T>> for PairList<T> {
268 fn from(value: Array<T>) -> Self {
269 PairList(value)
270 }
271}
272
273impl<T: FromValue> FromValue for PairList<T> {
274 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
275 match value {
276 Annotated(Some(Value::Array(items)), meta) => {
277 let mut rv = Vec::new();
278 for item in items.into_iter() {
279 rv.push(T::from_value(item));
280 }
281 Annotated(Some(PairList(rv)), meta)
282 }
283 Annotated(Some(Value::Object(items)), meta) => {
284 let mut rv = Vec::new();
285 for (key, value) in items.into_iter() {
286 rv.push(T::from_value(Annotated::new(Value::Array(vec![
287 Annotated::new(Value::String(key)),
288 value,
289 ]))));
290 }
291 Annotated(Some(PairList(rv)), meta)
292 }
293 other => FromValue::from_value(other).map_value(PairList),
294 }
295 }
296}
297
298impl<T> ProcessValue for PairList<T>
299where
300 T: ProcessValue + AsPair,
301{
302 #[inline]
303 fn value_type(&self) -> EnumSet<ValueType> {
304 EnumSet::only(ValueType::Object)
305 }
306
307 #[inline]
308 fn process_value<P>(
309 &mut self,
310 meta: &mut Meta,
311 processor: &mut P,
312 state: &ProcessingState<'_>,
313 ) -> ProcessingResult
314 where
315 P: Processor,
316 {
317 processor.process_pairlist(self, meta, state)
318 }
319
320 fn process_child_values<P>(
321 &mut self,
322 processor: &mut P,
323 state: &ProcessingState<'_>,
324 ) -> ProcessingResult
325 where
326 P: Processor,
327 {
328 for (idx, pair) in self.0.iter_mut().enumerate() {
329 let state = state.enter_index(idx, state.inner_attrs(), ValueType::for_field(pair));
330 process_value(pair, processor, &state)?;
331 }
332
333 Ok(())
334 }
335}
336
337macro_rules! hex_metrastructure {
338 ($type:ident, $expectation:expr) => {
339 impl FromStr for $type {
340 type Err = std::num::ParseIntError;
341
342 fn from_str(s: &str) -> Result<$type, Self::Err> {
343 if s.starts_with("0x") || s.starts_with("0X") {
344 u64::from_str_radix(&s[2..], 16).map($type)
345 } else {
346 s.parse().map($type)
347 }
348 }
349 }
350
351 impl fmt::Display for $type {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 write!(f, "{:#x}", self.0)
354 }
355 }
356
357 impl Empty for $type {
358 #[inline]
359 fn is_empty(&self) -> bool {
360 false
361 }
362 }
363
364 impl FromValue for $type {
365 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
366 match value {
367 Annotated(Some(Value::String(value)), mut meta) => match value.parse() {
368 Ok(value) => Annotated(Some(value), meta),
369 Err(err) => {
370 meta.add_error(Error::invalid(err));
371 meta.set_original_value(Some(value));
372 Annotated(None, meta)
373 }
374 },
375 Annotated(Some(Value::U64(value)), meta) => Annotated(Some($type(value)), meta),
376 Annotated(Some(Value::I64(value)), meta) => {
377 Annotated(Some($type(value as u64)), meta)
378 }
379 Annotated(None, meta) => Annotated(None, meta),
380 Annotated(Some(value), mut meta) => {
381 meta.add_error(Error::expected($expectation));
382 meta.set_original_value(Some(value));
383 Annotated(None, meta)
384 }
385 }
386 }
387 }
388
389 impl IntoValue for $type {
390 fn into_value(self) -> Value {
391 Value::String(self.to_string())
392 }
393 fn serialize_payload<S>(
394 &self,
395 s: S,
396 _behavior: relay_protocol::SkipSerialization,
397 ) -> Result<S::Ok, S::Error>
398 where
399 Self: Sized,
400 S: Serializer,
401 {
402 Serializer::collect_str(s, self)
403 }
404 }
405
406 impl ProcessValue for $type {}
407 };
408}
409
410#[derive(Debug)]
412pub struct InvalidRegVal;
413
414impl fmt::Display for InvalidRegVal {
415 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
416 write!(f, "invalid register value")
417 }
418}
419
420impl std::error::Error for InvalidRegVal {}
421
422#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
424pub struct RegVal(pub u64);
425
426hex_metrastructure!(RegVal, "register value");
427
428#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
430pub struct Addr(pub u64);
431
432hex_metrastructure!(Addr, "address");
433relay_common::impl_str_serde!(Addr, "an address");
434
435#[derive(
437 Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Empty, IntoValue, ProcessValue, Serialize,
438)]
439pub struct IpAddr(pub String);
440
441impl IpAddr {
442 pub fn auto() -> IpAddr {
444 IpAddr("{{auto}}".into())
445 }
446
447 pub fn parse<S>(value: S) -> Result<Self, S>
449 where
450 S: AsRef<str> + Into<String>,
451 {
452 if value.as_ref() == "{{auto}}" {
453 return Ok(IpAddr(value.into()));
454 }
455
456 match net::IpAddr::from_str(value.as_ref()) {
457 Ok(_) => Ok(IpAddr(value.into())),
458 Err(_) => Err(value),
459 }
460 }
461
462 pub fn is_auto(&self) -> bool {
464 self.0 == "{{auto}}"
465 }
466
467 pub fn is_valid(&self) -> bool {
469 self.is_auto() || net::IpAddr::from_str(&self.0).is_ok()
470 }
471
472 pub fn as_str(&self) -> &str {
474 &self.0
475 }
476
477 pub fn into_inner(self) -> String {
479 self.0
480 }
481}
482
483impl AsRef<str> for IpAddr {
484 fn as_ref(&self) -> &str {
485 &self.0
486 }
487}
488
489impl Default for IpAddr {
490 fn default() -> Self {
491 IpAddr::auto()
492 }
493}
494
495impl From<std::net::IpAddr> for IpAddr {
496 fn from(ip_addr: std::net::IpAddr) -> Self {
497 Self(ip_addr.to_string())
498 }
499}
500
501impl fmt::Display for IpAddr {
502 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
503 self.0.fmt(f)
504 }
505}
506
507impl<'de> Deserialize<'de> for IpAddr {
508 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
509 where
510 D: Deserializer<'de>,
511 {
512 let string = Cow::<'_, str>::deserialize(deserializer)?;
513 IpAddr::parse(string).map_err(|_| serde::de::Error::custom("expected an ip address"))
514 }
515}
516
517impl FromValue for IpAddr {
518 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
519 match value {
520 Annotated(Some(Value::String(value)), mut meta) => match IpAddr::parse(value) {
521 Ok(addr) => Annotated(Some(addr), meta),
522 Err(value) => {
523 meta.add_error(Error::expected("an ip address"));
524 meta.set_original_value(Some(value));
525 Annotated(None, meta)
526 }
527 },
528 Annotated(None, meta) => Annotated(None, meta),
529 Annotated(Some(value), mut meta) => {
530 meta.add_error(Error::expected("an ip address"));
531 meta.set_original_value(Some(value));
532 Annotated(None, meta)
533 }
534 }
535 }
536}
537
538impl FromStr for IpAddr {
539 type Err = ();
540
541 fn from_str(value: &str) -> Result<Self, Self::Err> {
542 IpAddr::parse(value).map_err(|_| ())
543 }
544}
545
546#[derive(Debug)]
548pub struct ParseLevelError;
549
550impl fmt::Display for ParseLevelError {
551 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
552 write!(f, "invalid level")
553 }
554}
555
556impl std::error::Error for ParseLevelError {}
557
558#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
560pub enum Level {
561 Debug,
563 #[default]
565 Info,
566 Warning,
568 Error,
570 Fatal,
572}
573
574impl Level {
575 pub fn name(self) -> &'static str {
576 match self {
577 Level::Debug => "debug",
578 Level::Info => "info",
579 Level::Warning => "warning",
580 Level::Error => "error",
581 Level::Fatal => "fatal",
582 }
583 }
584
585 fn from_python_level(value: u64) -> Option<Level> {
586 Some(match value {
587 10 => Level::Debug,
588 20 => Level::Info,
589 30 => Level::Warning,
590 40 => Level::Error,
591 50 => Level::Fatal,
592 _ => return None,
593 })
594 }
595}
596
597impl FromStr for Level {
598 type Err = ParseLevelError;
599
600 fn from_str(string: &str) -> Result<Self, Self::Err> {
601 Ok(match string {
602 "debug" => Level::Debug,
603 "info" | "log" => Level::Info,
604 "warning" => Level::Warning,
605 "error" => Level::Error,
606 "fatal" | "critical" => Level::Fatal,
607 _ => return Err(ParseLevelError),
608 })
609 }
610}
611
612impl fmt::Display for Level {
613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
614 f.write_str(self.name())
615 }
616}
617
618impl FromValue for Level {
619 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
620 match value {
621 Annotated(Some(Value::String(value)), mut meta) => match value.parse() {
622 Ok(value) => Annotated(Some(value), meta),
623 Err(err) => {
624 meta.add_error(Error::invalid(err));
625 meta.set_original_value(Some(value));
626 Annotated(None, meta)
627 }
628 },
629 Annotated(Some(Value::U64(val)), mut meta) => match Level::from_python_level(val) {
630 Some(value) => Annotated(Some(value), meta),
631 None => {
632 meta.add_error(ErrorKind::InvalidData);
633 meta.set_original_value(Some(val));
634 Annotated(None, meta)
635 }
636 },
637 Annotated(Some(Value::I64(val)), mut meta) => {
638 match Level::from_python_level(val as u64) {
639 Some(value) => Annotated(Some(value), meta),
640 None => {
641 meta.add_error(ErrorKind::InvalidData);
642 meta.set_original_value(Some(val));
643 Annotated(None, meta)
644 }
645 }
646 }
647 Annotated(None, meta) => Annotated(None, meta),
648 Annotated(Some(value), mut meta) => {
649 meta.add_error(Error::expected("a level"));
650 meta.set_original_value(Some(value));
651 Annotated(None, meta)
652 }
653 }
654 }
655}
656
657impl IntoValue for Level {
658 fn into_value(self) -> Value {
659 Value::String(self.to_string())
660 }
661
662 fn serialize_payload<S>(&self, s: S, _behavior: SkipSerialization) -> Result<S::Ok, S::Error>
663 where
664 Self: Sized,
665 S: Serializer,
666 {
667 Serialize::serialize(self.name(), s)
668 }
669}
670
671impl ProcessValue for Level {}
672
673impl Empty for Level {
674 #[inline]
675 fn is_empty(&self) -> bool {
676 false
677 }
678}
679
680#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Empty, IntoValue, ProcessValue)]
682pub struct LenientString(pub String);
683
684impl LenientString {
685 pub fn as_str(&self) -> &str {
687 &self.0
688 }
689
690 pub fn into_inner(self) -> String {
692 self.0
693 }
694}
695
696impl AsRef<str> for LenientString {
697 fn as_ref(&self) -> &str {
698 &self.0
699 }
700}
701
702impl std::ops::Deref for LenientString {
703 type Target = String;
704
705 fn deref(&self) -> &Self::Target {
706 &self.0
707 }
708}
709
710impl std::ops::DerefMut for LenientString {
711 fn deref_mut(&mut self) -> &mut Self::Target {
712 &mut self.0
713 }
714}
715
716impl From<String> for LenientString {
717 fn from(value: String) -> Self {
718 LenientString(value)
719 }
720}
721
722impl FromValue for LenientString {
723 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
724 match value {
725 Annotated(Some(Value::String(string)), meta) => Annotated(Some(string), meta),
726 Annotated(Some(Value::Bool(true)), meta) => Annotated(Some("True".to_string()), meta),
728 Annotated(Some(Value::Bool(false)), meta) => Annotated(Some("False".to_string()), meta),
729 Annotated(Some(Value::U64(num)), meta) => Annotated(Some(num.to_string()), meta),
730 Annotated(Some(Value::I64(num)), meta) => Annotated(Some(num.to_string()), meta),
731 Annotated(Some(Value::F64(num)), mut meta) => {
732 if num.abs() < (1i64 << 53) as f64 {
733 Annotated(Some(num.trunc().to_string()), meta)
734 } else {
735 meta.add_error(Error::expected("a number with JSON precision"));
736 meta.set_original_value(Some(num));
737 Annotated(None, meta)
738 }
739 }
740 Annotated(None, meta) => Annotated(None, meta),
741 Annotated(Some(value), mut meta) => {
742 meta.add_error(Error::expected("a primitive value"));
743 meta.set_original_value(Some(value));
744 Annotated(None, meta)
745 }
746 }
747 .map_value(LenientString)
748 }
749}
750
751#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Empty, IntoValue, ProcessValue)]
753pub struct JsonLenientString(pub String);
754
755impl JsonLenientString {
756 pub fn as_str(&self) -> &str {
758 &self.0
759 }
760
761 pub fn into_inner(self) -> String {
763 self.0
764 }
765}
766
767impl AsRef<str> for JsonLenientString {
768 fn as_ref(&self) -> &str {
769 &self.0
770 }
771}
772
773impl std::ops::Deref for JsonLenientString {
774 type Target = String;
775
776 fn deref(&self) -> &Self::Target {
777 &self.0
778 }
779}
780
781impl std::ops::DerefMut for JsonLenientString {
782 fn deref_mut(&mut self) -> &mut Self::Target {
783 &mut self.0
784 }
785}
786
787impl From<JsonLenientString> for String {
788 fn from(value: JsonLenientString) -> Self {
789 value.0
790 }
791}
792
793impl FromValue for JsonLenientString {
794 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
795 match value {
796 Annotated(Some(Value::String(string)), meta) => Annotated(Some(string.into()), meta),
797 Annotated(Some(other), meta) => {
798 Annotated(Some(serde_json::to_string(&other).unwrap().into()), meta)
799 }
800 Annotated(None, meta) => Annotated(None, meta),
801 }
802 }
803}
804
805impl From<String> for JsonLenientString {
806 fn from(value: String) -> Self {
807 JsonLenientString(value)
808 }
809}
810
811#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
812pub struct Timestamp(pub DateTime<Utc>);
813
814impl Timestamp {
815 pub fn into_inner(self) -> DateTime<Utc> {
816 self.0
817 }
818}
819
820impl ProcessValue for Timestamp {
821 #[inline]
822 fn value_type(&self) -> EnumSet<ValueType> {
823 EnumSet::only(ValueType::DateTime)
824 }
825
826 #[inline]
827 fn process_value<P>(
828 &mut self,
829 meta: &mut Meta,
830 processor: &mut P,
831 state: &ProcessingState<'_>,
832 ) -> ProcessingResult
833 where
834 P: Processor,
835 {
836 processor.process_timestamp(self, meta, state)
837 }
838}
839
840impl From<DateTime<Utc>> for Timestamp {
841 fn from(value: DateTime<Utc>) -> Self {
842 Timestamp(value)
843 }
844}
845
846impl Add<Duration> for Timestamp {
847 type Output = Self;
848
849 fn add(self, duration: Duration) -> Self::Output {
850 Timestamp(self.0 + duration)
851 }
852}
853
854impl Sub<Timestamp> for Timestamp {
855 type Output = chrono::Duration;
856
857 fn sub(self, rhs: Timestamp) -> Self::Output {
858 self.into_inner() - rhs.into_inner()
859 }
860}
861
862impl PartialEq<DateTime<Utc>> for Timestamp {
863 fn eq(&self, other: &DateTime<Utc>) -> bool {
864 &self.0 == other
865 }
866}
867
868impl PartialOrd<DateTime<Utc>> for Timestamp {
869 fn partial_cmp(&self, other: &DateTime<Utc>) -> Option<Ordering> {
870 self.0.partial_cmp(other)
871 }
872}
873
874impl fmt::Display for Timestamp {
875 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
876 self.0.fmt(f)
877 }
878}
879
880pub fn datetime_to_timestamp(dt: DateTime<Utc>) -> f64 {
881 let micros = (f64::from(dt.timestamp_subsec_nanos()) / 1_000f64).round();
897 dt.timestamp() as f64 + (micros / 1_000_000f64)
898}
899
900fn utc_result_to_annotated<V: IntoValue>(
901 result: LocalResult<DateTime<Utc>>,
902 original_value: V,
903 mut meta: Meta,
904) -> Annotated<DateTime<Utc>> {
905 match result {
906 LocalResult::Single(value) => Annotated(Some(value), meta),
907 LocalResult::Ambiguous(_, _) => {
908 meta.add_error(Error::expected("ambiguous timestamp"));
909 meta.set_original_value(Some(original_value));
910 Annotated(None, meta)
911 }
912 LocalResult::None => {
913 meta.add_error(Error::invalid("timestamp out of range"));
914 meta.set_original_value(Some(original_value));
915 Annotated(None, meta)
916 }
917 }
918}
919
920impl FromValue for Timestamp {
921 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
922 let rv = match value {
923 Annotated(Some(Value::String(value)), mut meta) => {
924 let parsed = match value.parse::<NaiveDateTime>() {
926 Ok(dt) => Ok(DateTime::from_naive_utc_and_offset(dt, Utc)),
927
928 Err(_) => value.parse(),
935 };
936 match parsed {
937 Ok(value) => Annotated(Some(value), meta),
938 Err(err) => {
939 meta.add_error(Error::invalid(err));
940 meta.set_original_value(Some(value));
941 Annotated(None, meta)
942 }
943 }
944 }
945 Annotated(Some(Value::U64(ts)), meta) => {
946 utc_result_to_annotated(Utc.timestamp_opt(ts as i64, 0), ts, meta)
947 }
948 Annotated(Some(Value::I64(ts)), meta) => {
949 utc_result_to_annotated(Utc.timestamp_opt(ts, 0), ts, meta)
950 }
951 Annotated(Some(Value::F64(ts)), meta) => {
952 let secs = ts as i64;
953 let nanos = (ts.fract() * 1_000_000_000f64) as u32;
956 utc_result_to_annotated(Utc.timestamp_opt(secs, nanos), ts, meta)
957 }
958 Annotated(None, meta) => Annotated(None, meta),
959 Annotated(Some(value), mut meta) => {
960 meta.add_error(Error::expected("a timestamp"));
961 meta.set_original_value(Some(value));
962 Annotated(None, meta)
963 }
964 };
965
966 match rv {
967 Annotated(Some(value), mut meta) => {
968 if value.year() > 9999 {
969 meta.add_error(Error::invalid("timestamp out of range"));
973 meta.set_original_value(Some(Timestamp(value)));
974 Annotated(None, meta)
975 } else {
976 Annotated(Some(Timestamp(value)), meta)
977 }
978 }
979 x => x.map_value(Timestamp),
980 }
981 }
982}
983
984impl IntoValue for Timestamp {
985 fn into_value(self) -> Value {
986 Value::F64(datetime_to_timestamp(self.0))
987 }
988
989 fn serialize_payload<S>(&self, s: S, _behavior: SkipSerialization) -> Result<S::Ok, S::Error>
990 where
991 Self: Sized,
992 S: Serializer,
993 {
994 Serialize::serialize(&datetime_to_timestamp(self.0), s)
995 }
996}
997
998impl Empty for Timestamp {
999 fn is_empty(&self) -> bool {
1000 false
1001 }
1002}
1003
1004#[cfg(test)]
1005mod tests {
1006 use similar_asserts::assert_eq;
1007
1008 use super::*;
1009
1010 #[test]
1011 fn test_values_serialization() {
1012 let value = Annotated::new(Values {
1013 values: Annotated::new(vec![
1014 Annotated::new(0u64),
1015 Annotated::new(1u64),
1016 Annotated::new(2u64),
1017 ]),
1018 other: Object::default(),
1019 });
1020 assert_eq!(value.to_json().unwrap(), "{\"values\":[0,1,2]}");
1021 }
1022
1023 #[test]
1024 fn test_values_deserialization() {
1025 #[derive(Clone, Debug, Empty, FromValue, IntoValue, PartialEq)]
1026 struct Exception {
1027 #[metastructure(field = "type")]
1028 ty: Annotated<String>,
1029 value: Annotated<String>,
1030 }
1031 let value = Annotated::<Values<Exception>>::from_json(
1032 r#"{"values": [{"type": "Test", "value": "aha!"}]}"#,
1033 )
1034 .unwrap();
1035 assert_eq!(
1036 value,
1037 Annotated::new(Values::new(vec![Annotated::new(Exception {
1038 ty: Annotated::new("Test".to_string()),
1039 value: Annotated::new("aha!".to_string()),
1040 })]))
1041 );
1042
1043 let value =
1044 Annotated::<Values<Exception>>::from_json(r#"[{"type": "Test", "value": "aha!"}]"#)
1045 .unwrap();
1046 assert_eq!(
1047 value,
1048 Annotated::new(Values::new(vec![Annotated::new(Exception {
1049 ty: Annotated::new("Test".to_string()),
1050 value: Annotated::new("aha!".to_string()),
1051 })]))
1052 );
1053
1054 let value =
1055 Annotated::<Values<Exception>>::from_json(r#"{"type": "Test", "value": "aha!"}"#)
1056 .unwrap();
1057 assert_eq!(
1058 value,
1059 Annotated::new(Values::new(vec![Annotated::new(Exception {
1060 ty: Annotated::new("Test".to_string()),
1061 value: Annotated::new("aha!".to_string()),
1062 })]))
1063 );
1064 }
1065
1066 #[test]
1067 fn test_hex_to_string() {
1068 assert_eq!("0x0", &Addr(0).to_string());
1069 assert_eq!("0x2a", &Addr(42).to_string());
1070 }
1071
1072 #[test]
1073 fn test_hex_from_string() {
1074 assert_eq!(Addr(0), "0".parse().unwrap());
1075 assert_eq!(Addr(42), "42".parse().unwrap());
1076 assert_eq!(Addr(42), "0x2a".parse().unwrap());
1077 assert_eq!(Addr(42), "0X2A".parse().unwrap());
1078 }
1079
1080 #[test]
1081 fn test_hex_serialization() {
1082 let value = Value::String("0x2a".to_string());
1083 let addr: Annotated<Addr> = FromValue::from_value(Annotated::new(value));
1084 assert_eq!(addr.payload_to_json().unwrap(), "\"0x2a\"");
1085 let value = Value::U64(42);
1086 let addr: Annotated<Addr> = FromValue::from_value(Annotated::new(value));
1087 assert_eq!(addr.payload_to_json().unwrap(), "\"0x2a\"");
1088 }
1089
1090 #[test]
1091 fn test_hex_deserialization() {
1092 let addr = Annotated::<Addr>::from_json("\"0x2a\"").unwrap();
1093 assert_eq!(addr.payload_to_json().unwrap(), "\"0x2a\"");
1094 let addr = Annotated::<Addr>::from_json("42").unwrap();
1095 assert_eq!(addr.payload_to_json().unwrap(), "\"0x2a\"");
1096 }
1097
1098 #[test]
1099 fn test_level() {
1100 assert_eq!(
1101 Level::Info,
1102 Annotated::<Level>::from_json("\"log\"").unwrap().0.unwrap()
1103 );
1104 assert_eq!(
1105 Level::Warning,
1106 Annotated::<Level>::from_json("30").unwrap().0.unwrap()
1107 );
1108 assert_eq!(
1109 Level::Fatal,
1110 Annotated::<Level>::from_json("\"critical\"")
1111 .unwrap()
1112 .0
1113 .unwrap()
1114 );
1115 }
1116
1117 #[test]
1118 fn test_ip_addr() {
1119 assert_eq!(
1120 IpAddr("{{auto}}".into()),
1121 Annotated::<IpAddr>::from_json("\"{{auto}}\"")
1122 .unwrap()
1123 .0
1124 .unwrap()
1125 );
1126 assert_eq!(
1127 IpAddr("127.0.0.1".into()),
1128 Annotated::<IpAddr>::from_json("\"127.0.0.1\"")
1129 .unwrap()
1130 .0
1131 .unwrap()
1132 );
1133 assert_eq!(
1134 IpAddr("::1".into()),
1135 Annotated::<IpAddr>::from_json("\"::1\"")
1136 .unwrap()
1137 .0
1138 .unwrap()
1139 );
1140 assert_eq!(
1141 Annotated::from_error(
1142 Error::expected("an ip address"),
1143 Some(Value::String("clearly invalid value".into()))
1144 ),
1145 Annotated::<IpAddr>::from_json("\"clearly invalid value\"").unwrap()
1146 );
1147 }
1148
1149 #[test]
1150 fn test_timestamp_year_out_of_range() {
1151 #[derive(Debug, FromValue, Default, Empty, IntoValue)]
1152 struct Helper {
1153 foo: Annotated<Timestamp>,
1154 }
1155
1156 let x: Annotated<Helper> = Annotated::from_json(r#"{"foo": 1562770897893}"#).unwrap();
1157 assert_eq!(
1158 x.to_json_pretty().unwrap(),
1159 r#"{
1160 "foo": null,
1161 "_meta": {
1162 "foo": {
1163 "": {
1164 "err": [
1165 [
1166 "invalid_data",
1167 {
1168 "reason": "timestamp out of range"
1169 }
1170 ]
1171 ],
1172 "val": 1562770897893.0
1173 }
1174 }
1175 }
1176}"#
1177 );
1178 }
1179
1180 #[test]
1181 fn test_timestamp_completely_out_of_range() {
1182 #[derive(Debug, FromValue, Default, Empty, IntoValue)]
1183 struct Helper {
1184 foo: Annotated<Timestamp>,
1185 }
1186
1187 let x: Annotated<Helper> =
1188 Annotated::from_json(r#"{"foo": -10000000000000000.0}"#).unwrap();
1189 assert_eq!(
1190 x.to_json_pretty().unwrap(),
1191 r#"{
1192 "foo": null,
1193 "_meta": {
1194 "foo": {
1195 "": {
1196 "err": [
1197 [
1198 "invalid_data",
1199 {
1200 "reason": "timestamp out of range"
1201 }
1202 ]
1203 ],
1204 "val": -1e16
1205 }
1206 }
1207 }
1208}"#
1209 );
1210 }
1211}