1use std::collections::BTreeMap;
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7use crate::StrOrI64;
8
9use super::{mail::MailProvider, response::Redirect, route::Route};
10
11#[derive(Debug, Serialize, Deserialize, Clone)]
32pub enum Data {
33 None,
35 Usize(usize),
37 I16(i16),
39 I32(i32),
41 I64(i64),
43 F32(f32),
45 F64(f64),
47 Bool(bool),
49 String(String),
51 Date(DateTime<Utc>),
53 Json(Value),
55 Vec(Vec<Data>),
57 Raw(Vec<u8>),
59 Map(BTreeMap<i64, Data>),
61 #[serde(skip_serializing, skip_deserializing)]
63 Route(Route),
64 #[serde(skip_serializing, skip_deserializing)]
66 Redirect(Redirect),
67 #[serde(skip_serializing, skip_deserializing)]
69 MailProvider(MailProvider),
70}
71
72macro_rules! impl_from_for_data {
73 ($($type:ty => $variant:ident),* $(,)?) => {
74 $(
75 impl From<$type> for Data {
76 fn from(value: $type) -> Self {
77 Data::$variant(value)
78 }
79 }
80
81 impl From<Data> for $type {
82 fn from(value: Data) -> Self {
83 if let Data::$variant(inner) = value {
84 inner
85 } else {
86 panic!("Cannot convert {:?} to {}", value, stringify!($type))
87 }
88 }
89 }
90
91 impl<'a> From<&'a Data> for &'a $type {
92 fn from(value: &'a Data) -> Self {
93 if let Data::$variant(inner) = value {
94 inner
95 } else {
96 panic!("Cannot convert {:?} to {}", value, stringify!($type))
97 }
98 }
99 }
100
101 )*
102 };
103}
104
105impl_from_for_data!(
106 usize => Usize,
107 i16 => I16,
108 i32 => I32,
109 i64 => I64,
110 f32 => F32,
111 f64 => F64,
112 bool => Bool,
113 String => String,
114 DateTime<Utc> => Date,
115 Value => Json,
116 Vec<Data> => Vec,
117 Vec<u8> => Raw,
118 BTreeMap<i64, Data> => Map,
119);
120
121impl Data {
122 pub fn get<T>(&self, key: impl StrOrI64) -> Option<&T>
123 where
124 for<'a> &'a T: From<&'a Data>,
125 {
126 match self {
127 Data::Vec(vec) => match usize::try_from(key.to_i64()) {
128 Ok(index) => {
129 let value = vec.get(index)?;
130 Some(value.into())
131 }
132 #[cfg(not(debug_assertions))]
133 Err(_) => None,
134 #[cfg(debug_assertions)]
135 Err(e) => panic!("The key must be in the range for type usize. Err: {}", e),
136 },
137 Data::Map(map) => {
138 let value = map.get(&key.to_i64())?;
139 Some(value.into())
140 }
141 #[cfg(not(debug_assertions))]
142 _ => None,
143 #[cfg(debug_assertions)]
144 _ => panic!("Must be Data::Map<Data> or Data::Vec<Data>"),
145 }
146 }
147
148 pub fn take<T>(&mut self, key: impl StrOrI64) -> Option<T>
149 where
150 T: From<Data>,
151 {
152 match self {
153 Data::Vec(vec) => match usize::try_from(key.to_i64()) {
154 Ok(index) => {
155 let value = vec.remove(index);
156 Some(value.into())
157 }
158 #[cfg(not(debug_assertions))]
159 Err(_) => None,
160 #[cfg(debug_assertions)]
161 Err(e) => panic!("The key must be in the range for type usize. Err: {}", e),
162 },
163 Data::Map(map) => {
164 let value = map.remove(&key.to_i64())?;
165 Some(value.into())
166 }
167 #[cfg(not(debug_assertions))]
168 _ => None,
169 #[cfg(debug_assertions)]
170 _ => panic!("Must be Data::Map<Data> or Data::Vec<Data>"),
171 }
172 }
173}