reifydb_type/value/
mod.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the MIT, see license.md file
3
4use std::{
5	cmp::Ordering,
6	fmt::{Display, Formatter},
7};
8
9use serde::{Deserialize, Serialize};
10
11mod as_string;
12pub mod blob;
13pub mod boolean;
14pub mod constraint;
15pub mod container;
16mod date;
17mod datetime;
18pub mod decimal;
19mod dictionary_entry_id;
20mod duration;
21pub mod frame;
22mod identity;
23pub mod int;
24mod into;
25pub mod is;
26pub mod number;
27mod ordered_f32;
28mod ordered_f64;
29pub mod row_number;
30pub mod temporal;
31mod time;
32mod try_from;
33mod r#type;
34pub mod uint;
35pub mod uuid;
36
37pub use blob::Blob;
38pub use constraint::{Constraint, TypeConstraint};
39pub use date::Date;
40pub use datetime::DateTime;
41pub use decimal::Decimal;
42pub use dictionary_entry_id::DictionaryEntryId;
43pub use duration::Duration;
44pub use identity::IdentityId;
45pub use int::Int;
46pub use into::IntoValue;
47pub use ordered_f32::OrderedF32;
48pub use ordered_f64::OrderedF64;
49pub use row_number::RowNumber;
50pub use time::Time;
51pub use try_from::{FromValueError, TryFromValue, TryFromValueCoerce};
52pub use r#type::{GetType, Type};
53pub use uint::Uint;
54pub use uuid::{Uuid4, Uuid7};
55
56/// A RQL value, represented as a native Rust type.
57#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
58pub enum Value {
59	/// Value is not defined (think null in common programming languages)
60	Undefined,
61	/// A boolean: true or false.
62	Boolean(bool),
63	/// A 4-byte floating point
64	Float4(OrderedF32),
65	/// An 8-byte floating point
66	Float8(OrderedF64),
67	/// A 1-byte signed integer
68	Int1(i8),
69	/// A 2-byte signed integer
70	Int2(i16),
71	/// A 4-byte signed integer
72	Int4(i32),
73	/// An 8-byte signed integer
74	Int8(i64),
75	/// A 16-byte signed integer
76	Int16(i128),
77	/// A UTF-8 encoded text. Maximum 255 bytes
78	Utf8(String),
79	/// A 1-byte unsigned integer
80	Uint1(u8),
81	/// A 2-byte unsigned integer
82	Uint2(u16),
83	/// A 4-byte unsigned integer
84	Uint4(u32),
85	/// A 8-byte unsigned integer
86	Uint8(u64),
87	/// A 16-byte unsigned integer
88	Uint16(u128),
89	/// A date value (year, month, day)
90	Date(Date),
91	/// A date and time value with nanosecond precision in SVTC
92	DateTime(DateTime),
93	/// A time value (hour, minute, second, nanosecond)
94	Time(Time),
95	/// A duration representing a duration
96	Duration(Duration),
97	/// A encoded number (8-byte unsigned integer)
98	RowNumber(RowNumber),
99	/// An identity identifier (UUID v7)
100	IdentityId(IdentityId),
101	/// A UUID version 4 (random)
102	Uuid4(Uuid4),
103	/// A UUID version 7 (timestamp-based)
104	Uuid7(Uuid7),
105	/// A binary large object (BLOB)
106	Blob(Blob),
107	/// An arbitrary-precision signed integer
108	Int(Int),
109	/// An arbitrary-precision unsigned integer
110	Uint(Uint),
111	/// An arbitrary-precision decimal
112	Decimal(Decimal),
113	/// A container that can hold any value type
114	Any(Box<Value>),
115}
116
117impl Value {
118	pub fn undefined() -> Self {
119		Value::Undefined
120	}
121
122	pub fn bool(v: impl Into<bool>) -> Self {
123		Value::Boolean(v.into())
124	}
125
126	pub fn float4(v: impl Into<f32>) -> Self {
127		OrderedF32::try_from(v.into()).map(Value::Float4).unwrap_or(Value::Undefined)
128	}
129
130	pub fn float8(v: impl Into<f64>) -> Self {
131		OrderedF64::try_from(v.into()).map(Value::Float8).unwrap_or(Value::Undefined)
132	}
133
134	pub fn int1(v: impl Into<i8>) -> Self {
135		Value::Int1(v.into())
136	}
137
138	pub fn int2(v: impl Into<i16>) -> Self {
139		Value::Int2(v.into())
140	}
141
142	pub fn int4(v: impl Into<i32>) -> Self {
143		Value::Int4(v.into())
144	}
145
146	pub fn int8(v: impl Into<i64>) -> Self {
147		Value::Int8(v.into())
148	}
149
150	pub fn int16(v: impl Into<i128>) -> Self {
151		Value::Int16(v.into())
152	}
153
154	pub fn utf8(v: impl Into<String>) -> Self {
155		Value::Utf8(v.into())
156	}
157
158	pub fn uint1(v: impl Into<u8>) -> Self {
159		Value::Uint1(v.into())
160	}
161
162	pub fn uint2(v: impl Into<u16>) -> Self {
163		Value::Uint2(v.into())
164	}
165
166	pub fn uint4(v: impl Into<u32>) -> Self {
167		Value::Uint4(v.into())
168	}
169
170	pub fn uint8(v: impl Into<u64>) -> Self {
171		Value::Uint8(v.into())
172	}
173
174	pub fn uint16(v: impl Into<u128>) -> Self {
175		Value::Uint16(v.into())
176	}
177
178	pub fn date(v: impl Into<Date>) -> Self {
179		Value::Date(v.into())
180	}
181
182	pub fn datetime(v: impl Into<DateTime>) -> Self {
183		Value::DateTime(v.into())
184	}
185
186	pub fn time(v: impl Into<Time>) -> Self {
187		Value::Time(v.into())
188	}
189
190	pub fn duration(v: impl Into<Duration>) -> Self {
191		Value::Duration(v.into())
192	}
193
194	pub fn row_number(v: impl Into<RowNumber>) -> Self {
195		Value::RowNumber(v.into())
196	}
197
198	pub fn identity_id(v: impl Into<IdentityId>) -> Self {
199		Value::IdentityId(v.into())
200	}
201
202	pub fn uuid4(v: impl Into<Uuid4>) -> Self {
203		Value::Uuid4(v.into())
204	}
205
206	pub fn uuid7(v: impl Into<Uuid7>) -> Self {
207		Value::Uuid7(v.into())
208	}
209
210	pub fn blob(v: impl Into<Blob>) -> Self {
211		Value::Blob(v.into())
212	}
213
214	pub fn any(v: impl Into<Value>) -> Self {
215		Value::Any(Box::new(v.into()))
216	}
217}
218
219impl PartialOrd for Value {
220	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
221		match (self, other) {
222			(Value::Boolean(l), Value::Boolean(r)) => l.partial_cmp(r),
223			(Value::Float4(l), Value::Float4(r)) => l.partial_cmp(r),
224			(Value::Float8(l), Value::Float8(r)) => l.partial_cmp(r),
225			(Value::Int1(l), Value::Int1(r)) => l.partial_cmp(r),
226			(Value::Int2(l), Value::Int2(r)) => l.partial_cmp(r),
227			(Value::Int4(l), Value::Int4(r)) => l.partial_cmp(r),
228			(Value::Int8(l), Value::Int8(r)) => l.partial_cmp(r),
229			(Value::Int16(l), Value::Int16(r)) => l.partial_cmp(r),
230			(Value::Utf8(l), Value::Utf8(r)) => l.partial_cmp(r),
231			(Value::Uint1(l), Value::Uint1(r)) => l.partial_cmp(r),
232			(Value::Uint2(l), Value::Uint2(r)) => l.partial_cmp(r),
233			(Value::Uint4(l), Value::Uint4(r)) => l.partial_cmp(r),
234			(Value::Uint8(l), Value::Uint8(r)) => l.partial_cmp(r),
235			(Value::Uint16(l), Value::Uint16(r)) => l.partial_cmp(r),
236			(Value::Date(l), Value::Date(r)) => l.partial_cmp(r),
237			(Value::DateTime(l), Value::DateTime(r)) => l.partial_cmp(r),
238			(Value::Time(l), Value::Time(r)) => l.partial_cmp(r),
239			(Value::Duration(l), Value::Duration(r)) => l.partial_cmp(r),
240			(Value::RowNumber(l), Value::RowNumber(r)) => l.partial_cmp(r),
241			(Value::IdentityId(l), Value::IdentityId(r)) => l.partial_cmp(r),
242			(Value::Uuid4(l), Value::Uuid4(r)) => l.partial_cmp(r),
243			(Value::Uuid7(l), Value::Uuid7(r)) => l.partial_cmp(r),
244			(Value::Blob(l), Value::Blob(r)) => l.partial_cmp(r),
245			(Value::Int(l), Value::Int(r)) => l.partial_cmp(r),
246			(Value::Uint(l), Value::Uint(r)) => l.partial_cmp(r),
247			(Value::Decimal(l), Value::Decimal(r)) => l.partial_cmp(r),
248			(Value::Any(_), Value::Any(_)) => None, // Any values are not comparable
249			(Value::Undefined, Value::Undefined) => Some(Ordering::Equal),
250			// Undefined sorts after all other values (similar to NULL in SQL)
251			(Value::Undefined, _) => Some(Ordering::Greater),
252			(_, Value::Undefined) => Some(Ordering::Less),
253			(left, right) => {
254				unimplemented!("partial cmp {left:?} {right:?}")
255			}
256		}
257	}
258}
259
260impl Ord for Value {
261	fn cmp(&self, other: &Self) -> Ordering {
262		match (self, other) {
263			(Value::Boolean(l), Value::Boolean(r)) => l.cmp(r),
264			(Value::Float4(l), Value::Float4(r)) => l.cmp(r),
265			(Value::Float8(l), Value::Float8(r)) => l.cmp(r),
266			(Value::Int1(l), Value::Int1(r)) => l.cmp(r),
267			(Value::Int2(l), Value::Int2(r)) => l.cmp(r),
268			(Value::Int4(l), Value::Int4(r)) => l.cmp(r),
269			(Value::Int8(l), Value::Int8(r)) => l.cmp(r),
270			(Value::Int16(l), Value::Int16(r)) => l.cmp(r),
271			(Value::Utf8(l), Value::Utf8(r)) => l.cmp(r),
272			(Value::Uint1(l), Value::Uint1(r)) => l.cmp(r),
273			(Value::Uint2(l), Value::Uint2(r)) => l.cmp(r),
274			(Value::Uint4(l), Value::Uint4(r)) => l.cmp(r),
275			(Value::Uint8(l), Value::Uint8(r)) => l.cmp(r),
276			(Value::Uint16(l), Value::Uint16(r)) => l.cmp(r),
277			(Value::Date(l), Value::Date(r)) => l.cmp(r),
278			(Value::DateTime(l), Value::DateTime(r)) => l.cmp(r),
279			(Value::Time(l), Value::Time(r)) => l.cmp(r),
280			(Value::Duration(l), Value::Duration(r)) => l.cmp(r),
281			(Value::RowNumber(l), Value::RowNumber(r)) => l.cmp(r),
282			(Value::IdentityId(l), Value::IdentityId(r)) => l.cmp(r),
283			(Value::Uuid4(l), Value::Uuid4(r)) => l.cmp(r),
284			(Value::Uuid7(l), Value::Uuid7(r)) => l.cmp(r),
285			(Value::Blob(l), Value::Blob(r)) => l.cmp(r),
286			(Value::Int(l), Value::Int(r)) => l.cmp(r),
287			(Value::Uint(l), Value::Uint(r)) => l.cmp(r),
288			(Value::Decimal(l), Value::Decimal(r)) => l.cmp(r),
289			(Value::Any(_), Value::Any(_)) => unreachable!("Any values are not orderable"),
290			_ => unimplemented!(),
291		}
292	}
293}
294
295impl Display for Value {
296	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
297		match self {
298			Value::Boolean(true) => f.write_str("true"),
299			Value::Boolean(false) => f.write_str("false"),
300			Value::Float4(value) => Display::fmt(value, f),
301			Value::Float8(value) => Display::fmt(value, f),
302			Value::Int1(value) => Display::fmt(value, f),
303			Value::Int2(value) => Display::fmt(value, f),
304			Value::Int4(value) => Display::fmt(value, f),
305			Value::Int8(value) => Display::fmt(value, f),
306			Value::Int16(value) => Display::fmt(value, f),
307			Value::Utf8(value) => Display::fmt(value, f),
308			Value::Uint1(value) => Display::fmt(value, f),
309			Value::Uint2(value) => Display::fmt(value, f),
310			Value::Uint4(value) => Display::fmt(value, f),
311			Value::Uint8(value) => Display::fmt(value, f),
312			Value::Uint16(value) => Display::fmt(value, f),
313			Value::Date(value) => Display::fmt(value, f),
314			Value::DateTime(value) => Display::fmt(value, f),
315			Value::Time(value) => Display::fmt(value, f),
316			Value::Duration(value) => Display::fmt(value, f),
317			Value::RowNumber(value) => Display::fmt(value, f),
318			Value::IdentityId(value) => Display::fmt(value, f),
319			Value::Uuid4(value) => Display::fmt(value, f),
320			Value::Uuid7(value) => Display::fmt(value, f),
321			Value::Blob(value) => Display::fmt(value, f),
322			Value::Int(value) => Display::fmt(value, f),
323			Value::Uint(value) => Display::fmt(value, f),
324			Value::Decimal(value) => Display::fmt(value, f),
325			Value::Any(value) => Display::fmt(value, f),
326			Value::Undefined => f.write_str("undefined"),
327		}
328	}
329}
330
331impl Value {
332	pub fn get_type(&self) -> Type {
333		match self {
334			Value::Undefined => Type::Undefined,
335			Value::Boolean(_) => Type::Boolean,
336			Value::Float4(_) => Type::Float4,
337			Value::Float8(_) => Type::Float8,
338			Value::Int1(_) => Type::Int1,
339			Value::Int2(_) => Type::Int2,
340			Value::Int4(_) => Type::Int4,
341			Value::Int8(_) => Type::Int8,
342			Value::Int16(_) => Type::Int16,
343			Value::Utf8(_) => Type::Utf8,
344			Value::Uint1(_) => Type::Uint1,
345			Value::Uint2(_) => Type::Uint2,
346			Value::Uint4(_) => Type::Uint4,
347			Value::Uint8(_) => Type::Uint8,
348			Value::Uint16(_) => Type::Uint16,
349			Value::Date(_) => Type::Date,
350			Value::DateTime(_) => Type::DateTime,
351			Value::Time(_) => Type::Time,
352			Value::Duration(_) => Type::Duration,
353			Value::RowNumber(_) => Type::RowNumber,
354			Value::IdentityId(_) => Type::IdentityId,
355			Value::Uuid4(_) => Type::Uuid4,
356			Value::Uuid7(_) => Type::Uuid7,
357			Value::Blob(_) => Type::Blob,
358			Value::Int(_) => Type::Int,
359			Value::Uint(_) => Type::Uint,
360			Value::Decimal(_) => Type::Decimal,
361			Value::Any(_) => Type::Any,
362		}
363	}
364}