1use super::types;
2
3#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub enum Value {
6 Blob(types::Blob),
7 Boolean(types::Boolean),
8 Date(types::Date),
9 DateTime(types::DateTime),
10 Decimal(types::Decimal),
11 Int32(types::Int32),
12 Int64(types::Int64),
13 Null,
14 Principal(types::Principal),
15 Text(types::Text),
16 Uint32(types::Uint32),
17 Uint64(types::Uint64),
18 Uuid(types::Uuid),
19}
20
21macro_rules! impl_conv_for_value {
23 ($variant:ident, $ty:ty, $name:ident) => {
24 impl From<$ty> for Value {
25 fn from(value: $ty) -> Self {
26 Value::$variant(value)
27 }
28 }
29
30 impl Value {
31 pub fn $name(&self) -> Option<&$ty> {
33 if let Value::$variant(v) = self {
34 Some(v)
35 } else {
36 None
37 }
38 }
39 }
40 };
41}
42
43impl_conv_for_value!(Blob, types::Blob, as_blob);
44impl_conv_for_value!(Boolean, types::Boolean, as_boolean);
45impl_conv_for_value!(Date, types::Date, as_date);
46impl_conv_for_value!(DateTime, types::DateTime, as_datetime);
47impl_conv_for_value!(Decimal, types::Decimal, as_decimal);
48impl_conv_for_value!(Int32, types::Int32, as_int32);
49impl_conv_for_value!(Int64, types::Int64, as_int64);
50impl_conv_for_value!(Principal, types::Principal, as_principal);
51impl_conv_for_value!(Text, types::Text, as_text);
52impl_conv_for_value!(Uint32, types::Uint32, as_uint32);
53impl_conv_for_value!(Uint64, types::Uint64, as_uint64);
54impl_conv_for_value!(Uuid, types::Uuid, as_uuid);
55
56impl Value {
57 pub fn is_null(&self) -> bool {
59 matches!(self, Value::Null)
60 }
61
62 pub fn type_name(&self) -> &'static str {
64 match self {
65 Value::Blob(_) => "Blob",
66 Value::Boolean(_) => "Boolean",
67 Value::Date(_) => "Date",
68 Value::DateTime(_) => "DateTime",
69 Value::Decimal(_) => "Decimal",
70 Value::Int32(_) => "Int32",
71 Value::Int64(_) => "Int64",
72 Value::Null => "Null",
73 Value::Principal(_) => "Principal",
74 Value::Text(_) => "Text",
75 Value::Uint32(_) => "Uint32",
76 Value::Uint64(_) => "Uint64",
77 Value::Uuid(_) => "Uuid",
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84
85 use uuid::Uuid;
86
87 use super::*;
88
89 #[test]
90 fn test_null() {
91 let int_value: Value = types::Int32(42).into();
92 assert!(!int_value.is_null());
93
94 let null_value = Value::Null;
95 assert!(null_value.is_null());
96 }
97
98 #[test]
99 fn test_value_conversion_blob() {
100 let blob = types::Blob(vec![1, 2, 3]);
101 let value: Value = blob.clone().into();
102 assert_eq!(value.as_blob(), Some(&blob));
103 }
104
105 #[test]
106 fn test_value_conversion_boolean() {
107 let boolean = types::Boolean(true);
108 let value: Value = boolean.into();
109 assert_eq!(value.as_boolean(), Some(&boolean));
110 }
111
112 #[test]
113 fn test_value_conversion_date() {
114 let date = types::Date {
115 year: 2023,
116 month: 3,
117 day: 15,
118 }; let value: Value = date.into();
120 assert_eq!(value.as_date(), Some(&date));
121 }
122
123 #[test]
124 fn test_value_conversion_datetime() {
125 let datetime = types::DateTime {
126 year: 2023,
127 month: 3,
128 day: 15,
129 hour: 12,
130 minute: 30,
131 second: 45,
132 microsecond: 123456,
133 timezone_offset_minutes: 0,
134 }; let value: Value = datetime.into();
136 assert_eq!(value.as_datetime(), Some(&datetime));
137 }
138
139 #[test]
140 fn test_value_conversion_decimal() {
141 let decimal = types::Decimal(rust_decimal::Decimal::new(12345, 2)); let value: Value = decimal.into();
143 assert_eq!(value.as_decimal(), Some(&decimal));
144 }
145
146 #[test]
147 fn test_value_conversion_int32() {
148 let int32 = types::Int32(1234567890);
149 let value: Value = int32.into();
150 assert_eq!(value.as_int32(), Some(&int32));
151 }
152
153 #[test]
154 fn test_value_conversion_int64() {
155 let int64 = types::Int64(1234567890);
156 let value: Value = int64.into();
157 assert_eq!(value.as_int64(), Some(&int64));
158 }
159
160 #[test]
161 fn test_value_conversion_principal() {
162 let principal = types::Principal(candid::Principal::from_text("aaaaa-aa").unwrap());
163 let value: Value = principal.clone().into();
164 assert_eq!(value.as_principal(), Some(&principal));
165 }
166
167 #[test]
168 fn test_value_conversion_text() {
169 let text = types::Text("Hello, World!".to_string());
170 let value: Value = text.clone().into();
171 assert_eq!(value.as_text(), Some(&text));
172 }
173
174 #[test]
175 fn test_value_conversion_uint32() {
176 let uint32 = types::Uint32(123456);
177 let value: Value = uint32.into();
178 assert_eq!(value.as_uint32(), Some(&uint32));
179 }
180
181 #[test]
182 fn test_value_conversion_uint64() {
183 let uint64 = types::Uint64(12345678901234);
184 let value: Value = uint64.into();
185 assert_eq!(value.as_uint64(), Some(&uint64));
186 }
187
188 #[test]
189 fn test_value_conversion_uuid() {
190 let uuid = types::Uuid(
191 Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").expect("failed to parse uuid"),
192 );
193 let value: Value = uuid.clone().into();
194 assert_eq!(value.as_uuid(), Some(&uuid));
195 }
196
197 #[test]
198 fn test_value_type_name() {
199 let int_value: Value = types::Int32(42).into();
200 assert_eq!(int_value.type_name(), "Int32");
201
202 let text_value: Value = types::Text("Hello".to_string()).into();
203 assert_eq!(text_value.type_name(), "Text");
204
205 let null_value = Value::Null;
206 assert_eq!(null_value.type_name(), "Null");
207 }
208}