1use std::{collections::HashMap, hash::BuildHasher};
2
3use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone};
4use chrono_tz::Tz;
5
6use crate::value::*;
7
8#[doc(hidden)]
11macro_rules! impl_from {
12 ($T:ty, $V:ident) => {
13 impl ::std::convert::From<$T> for $crate::Value {
14 fn from(value: $T) -> Self {
15 Value::$V(value)
16 }
17 }
18 };
19}
20
21impl_from!(bool, Boolean);
22
23macro_rules! impl_from_int {
24 ($($T:ty),+) => {
25 $(
26 impl ::std::convert::From<$T> for $crate::Value {
27 fn from(value: $T) -> Self {
28 Value::Integer(value as i64)
29 }
30 }
31 )*
32 };
33}
34impl_from_int!(i8, i16, i32, i64);
35
36impl_from!(f64, Float);
37
38impl From<&[u8]> for Value {
39 fn from(value: &[u8]) -> Self {
40 Value::Bytes(value.to_vec())
41 }
42}
43
44impl_from!(Vec<u8>, Bytes);
45
46impl<T> From<Vec<T>> for Value
47where
48 T: Into<Value>,
49{
50 fn from(value: Vec<T>) -> Self {
51 Value::List(value.into_iter().map(T::into).collect())
52 }
53}
54
55impl<K, V, S> From<HashMap<K, V, S>> for Value
56where
57 K: Into<std::string::String>,
58 V: Into<Value>,
59 S: BuildHasher,
60{
61 fn from(value: HashMap<K, V, S>) -> Self {
62 Value::Map(
63 value
64 .into_iter()
65 .map(|(k, v)| (K::into(k), V::into(v)))
66 .collect(),
67 )
68 }
69}
70
71impl From<&str> for Value {
72 fn from(value: &str) -> Self {
73 Value::String(String::from(value))
74 }
75}
76
77impl_from!(String, String);
78
79impl_from!(Node, Node);
80
81impl_from!(Relationship, Relationship);
82
83impl_from!(Path, Path);
84
85impl_from!(UnboundRelationship, UnboundRelationship);
86
87impl_from!(NaiveDate, Date);
88
89impl<O: Offset> From<(NaiveTime, O)> for Value {
91 fn from(pair: (NaiveTime, O)) -> Self {
92 Value::Time(pair.0, pair.1.fix())
93 }
94}
95
96impl<T: TimeZone> From<DateTime<T>> for Value {
97 fn from(value: DateTime<T>) -> Self {
98 Value::DateTimeOffset(DateTime::from_utc(value.naive_utc(), value.offset().fix()))
99 }
100}
101
102impl From<(NaiveDateTime, chrono_tz::Tz)> for Value {
105 fn from(pair: (NaiveDateTime, chrono_tz::Tz)) -> Self {
106 Value::DateTimeZoned(pair.1.from_utc_datetime(&pair.0))
107 }
108}
109
110impl_from!(NaiveTime, LocalTime);
111
112impl_from!(NaiveDateTime, LocalDateTime);
113
114impl_from!(Duration, Duration);
115
116impl From<std::time::Duration> for Value {
117 fn from(value: std::time::Duration) -> Self {
118 Value::Duration(Duration::from(value))
119 }
120}
121
122impl_from!(Point2D, Point2D);
123
124impl_from!(Point3D, Point3D);
125
126impl<T: Into<Value>> From<Option<T>> for Value {
127 fn from(option: Option<T>) -> Self {
128 match option {
129 Some(v) => v.into(),
130 None => Value::Null,
131 }
132 }
133}
134
135#[doc(hidden)]
138macro_rules! impl_try_from_value {
139 ($T:ty, $V:ident) => {
140 impl ::std::convert::TryFrom<$crate::Value> for $T {
141 type Error = $crate::error::ConversionError;
142
143 fn try_from(value: $crate::Value) -> $crate::error::ConversionResult<Self> {
144 match value {
145 $crate::Value::$V(inner) => Ok(inner),
146 _ => Err($crate::error::ConversionError::FromValue(value)),
147 }
148 }
149 }
150 };
151}
152
153impl_try_from_value!(bool, Boolean);
154
155macro_rules! impl_try_from_value_for_ints {
156 ($($T:ty),+) => {
157 $(
158 impl TryFrom<$crate::Value> for $T {
159 type Error = $crate::error::ConversionError;
160
161 fn try_from(value: $crate::Value) -> $crate::error::ConversionResult<Self> {
162 use ::std::convert::TryInto;
163
164 match value {
165 $crate::Value::Integer(integer) => Ok(integer.try_into()?),
166 _ => Err($crate::error::ConversionError::FromValue(value)),
167 }
168 }
169 }
170 )*
171 };
172}
173impl_try_from_value_for_ints!(i8, i16, i32, i64);
174
175impl_try_from_value!(f64, Float);
176
177impl_try_from_value!(Vec<u8>, Bytes);
178
179impl<T> TryFrom<Value> for Vec<T>
180where
181 T: TryFrom<Value, Error = ConversionError>,
182{
183 type Error = ConversionError;
184
185 fn try_from(value: Value) -> ConversionResult<Self> {
186 match value {
187 Value::List(list) => list.into_iter().map(T::try_from).collect(),
188 _ => Err(ConversionError::FromValue(value)),
189 }
190 }
191}
192
193impl_try_from_value!(Vec<Value>, List);
194
195impl<V, S> TryFrom<Value> for HashMap<std::string::String, V, S>
196where
197 V: TryFrom<Value, Error = ConversionError>,
198 S: BuildHasher + Default,
199{
200 type Error = ConversionError;
201
202 fn try_from(value: Value) -> ConversionResult<Self> {
203 match value {
204 Value::Map(map) => {
205 let mut new_map = HashMap::with_capacity_and_hasher(map.len(), Default::default());
206 for (k, v) in map {
207 new_map.insert(k, V::try_from(v)?);
208 }
209 Ok(new_map)
210 }
211 _ => Err(ConversionError::FromValue(value)),
212 }
213 }
214}
215
216impl<S> TryFrom<Value> for HashMap<std::string::String, Value, S>
217where
218 S: BuildHasher + Default,
219{
220 type Error = ConversionError;
221
222 fn try_from(value: Value) -> ConversionResult<Self> {
223 match value {
224 Value::Map(map) => {
225 let mut new_map = HashMap::with_capacity_and_hasher(map.len(), Default::default());
226 for (k, v) in map {
227 new_map.insert(k, v);
228 }
229 Ok(new_map)
230 }
231 _ => Err(ConversionError::FromValue(value)),
232 }
233 }
234}
235
236impl_try_from_value!(String, String);
237
238impl_try_from_value!(Node, Node);
239
240impl_try_from_value!(Relationship, Relationship);
241
242impl_try_from_value!(Path, Path);
243
244impl_try_from_value!(UnboundRelationship, UnboundRelationship);
245
246impl_try_from_value!(NaiveDate, Date);
247
248impl TryFrom<Value> for DateTime<FixedOffset> {
249 type Error = ConversionError;
250
251 fn try_from(value: Value) -> ConversionResult<Self> {
252 match value {
253 Value::DateTimeOffset(date_time_offset) => Ok(date_time_offset),
254 Value::DateTimeZoned(date_time_zoned) => {
255 Ok(date_time_zoned.with_timezone(&date_time_zoned.offset().fix()))
256 }
257 _ => Err(ConversionError::FromValue(value)),
258 }
259 }
260}
261
262impl_try_from_value!(DateTime<Tz>, DateTimeZoned);
263
264impl_try_from_value!(NaiveTime, LocalTime);
265
266impl_try_from_value!(NaiveDateTime, LocalDateTime);
267
268impl_try_from_value!(Duration, Duration);
272
273impl_try_from_value!(Point2D, Point2D);
274
275impl_try_from_value!(Point3D, Point3D);