1pub use crate::value::Value;
16use base64::Engine;
17use base64::prelude::BASE64_STANDARD;
18use prost_types::Value as ProtoValue;
19use rust_decimal::Decimal;
20
21use std::time::SystemTime;
22use time::{Date, OffsetDateTime};
23
24pub trait ToValue {
33 fn to_value(&self) -> Value;
38}
39
40impl<T> ToValue for Option<T>
41where
42 T: ToValue,
43{
44 fn to_value(&self) -> Value {
45 match self {
46 Some(v) => v.to_value(),
47 None => Value(ProtoValue {
48 kind: Some(prost_types::value::Kind::NullValue(0)),
49 }),
50 }
51 }
52}
53
54impl ToValue for Value {
55 fn to_value(&self) -> Value {
56 self.clone()
57 }
58}
59
60impl ToValue for ProtoValue {
61 fn to_value(&self) -> Value {
62 Value(self.clone())
63 }
64}
65
66impl ToValue for String {
67 fn to_value(&self) -> Value {
68 Value(ProtoValue {
69 kind: Some(prost_types::value::Kind::StringValue(self.clone())),
70 })
71 }
72}
73
74impl ToValue for &str {
75 fn to_value(&self) -> Value {
76 Value(ProtoValue {
77 kind: Some(prost_types::value::Kind::StringValue(self.to_string())),
78 })
79 }
80}
81
82impl ToValue for i64 {
83 fn to_value(&self) -> Value {
84 Value(ProtoValue {
85 kind: Some(prost_types::value::Kind::StringValue(self.to_string())),
86 })
87 }
88}
89
90impl ToValue for i32 {
91 fn to_value(&self) -> Value {
92 Value(ProtoValue {
93 kind: Some(prost_types::value::Kind::StringValue(self.to_string())),
94 })
95 }
96}
97
98impl ToValue for Decimal {
99 fn to_value(&self) -> Value {
100 Value(ProtoValue {
101 kind: Some(prost_types::value::Kind::StringValue(self.to_string())),
102 })
103 }
104}
105
106impl ToValue for SystemTime {
107 fn to_value(&self) -> Value {
108 let dt = OffsetDateTime::from(*self);
109 Value(ProtoValue {
110 kind: Some(prost_types::value::Kind::StringValue(
111 dt.format(crate::value::SPANNER_TIMESTAMP_FORMAT)
112 .expect("failed to format time"),
113 )),
114 })
115 }
116}
117
118impl ToValue for OffsetDateTime {
119 fn to_value(&self) -> Value {
120 Value(ProtoValue {
121 kind: Some(prost_types::value::Kind::StringValue(
122 self.format(crate::value::SPANNER_TIMESTAMP_FORMAT)
123 .expect("failed to format time"),
124 )),
125 })
126 }
127}
128
129impl ToValue for wkt::Timestamp {
130 fn to_value(&self) -> Value {
131 let dt = OffsetDateTime::try_from(*self)
132 .expect("valid wkt timestamp conversion to OffsetDateTime");
133 dt.to_value()
134 }
135}
136
137impl ToValue for Date {
138 fn to_value(&self) -> Value {
139 Value(ProtoValue {
140 kind: Some(prost_types::value::Kind::StringValue(
141 self.format(crate::value::SPANNER_DATE_FORMAT)
142 .expect("failed to format date"),
143 )),
144 })
145 }
146}
147
148impl ToValue for bool {
149 fn to_value(&self) -> Value {
150 Value(ProtoValue {
151 kind: Some(prost_types::value::Kind::BoolValue(*self)),
152 })
153 }
154}
155
156impl ToValue for f64 {
157 fn to_value(&self) -> Value {
158 Value(ProtoValue {
159 kind: Some(prost_types::value::Kind::NumberValue(*self)),
160 })
161 }
162}
163
164impl ToValue for f32 {
165 fn to_value(&self) -> Value {
166 Value(ProtoValue {
167 kind: Some(prost_types::value::Kind::NumberValue(*self as f64)),
168 })
169 }
170}
171
172impl ToValue for Vec<u8> {
173 fn to_value(&self) -> Value {
174 Value(ProtoValue {
175 kind: Some(prost_types::value::Kind::StringValue(
176 BASE64_STANDARD.encode(self),
177 )),
178 })
179 }
180}
181
182impl<T> ToValue for Vec<T>
183where
184 T: ToValue,
185{
186 fn to_value(&self) -> Value {
187 Value(ProtoValue {
188 kind: Some(prost_types::value::Kind::ListValue(
189 prost_types::ListValue {
190 values: self.iter().map(|v| v.to_value().0).collect(),
191 },
192 )),
193 })
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200 use crate::value::Kind;
201 use std::str::FromStr;
202
203 #[test]
204 fn test_to_value_string() {
205 let v = "hello".to_string().to_value();
206 assert_eq!(v.kind(), Kind::String);
207 assert_eq!(v.as_string(), "hello");
208
209 let v = "world".to_value();
210 assert_eq!(v.kind(), Kind::String);
211 assert_eq!(v.as_string(), "world");
212 }
213
214 #[test]
215 fn test_to_value_int() {
216 let v = 42i64.to_value();
217 assert_eq!(v.kind(), Kind::String);
218 assert_eq!(v.as_string(), "42");
219
220 let v = 42i32.to_value();
221 assert_eq!(v.kind(), Kind::String);
222 assert_eq!(v.as_string(), "42");
223 }
224
225 #[test]
226 fn test_to_value_float() {
227 let v = 42.5f64.to_value();
228 assert_eq!(v.kind(), Kind::Number);
229 assert_eq!(v.as_f64(), 42.5);
230
231 let v = 42.5f32.to_value();
232 assert_eq!(v.kind(), Kind::Number);
233 assert_eq!(v.as_f64(), 42.5);
234 }
235
236 #[test]
237 fn test_to_value_bool() {
238 let v = true.to_value();
239 assert_eq!(v.kind(), Kind::Bool);
240 assert!(v.as_bool());
241
242 let v = false.to_value();
243 assert_eq!(v.kind(), Kind::Bool);
244 assert!(!v.as_bool());
245 }
246
247 #[test]
248 fn test_to_value_bytes() {
249 let bytes: Vec<u8> = vec![1, 2, 3];
250 let v = bytes.to_value();
251 assert_eq!(v.kind(), Kind::String);
252 assert_eq!(v.as_string(), "AQID"); }
254
255 #[test]
256 fn test_to_value_decimal() {
257 let d = Decimal::from_str("123.456").unwrap();
258 let v = d.to_value();
259 assert_eq!(v.kind(), Kind::String);
260 assert_eq!(v.as_string(), "123.456");
261 }
262
263 #[test]
264 fn test_to_value_date() {
265 let d = Date::from_calendar_date(2023, time::Month::October, 27).unwrap();
266 let v = d.to_value();
267 assert_eq!(v.kind(), Kind::String);
268 assert_eq!(v.as_string(), "2023-10-27");
269 }
270
271 #[test]
272 fn test_to_value_timestamp() {
273 let dt = OffsetDateTime::parse(
274 "2023-10-27T10:00:00Z",
275 &time::format_description::well_known::Rfc3339,
276 )
277 .unwrap();
278 let v = dt.to_value();
279 assert_eq!(v.kind(), Kind::String);
280 assert_eq!(v.as_string(), "2023-10-27T10:00:00.000000000Z");
281
282 let system_time: SystemTime = dt.into();
283 let v = system_time.to_value();
284 assert_eq!(v.kind(), Kind::String);
285 assert_eq!(v.as_string(), "2023-10-27T10:00:00.000000000Z");
286 }
287
288 #[test]
289 fn test_to_value_wkt_timestamp() {
290 let dt = OffsetDateTime::parse(
291 "2023-10-27T10:00:00Z",
292 &time::format_description::well_known::Rfc3339,
293 )
294 .expect("valid date time parsing");
295 let wkt_ts = wkt::Timestamp::try_from(dt).expect("valid wkt timestamp conversion");
296 let v = wkt_ts.to_value();
297 assert_eq!(v.kind(), Kind::String);
298 assert_eq!(v.as_string(), "2023-10-27T10:00:00.000000000Z");
299 }
300
301 #[test]
302 fn test_to_value_option() {
303 let some_val: Option<i32> = Some(42);
304 let v = some_val.to_value();
305 assert_eq!(v.kind(), Kind::String);
306 assert_eq!(v.as_string(), "42");
307
308 let none_val: Option<i32> = None;
309 let v = none_val.to_value();
310 assert_eq!(v.kind(), Kind::Null);
311 }
312
313 #[test]
314 fn test_to_value_value() {
315 let v_original = 42i32.to_value();
316 let v = v_original.to_value();
317 assert_eq!(v, v_original);
318
319 let v_proto = ProtoValue {
320 kind: Some(prost_types::value::Kind::BoolValue(true)),
321 };
322 let v = v_proto.to_value();
323 assert_eq!(v.kind(), Kind::Bool);
324 assert!(v.as_bool());
325 }
326
327 #[test]
328 fn test_to_value_array() {
329 let str_array = vec!["one".to_string(), "two".to_string()];
330 let v = str_array.to_value();
331 assert_eq!(v.kind(), Kind::List);
332 let list = v.as_list();
333 assert_eq!(list.len(), 2);
334 assert_eq!(
335 list.get(0).expect("element 0 should exist").as_string(),
336 "one"
337 );
338 assert_eq!(
339 list.get(1).expect("element 1 should exist").as_string(),
340 "two"
341 );
342
343 let int_array = vec![42i64, 100i64];
344 let v = int_array.to_value();
345 assert_eq!(v.kind(), Kind::List);
346 let list = v.as_list();
347 assert_eq!(list.len(), 2);
348 assert_eq!(
349 list.get(0).expect("element 0 should exist").as_string(),
350 "42"
351 );
352 assert_eq!(
353 list.get(1).expect("element 1 should exist").as_string(),
354 "100"
355 );
356
357 let bool_array = vec![true, false];
358 let v = bool_array.to_value();
359 assert_eq!(v.kind(), Kind::List);
360 let list = v.as_list();
361 assert_eq!(list.len(), 2);
362 assert!(list.get(0).expect("element 0 should exist").as_bool());
363 assert!(!list.get(1).expect("element 1 should exist").as_bool());
364
365 let float_array = vec![9.9f64, -2.5f64];
366 let v = float_array.to_value();
367 assert_eq!(v.kind(), Kind::List);
368 let list = v.as_list();
369 assert_eq!(list.len(), 2);
370 assert_eq!(list.get(0).expect("element 0 should exist").as_f64(), 9.9);
371 assert_eq!(list.get(1).expect("element 1 should exist").as_f64(), -2.5);
372
373 let empty_array: Vec<f64> = vec![];
374 let v = empty_array.to_value();
375 assert_eq!(v.kind(), Kind::List);
376 assert_eq!(v.as_list().len(), 0);
377
378 let null_array: Option<Vec<i64>> = None;
379 let v = null_array.to_value();
380 assert_eq!(v.kind(), Kind::Null);
381
382 let opt_array: Vec<Option<i64>> = vec![Some(42), None, Some(100)];
383 let v = opt_array.to_value();
384 assert_eq!(v.kind(), Kind::List);
385 let list = v.as_list();
386 assert_eq!(list.len(), 3);
387 assert_eq!(
388 list.get(0).expect("element 0 should exist").as_string(),
389 "42"
390 );
391 assert_eq!(
392 list.get(1).expect("element 1 should exist").kind(),
393 Kind::Null
394 );
395 assert_eq!(
396 list.get(2).expect("element 2 should exist").as_string(),
397 "100"
398 );
399 }
400}