Skip to main content

reifydb_type/value/
into.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2025 ReifyDB
3
4use crate::value::{
5	Value,
6	blob::Blob,
7	date::Date,
8	datetime::DateTime,
9	duration::Duration,
10	identity::IdentityId,
11	ordered_f32::OrderedF32,
12	ordered_f64::OrderedF64,
13	time::Time,
14	r#type::Type,
15	uuid::{Uuid4, Uuid7},
16};
17
18pub trait IntoValue {
19	fn into_value(self) -> Value;
20}
21
22impl IntoValue for Value {
23	fn into_value(self) -> Value {
24		self
25	}
26}
27
28impl IntoValue for bool {
29	fn into_value(self) -> Value {
30		Value::Boolean(self)
31	}
32}
33
34impl IntoValue for i8 {
35	fn into_value(self) -> Value {
36		Value::Int1(self)
37	}
38}
39
40impl IntoValue for i16 {
41	fn into_value(self) -> Value {
42		Value::Int2(self)
43	}
44}
45
46impl IntoValue for i32 {
47	fn into_value(self) -> Value {
48		Value::Int4(self)
49	}
50}
51
52impl IntoValue for i64 {
53	fn into_value(self) -> Value {
54		Value::Int8(self)
55	}
56}
57
58impl IntoValue for i128 {
59	fn into_value(self) -> Value {
60		Value::Int16(self)
61	}
62}
63
64impl IntoValue for u8 {
65	fn into_value(self) -> Value {
66		Value::Uint1(self)
67	}
68}
69
70impl IntoValue for u16 {
71	fn into_value(self) -> Value {
72		Value::Uint2(self)
73	}
74}
75
76impl IntoValue for u32 {
77	fn into_value(self) -> Value {
78		Value::Uint4(self)
79	}
80}
81
82impl IntoValue for u64 {
83	fn into_value(self) -> Value {
84		Value::Uint8(self)
85	}
86}
87
88impl IntoValue for u128 {
89	fn into_value(self) -> Value {
90		Value::Uint16(self)
91	}
92}
93
94impl IntoValue for f32 {
95	fn into_value(self) -> Value {
96		OrderedF32::try_from(self).map(|v| Value::Float4(v)).unwrap_or(Value::None {
97			inner: Type::Float4,
98		})
99	}
100}
101
102impl IntoValue for f64 {
103	fn into_value(self) -> Value {
104		OrderedF64::try_from(self).map(|v| Value::Float8(v)).unwrap_or(Value::None {
105			inner: Type::Float8,
106		})
107	}
108}
109
110impl IntoValue for String {
111	fn into_value(self) -> Value {
112		Value::Utf8(self)
113	}
114}
115
116impl IntoValue for &str {
117	fn into_value(self) -> Value {
118		Value::Utf8(self.to_string())
119	}
120}
121
122impl IntoValue for OrderedF32 {
123	fn into_value(self) -> Value {
124		Value::Float4(self)
125	}
126}
127
128impl IntoValue for OrderedF64 {
129	fn into_value(self) -> Value {
130		Value::Float8(self)
131	}
132}
133
134impl IntoValue for Blob {
135	fn into_value(self) -> Value {
136		Value::Blob(self)
137	}
138}
139
140impl IntoValue for Uuid4 {
141	fn into_value(self) -> Value {
142		Value::Uuid4(self)
143	}
144}
145
146impl IntoValue for Uuid7 {
147	fn into_value(self) -> Value {
148		Value::Uuid7(self)
149	}
150}
151
152impl IntoValue for Date {
153	fn into_value(self) -> Value {
154		Value::Date(self)
155	}
156}
157
158impl IntoValue for DateTime {
159	fn into_value(self) -> Value {
160		Value::DateTime(self)
161	}
162}
163
164impl IntoValue for Time {
165	fn into_value(self) -> Value {
166		Value::Time(self)
167	}
168}
169
170impl IntoValue for Duration {
171	fn into_value(self) -> Value {
172		Value::Duration(self)
173	}
174}
175
176impl IntoValue for IdentityId {
177	fn into_value(self) -> Value {
178		Value::IdentityId(self)
179	}
180}
181
182impl<T: IntoValue> IntoValue for Option<T> {
183	fn into_value(self) -> Value {
184		match self {
185			Some(v) => v.into_value(),
186			None => Value::none(),
187		}
188	}
189}
190
191impl IntoValue for Vec<u8> {
192	fn into_value(self) -> Value {
193		Value::Blob(Blob::new(self))
194	}
195}
196
197impl IntoValue for &[u8] {
198	fn into_value(self) -> Value {
199		Value::Blob(Blob::from_slice(self))
200	}
201}
202
203impl<const N: usize> IntoValue for [u8; N] {
204	fn into_value(self) -> Value {
205		Value::Blob(Blob::from_slice(&self))
206	}
207}
208
209impl<const N: usize> IntoValue for &[u8; N] {
210	fn into_value(self) -> Value {
211		Value::Blob(Blob::from_slice(self))
212	}
213}
214
215#[cfg(test)]
216#[allow(clippy::approx_constant)]
217pub mod tests {
218	use std::f64::consts::PI;
219
220	use crate::value::{
221		Value, blob::Blob, into::IntoValue, ordered_f32::OrderedF32, ordered_f64::OrderedF64, r#type::Type,
222	};
223
224	#[test]
225	fn test_into_value_primitives() {
226		// Test boolean
227		assert_eq!(true.into_value(), Value::Boolean(true));
228		assert_eq!(false.into_value(), Value::Boolean(false));
229
230		// Test integers
231		assert_eq!(42i8.into_value(), Value::Int1(42));
232		assert_eq!(1234i16.into_value(), Value::Int2(1234));
233		assert_eq!(123456i32.into_value(), Value::Int4(123456));
234		assert_eq!(1234567890i64.into_value(), Value::Int8(1234567890));
235		assert_eq!(12345678901234567890i128.into_value(), Value::Int16(12345678901234567890));
236
237		// Test unsigned integers
238		assert_eq!(42u8.into_value(), Value::Uint1(42));
239		assert_eq!(1234u16.into_value(), Value::Uint2(1234));
240		assert_eq!(123456u32.into_value(), Value::Uint4(123456));
241		assert_eq!(1234567890u64.into_value(), Value::Uint8(1234567890));
242		assert_eq!(12345678901234567890u128.into_value(), Value::Uint16(12345678901234567890));
243
244		// Test floats
245		assert_eq!(3.14f32.into_value(), Value::Float4(OrderedF32::try_from(3.14f32).unwrap()));
246		assert_eq!(PI.into_value(), Value::Float8(OrderedF64::try_from(PI).unwrap()));
247
248		// Test NaN handling
249
250		assert_eq!(
251			f32::NAN.into_value(),
252			Value::None {
253				inner: Type::Float4
254			}
255		);
256		assert_eq!(
257			f64::NAN.into_value(),
258			Value::None {
259				inner: Type::Float8
260			}
261		);
262	}
263
264	#[test]
265	fn test_into_value_strings() {
266		assert_eq!("hello".into_value(), Value::Utf8("hello".to_string()));
267		assert_eq!("world".to_string().into_value(), Value::Utf8("world".to_string()));
268	}
269
270	#[test]
271	fn test_into_value_option() {
272		assert_eq!(Some(42i32).into_value(), Value::Int4(42));
273		assert_eq!(None::<i32>.into_value(), Value::none());
274		assert_eq!(Some("hello").into_value(), Value::Utf8("hello".to_string()));
275		assert_eq!(None::<&str>.into_value(), Value::none());
276	}
277
278	#[test]
279	fn test_into_value_bytes() {
280		// Test Vec<u8>
281		let vec_bytes = vec![1u8, 2, 3, 4];
282		assert_eq!(vec_bytes.clone().into_value(), Value::Blob(Blob::new(vec![1, 2, 3, 4])));
283
284		// Test &[u8]
285		let slice_bytes: &[u8] = &[5, 6, 7, 8];
286		assert_eq!(slice_bytes.into_value(), Value::Blob(Blob::from_slice(&[5, 6, 7, 8])));
287
288		// Test [u8; N]
289		let array_bytes: [u8; 4] = [9, 10, 11, 12];
290		assert_eq!(array_bytes.into_value(), Value::Blob(Blob::from_slice(&[9, 10, 11, 12])));
291
292		// Test &[u8; N]
293		let array_ref: &[u8; 3] = &[13, 14, 15];
294		assert_eq!(array_ref.into_value(), Value::Blob(Blob::from_slice(&[13, 14, 15])));
295
296		// Test Vec<u8>
297		let vec = vec![16, 17, 18];
298		assert_eq!(vec.into_value(), Value::Blob(Blob::new(vec![16, 17, 18])));
299	}
300}