1#![allow(clippy::derive_ord_xor_partial_ord)]
2
3use std::cmp::Ordering;
4use std::collections::{BTreeMap, HashMap};
5use std::ops::Bound;
6use std::time::Duration as StdDuration;
7
8use anyhow::{Result, bail};
9use chrono::{DateTime, Utc};
10use common::fmt::{EscapeIdent, QuoteStr};
11use geo::Point;
12use revision::revisioned;
13use rust_decimal::prelude::*;
14use storekey::{BorrowDecode, Encode};
15use surrealdb_collections::VecMap;
16pub use surrealdb_strand::Strand;
17use surrealdb_types::{SqlFormat, ToSql, write_sql};
18
19use crate::expr;
20use crate::expr::Error;
21use crate::expr::kind::GeometryKind;
22use crate::expr::statements::info::InfoStructure;
23use crate::val::table_name_public::IntoPublicTable;
24
25pub mod array;
26pub mod bytes;
27pub mod closure;
28pub mod convert_public;
29pub mod datetime;
30pub mod duration;
31pub mod evaluator;
32pub mod field_path;
33pub mod file;
34pub mod geometry;
35pub mod number;
36pub mod object;
37pub mod range;
38pub mod record_id;
39pub mod regex;
40pub mod rnd;
41pub mod set;
42pub mod table_name_public;
43pub mod uuid;
44pub mod value;
45
46pub use surrealdb_strand::TableName;
47
48pub use self::array::Array;
49pub use self::bytes::Bytes;
50pub use self::closure::Closure;
51pub use self::convert_public::convert_public_value_to_internal;
52pub use self::datetime::Datetime;
53pub use self::duration::Duration;
54pub use self::evaluator::{BoxInvokeFut, ClosureEvaluator};
55pub use self::file::File;
56pub use self::geometry::Geometry;
57pub use self::number::Number;
58pub use self::object::Object;
59pub use self::range::Range;
60pub use self::record_id::{RecordId, RecordIdKey, RecordIdKeyRange, RecordIdentity};
61pub use self::regex::Regex;
62pub use self::set::Set;
63pub use self::uuid::Uuid;
64pub use self::value::{CastError, CoerceError};
65
66pub enum IndexFormat {}
69
70#[derive(Clone, Copy, Eq, PartialEq, PartialOrd)]
72pub struct SqlNone;
73
74#[derive(Clone, Copy, Eq, PartialEq, PartialOrd)]
76pub struct Null;
77
78#[revisioned(revision(1), revision(2, optimised))]
101#[derive(Clone, Debug, Default, PartialEq, PartialOrd, Hash, Encode, BorrowDecode)]
102#[storekey(format = "()")]
103#[storekey(format = "IndexFormat")]
104pub enum Value {
105 #[default]
106 #[revision(size = "inline")]
107 None,
108 #[revision(size = "inline")]
109 Null,
110 #[revision(size = "fixed(1)")]
111 Bool(bool),
112 #[revision(size = "varlen")]
113 Number(Number),
114 #[revision(size = "varlen")]
115 String(Strand),
116 #[revision(size = "varlen")]
117 Duration(Duration),
118 #[revision(size = "varlen")]
119 Datetime(Datetime),
120 #[revision(size = "varlen")]
121 Uuid(Uuid),
122 #[revision(size = "varlen")]
123 Array(Array),
124 #[revision(size = "varlen")]
125 Set(Set),
126 #[revision(size = "varlen")]
127 Object(Object),
128 #[revision(size = "varlen")]
129 Geometry(Geometry),
130 #[revision(size = "varlen")]
131 Bytes(Bytes),
132 #[revision(size = "varlen")]
133 Table(TableName),
134 #[revision(size = "varlen")]
135 RecordId(RecordId),
136 #[revision(size = "varlen")]
137 File(File),
138 #[revision(size = "varlen")]
139 Regex(Regex),
140 #[revision(size = "varlen")]
141 Range(Box<Range>),
142 #[revision(size = "varlen")]
146 Closure(Box<Closure>),
147 }
149
150impl Eq for Value {}
151
152impl Ord for Value {
153 fn cmp(&self, other: &Self) -> Ordering {
154 self.partial_cmp(other).unwrap_or(Ordering::Equal)
155 }
156}
157
158impl Value {
159 pub fn hash_agrees_with_eq(&self) -> bool {
180 match self {
181 Value::None
182 | Value::Null
183 | Value::Bool(_)
184 | Value::String(_)
185 | Value::Duration(_)
186 | Value::Datetime(_)
187 | Value::Uuid(_)
188 | Value::Bytes(_)
189 | Value::Table(_)
190 | Value::File(_) => true,
191 Value::Number(_)
192 | Value::Geometry(_)
193 | Value::Regex(_)
194 | Value::Range(_)
195 | Value::Closure(_) => false,
196 Value::Array(a) => a.iter().all(Value::hash_agrees_with_eq),
197 Value::Set(s) => s.iter().all(Value::hash_agrees_with_eq),
198 Value::Object(o) => o.values().all(Value::hash_agrees_with_eq),
201 Value::RecordId(r) => r.key.hash_agrees_with_eq(),
202 }
203 }
204
205 pub const NONE: Self = Self::None;
206
207 pub fn empty_object() -> Self {
213 Value::Object(Object::default())
214 }
215
216 pub fn is_some(&self) -> bool {
222 !matches!(self, Value::None)
223 }
224
225 pub fn is_nullish(&self) -> bool {
227 matches!(self, Value::None | Value::Null)
228 }
229
230 pub fn is_empty_array(&self) -> bool {
232 if let Value::Array(v) = self {
233 v.is_empty()
234 } else {
235 false
236 }
237 }
238
239 pub fn is_truthy(&self) -> bool {
241 match self {
242 Value::Bool(v) => *v,
243 Value::Uuid(_) => true,
244 Value::RecordId(_) => true,
245 Value::Geometry(_) => true,
246 Value::Datetime(_) => true,
247 Value::Bytes(v) => !v.is_empty(),
248 Value::Array(v) => !v.is_empty(),
249 Value::Set(v) => !v.is_empty(),
250 Value::Object(v) => !v.is_empty(),
251 Value::String(v) => !v.is_empty(),
252 Value::Number(v) => v.is_truthy(),
253 Value::Duration(v) => v.as_nanos() > 0,
254 _ => false,
255 }
256 }
257
258 pub fn is_int(&self) -> bool {
260 matches!(self, Value::Number(Number::Int(_)))
261 }
262
263 pub fn is_float(&self) -> bool {
265 matches!(self, Value::Number(Number::Float(_)))
266 }
267
268 pub fn is_decimal(&self) -> bool {
270 matches!(self, Value::Number(Number::Decimal(_)))
271 }
272
273 pub fn is_record_type(&self, types: &[TableName]) -> bool {
275 match self {
276 Value::RecordId(v) => v.is_table_type(types),
277 _ => false,
278 }
279 }
280
281 pub fn is_geometry_type(&self, types: &[GeometryKind]) -> bool {
283 match self {
284 Value::Geometry(Geometry::Point(_)) => {
285 types.iter().any(|t| matches!(t, GeometryKind::Point))
286 }
287 Value::Geometry(Geometry::Line(_)) => {
288 types.iter().any(|t| matches!(t, GeometryKind::Line))
289 }
290 Value::Geometry(Geometry::Polygon(_)) => {
291 types.iter().any(|t| matches!(t, GeometryKind::Polygon))
292 }
293 Value::Geometry(Geometry::MultiPoint(_)) => {
294 types.iter().any(|t| matches!(t, GeometryKind::MultiPoint))
295 }
296 Value::Geometry(Geometry::MultiLine(_)) => {
297 types.iter().any(|t| matches!(t, GeometryKind::MultiLine))
298 }
299 Value::Geometry(Geometry::MultiPolygon(_)) => {
300 types.iter().any(|t| matches!(t, GeometryKind::MultiPolygon))
301 }
302 Value::Geometry(Geometry::Collection(_)) => {
303 types.iter().any(|t| matches!(t, GeometryKind::Collection))
304 }
305 _ => false,
306 }
307 }
308
309 pub fn into_raw_string(self) -> String {
315 match self {
316 Value::String(v) => v.into_string(),
317 Value::Uuid(v) => v.to_string(),
318 Value::Datetime(v) => v.to_string(),
319 _ => self.to_sql(),
320 }
321 }
322
323 pub fn to_raw_string(&self) -> String {
325 match self {
326 Value::String(v) => v.as_str().to_owned(),
327 Value::Uuid(v) => v.to_string(),
328 Value::Datetime(v) => v.to_string(),
329 _ => self.to_sql(),
330 }
331 }
332
333 pub fn kind_of(&self) -> &'static str {
339 match self {
340 Self::None => "none",
341 Self::Null => "null",
342 Self::Bool(_) => "bool",
343 Self::Uuid(_) => "uuid",
344 Self::Array(_) => "array",
345 Self::Set(_) => "set",
346 Self::Object(_) => "object",
347 Self::String(_) => "string",
348 Self::Duration(_) => "duration",
349 Self::Datetime(_) => "datetime",
350 Self::Closure(_) => "function",
351 Self::Number(Number::Int(_)) => "int",
352 Self::Number(Number::Float(_)) => "float",
353 Self::Number(Number::Decimal(_)) => "decimal",
354 Self::Geometry(Geometry::Point(_)) => "geometry<point>",
355 Self::Geometry(Geometry::Line(_)) => "geometry<line>",
356 Self::Geometry(Geometry::Polygon(_)) => "geometry<polygon>",
357 Self::Geometry(Geometry::MultiPoint(_)) => "geometry<multipoint>",
358 Self::Geometry(Geometry::MultiLine(_)) => "geometry<multiline>",
359 Self::Geometry(Geometry::MultiPolygon(_)) => "geometry<multipolygon>",
360 Self::Geometry(Geometry::Collection(_)) => "geometry<collection>",
361 Self::Regex(_) => "regex",
362 Self::File(_) => "file",
363 Self::Bytes(_) => "bytes",
364 Self::Range(_) => "range",
365 Self::RecordId(_) => "record",
366 Self::Table(_) => "table",
367 }
368 }
369
370 pub fn equal(&self, other: &Value) -> bool {
376 match self {
377 Value::None => other.is_none(),
378 Value::Null => other.is_null(),
379 Value::Bool(v) => match other {
380 Value::Bool(w) => v == w,
381 _ => false,
382 },
383 Value::Uuid(v) => match other {
384 Value::Uuid(w) => v == w,
385 _ => false,
386 },
387 Value::RecordId(v) => match other {
388 Value::RecordId(w) => v == w,
389 _ => false,
390 },
391 Value::String(v) => match other {
392 Value::String(w) => v == w,
393 Value::Regex(w) => w.inner().is_match(v.as_str()),
394 _ => false,
395 },
396 Value::Regex(v) => match other {
397 Value::Regex(w) => v == w,
398 Value::String(w) => v.inner().is_match(w.as_str()),
399 _ => false,
400 },
401 Value::Array(v) => match other {
402 Value::Array(w) => v == w,
403 _ => false,
404 },
405 Value::Set(v) => match other {
406 Value::Set(w) => v == w,
407 _ => false,
408 },
409 Value::Object(v) => match other {
410 Value::Object(w) => v == w,
411 _ => false,
412 },
413 Value::Number(v) => match other {
414 Value::Number(w) => v == w,
415 _ => false,
416 },
417 Value::Geometry(v) => match other {
418 Value::Geometry(w) => v == w,
419 _ => false,
420 },
421 Value::Duration(v) => match other {
422 Value::Duration(w) => v == w,
423 _ => false,
424 },
425 Value::Datetime(v) => match other {
426 Value::Datetime(w) => v == w,
427 _ => false,
428 },
429 _ => self == other,
430 }
431 }
432
433 pub fn all_equal(&self, other: &Value) -> bool {
435 match self {
436 Value::Array(v) => v.iter().all(|v| v.equal(other)),
437 Value::Set(v) => v.iter().all(|v| v.equal(other)),
438 _ => self.equal(other),
439 }
440 }
441
442 pub fn any_equal(&self, other: &Value) -> bool {
444 match self {
445 Value::Array(v) => v.iter().any(|v| v.equal(other)),
446 Value::Set(v) => v.iter().any(|v| v.equal(other)),
447 _ => self.equal(other),
448 }
449 }
450
451 pub fn contains(&self, other: &Value) -> bool {
453 match self {
454 Value::Array(v) => v.iter().any(|v| v.equal(other)),
455 Value::Set(v) => v.contains(other),
456 Value::Uuid(v) => match other {
457 Value::String(w) => v.to_string().contains(w.as_str()),
458 _ => false,
459 },
460 Value::String(v) => match other {
461 Value::String(w) => v.contains(w.as_str()),
462 _ => false,
463 },
464 Value::Geometry(v) => match other {
465 Value::Geometry(w) => v.contains(w),
466 _ => false,
467 },
468 Value::Object(v) => match other {
469 Value::String(w) => v.contains_key(w.as_str()),
470 _ => false,
471 },
472 Value::Range(r) => {
473 let beg = match &r.start {
474 Bound::Unbounded => true,
475 Bound::Included(beg) => beg.le(other),
476 Bound::Excluded(beg) => beg.lt(other),
477 };
478
479 beg && match &r.end {
480 Bound::Unbounded => true,
481 Bound::Included(end) => end.ge(other),
482 Bound::Excluded(end) => end.gt(other),
483 }
484 }
485 _ => false,
486 }
487 }
488
489 pub fn contains_all(&self, other: &Value) -> bool {
491 match other {
492 Value::Array(v) if v.iter().all(|v| v.is_strand()) && self.is_strand() => {
493 let Value::String(this) = self else {
495 return false;
496 };
497 v.iter().all(|s| {
498 let Value::String(other_string) = s else {
499 return false;
500 };
501 this.contains(&**other_string)
502 })
503 }
504 Value::Set(v) if v.iter().all(|v| v.is_strand()) && self.is_strand() => {
505 let Value::String(this) = self else {
507 return false;
508 };
509 v.iter().all(|s| {
510 let Value::String(other_string) = s else {
511 return false;
512 };
513 this.contains(&**other_string)
514 })
515 }
516 Value::Array(v) => v.iter().all(|v| match self {
517 Value::Array(w) => w.iter().any(|w| v.equal(w)),
518 Value::Set(w) => w.iter().any(|w| v.equal(w)),
519 Value::Geometry(_) => self.contains(v),
520 _ => false,
521 }),
522 Value::Set(v) => v.iter().all(|v| match self {
523 Value::Array(w) => w.iter().any(|w| v.equal(w)),
524 Value::Set(w) => w.iter().any(|w| v.equal(w)),
525 Value::Geometry(_) => self.contains(v),
526 _ => false,
527 }),
528 Value::String(other_strand) => match self {
529 Value::String(s) => s.contains(&**other_strand),
530 _ => false,
531 },
532 _ => false,
533 }
534 }
535
536 pub fn contains_any(&self, other: &Value) -> bool {
538 match other {
539 Value::Array(v) if v.iter().all(|v| v.is_strand()) && self.is_strand() => {
540 let Value::String(this) = self else {
542 return false;
543 };
544 v.iter().any(|s| {
545 let Value::String(other_string) = s else {
546 return false;
547 };
548 this.contains(&**other_string)
549 })
550 }
551 Value::Set(v) if v.iter().all(|v| v.is_strand()) && self.is_strand() => {
552 let Value::String(this) = self else {
554 return false;
555 };
556 v.iter().any(|s| {
557 let Value::String(other_string) = s else {
558 return false;
559 };
560 this.contains(&**other_string)
561 })
562 }
563 Value::Array(v) => v.iter().any(|v| match self {
564 Value::Array(w) => w.iter().any(|w| v.equal(w)),
565 Value::Set(w) => w.iter().any(|w| v.equal(w)),
566 Value::Geometry(_) => self.contains(v),
567 _ => false,
568 }),
569 Value::Set(v) => v.iter().any(|v| match self {
570 Value::Array(w) => w.iter().any(|w| v.equal(w)),
571 Value::Set(w) => w.iter().any(|w| v.equal(w)),
572 Value::Geometry(_) => self.contains(v),
573 _ => false,
574 }),
575 Value::String(other_strand) => match self {
576 Value::String(s) => s.contains(&**other_strand),
577 _ => false,
578 },
579 _ => false,
580 }
581 }
582
583 pub fn intersects(&self, other: &Value) -> bool {
585 match self {
586 Value::Geometry(v) => match other {
587 Value::Geometry(w) => v.intersects(w),
588 _ => false,
589 },
590 _ => false,
591 }
592 }
593
594 pub fn lexical_cmp(&self, other: &Value) -> Option<Ordering> {
600 match (self, other) {
601 (Value::String(a), Value::String(b)) => Some(lexicmp::lexical_cmp(a, b)),
602 _ => self.partial_cmp(other),
603 }
604 }
605
606 pub fn natural_cmp(&self, other: &Value) -> Option<Ordering> {
608 match (self, other) {
609 (Value::String(a), Value::String(b)) => Some(lexicmp::natural_cmp(a, b)),
610 _ => self.partial_cmp(other),
611 }
612 }
613
614 pub fn natural_lexical_cmp(&self, other: &Value) -> Option<Ordering> {
617 match (self, other) {
618 (Value::String(a), Value::String(b)) => Some(lexicmp::natural_lexical_cmp(a, b)),
619 _ => self.partial_cmp(other),
620 }
621 }
622
623 pub fn into_literal(self) -> expr::Expr {
625 match self {
626 Value::None => expr::Expr::Literal(expr::Literal::None),
627 Value::Null => expr::Expr::Literal(expr::Literal::Null),
628 Value::Bool(x) => expr::Expr::Literal(expr::Literal::Bool(x)),
629 Value::Number(Number::Int(i)) => expr::Expr::Literal(expr::Literal::Integer(i)),
630 Value::Number(Number::Float(f)) => expr::Expr::Literal(expr::Literal::Float(f)),
631 Value::Number(Number::Decimal(d)) => expr::Expr::Literal(expr::Literal::Decimal(d)),
632 Value::String(strand) => expr::Expr::Literal(expr::Literal::String(strand)),
633 Value::Duration(duration) => expr::Expr::Literal(expr::Literal::Duration(duration)),
634 Value::Datetime(datetime) => expr::Expr::Literal(expr::Literal::Datetime(datetime)),
635 Value::Uuid(uuid) => expr::Expr::Literal(expr::Literal::Uuid(uuid)),
636 Value::Array(array) => expr::Expr::Literal(expr::Literal::Array(array.into_literal())),
637 Value::Set(set) => {
638 expr::Expr::Literal(expr::Literal::Array(set.into_literal()))
641 }
642 Value::Object(object) => {
643 expr::Expr::Literal(expr::Literal::Object(object.into_literal()))
644 }
645 Value::Geometry(geometry) => expr::Expr::Literal(expr::Literal::Geometry(geometry)),
646 Value::Bytes(bytes) => expr::Expr::Literal(expr::Literal::Bytes(bytes)),
647 Value::RecordId(record_id) => {
648 expr::Expr::Literal(expr::Literal::RecordId(record_id.into_literal()))
649 }
650 Value::Regex(regex) => expr::Expr::Literal(expr::Literal::Regex(regex)),
651 Value::File(file) => expr::Expr::Literal(expr::Literal::File(file)),
652 Value::Closure(closure) => closure.into_expr(),
653 Value::Range(range) => range.into_literal(),
654 Value::Table(t) => expr::Expr::Table(t),
655 }
656 }
657}
658
659impl ToSql for Value {
660 fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
661 match self {
662 Value::None => f.push_str("NONE"),
663 Value::Null => f.push_str("NULL"),
664 Value::Bool(v) => v.fmt_sql(f, sql_fmt),
665 Value::Number(v) => v.fmt_sql(f, sql_fmt),
666 Value::String(v) => write_sql!(f, sql_fmt, "{}", QuoteStr(v.as_str())),
667 Value::Duration(v) => v.fmt_sql(f, sql_fmt),
668 Value::Datetime(v) => v.fmt_sql(f, sql_fmt),
669 Value::Uuid(v) => v.fmt_sql(f, sql_fmt),
670 Value::Array(v) => v.fmt_sql(f, sql_fmt),
671 Value::Set(v) => v.fmt_sql(f, sql_fmt),
672 Value::Object(v) => v.fmt_sql(f, sql_fmt),
673 Value::Geometry(v) => v.fmt_sql(f, sql_fmt),
674 Value::Bytes(v) => v.fmt_sql(f, sql_fmt),
675 Value::Table(v) => EscapeIdent(v.as_str()).fmt_sql(f, sql_fmt),
680 Value::RecordId(v) => v.fmt_sql(f, sql_fmt),
681 Value::File(v) => v.fmt_sql(f, sql_fmt),
682 Value::Regex(v) => v.fmt_sql(f, sql_fmt),
683 Value::Range(v) => v.fmt_sql(f, sql_fmt),
684 Value::Closure(v) => v.fmt_sql(f, sql_fmt),
685 }
686 }
687}
688
689impl InfoStructure for Value {
690 fn structure(self) -> Value {
691 self.to_sql().into()
692 }
693}
694
695pub trait TryAdd<Rhs = Self> {
698 type Output;
699 fn try_add(self, rhs: Rhs) -> Result<Self::Output>;
700}
701
702use std::ops::Add;
703
704impl TryAdd for Value {
705 type Output = Self;
706 fn try_add(self, other: Self) -> Result<Self> {
707 Ok(match (self, other) {
708 (Self::Number(v), Self::Number(w)) => Self::Number(v.try_add(w)?),
709 (Self::String(v), Self::String(w)) => {
710 let mut s = String::with_capacity(v.len() + w.len());
711 s.push_str(v.as_str());
712 s.push_str(w.as_str());
713 Value::String(s.into())
714 }
715 (Self::Datetime(v), Self::Duration(w)) => Self::Datetime(w.try_add(v)?),
716 (Self::Duration(v), Self::Datetime(w)) => Self::Datetime(v.try_add(w)?),
717 (Self::Duration(v), Self::Duration(w)) => Self::Duration(v.try_add(w)?),
718 (Self::Array(v), Self::Array(w)) => Self::Array(v.concat(w)),
719 (Self::Array(v), Self::Set(w)) => Self::Array(v.concat_set(w)),
720
721 (Self::Set(mut v), Self::Set(w)) => {
722 v.0.extend(w.0);
723 Self::Set(v)
724 }
725 (Self::Set(mut v), Self::Array(w)) => {
726 v.0.extend(w.0);
727 Self::Set(v)
728 }
729 (Self::Object(v), Self::Object(w)) => Self::Object(v.add(w)),
730 (v, w) => bail!(Error::TryAdd(v.kind_of().to_owned(), w.kind_of().to_owned())),
731 })
732 }
733}
734
735pub trait TrySub<Rhs = Self> {
738 type Output;
739 fn try_sub(self, v: Rhs) -> Result<Self::Output>;
740}
741
742impl TrySub for Value {
743 type Output = Self;
744 fn try_sub(self, other: Self) -> Result<Self> {
745 Ok(match (self, other) {
746 (Self::Number(v), Self::Number(w)) => Self::Number(v.try_sub(w)?),
747 (Self::Datetime(v), Self::Datetime(w)) => Self::Duration(v.try_sub(w)?),
748 (Self::Datetime(v), Self::Duration(w)) => Self::Datetime(w.try_sub(v)?),
749 (Self::Duration(v), Self::Datetime(w)) => Self::Datetime(v.try_sub(w)?),
750 (Self::Duration(v), Self::Duration(w)) => Self::Duration(v.try_sub(w)?),
751 (Self::Array(v), Self::Array(x)) => Self::from(v.remove_all(&x.0)),
752 (Self::Array(v), Self::Set(x)) => Self::from(v.remove_all_set(&x)),
753 (Self::Set(mut v), Self::Array(x)) => {
754 for item in x.0 {
755 v.remove(&item);
756 }
757 Self::from(v)
758 }
759 (Self::Set(mut v), Self::Set(x)) => {
760 for item in x {
761 v.remove(&item);
762 }
763 Self::from(v)
764 }
765 (v, w) => bail!(Error::TrySub(v.kind_of().to_owned(), w.kind_of().to_owned())),
766 })
767 }
768}
769
770pub trait TryMul<Rhs = Self> {
773 type Output;
774 fn try_mul(self, v: Self) -> Result<Self::Output>;
775}
776
777impl TryMul for Value {
778 type Output = Self;
779 fn try_mul(self, other: Self) -> Result<Self> {
780 match (self, other) {
781 (Self::Number(v), Self::Number(w)) => Ok(Self::Number(v.try_mul(w)?)),
782 (Self::Duration(d), Self::Number(Number::Int(i))) => {
783 if i < 0 {
784 bail!("Cannot multiply a duration with a negative number");
785 }
786
787 let factor: u32 = i.try_into()?;
788
789 let res =
790 d.0.checked_mul(factor)
791 .ok_or_else(|| Error::ArithmeticOverflow(format!("{d} * {i}")))?;
792
793 Ok(Value::Duration(Duration(res)))
794 }
795 (Self::Duration(d), Self::Number(Number::Float(f))) => {
796 if !(f.is_finite() && f >= 0.0) {
797 bail!("Cannot multiply a duration with a non-finite or negative number");
798 }
799
800 let secs = d.0.as_secs_f64() * f;
801 let res = StdDuration::try_from_secs_f64(secs)
802 .map_err(|_| Error::ArithmeticOverflow(format!("{d} * {f}")))?;
803
804 Ok(Value::Duration(Duration(res)))
805 }
806 (Self::Duration(d), Self::Number(Number::Decimal(dec))) => {
807 if !dec.is_sign_positive() && !dec.is_zero() {
808 bail!("Cannot multiply a duration with a negative number");
809 }
810
811 let nanos: Decimal = d.nanos().into();
812 let scaled = (nanos * dec).trunc();
813
814 let scaled_nanos: u128 = scaled
815 .to_u128()
816 .ok_or_else(|| Error::ArithmeticOverflow(format!("{d} * {dec}")))?;
817
818 let secs: u64 = (scaled_nanos / 1_000_000_000)
819 .try_into()
820 .map_err(|_| Error::ArithmeticOverflow(format!("{d} * {dec}")))?;
821
822 let subsec_nanos: u32 = (scaled_nanos % 1_000_000_000).try_into()?;
823
824 Ok(Value::Duration(Duration(StdDuration::new(secs, subsec_nanos))))
825 }
826 (v, w) => bail!(Error::TryMul(v.kind_of().to_owned(), w.kind_of().to_owned())),
827 }
828 }
829}
830
831pub trait TryDiv<Rhs = Self> {
834 type Output;
835 fn try_div(self, v: Self) -> Result<Self::Output>;
836}
837
838impl TryDiv for Value {
839 type Output = Self;
840 fn try_div(self, other: Self) -> Result<Self> {
841 match (self, other) {
842 (Self::Number(v), Self::Number(w)) => Ok(Self::Number(v.try_div(w)?)),
843 (Self::Duration(d), Self::Number(Number::Int(i))) => {
844 if i <= 0 {
845 bail!("A duration can only be divided by a value greater than 0.");
846 }
847
848 let denom: u32 = i.try_into()?;
849 let res = d.0 / denom;
850 Ok(Value::Duration(Duration(res)))
851 }
852 (Self::Duration(d), Self::Number(Number::Float(f))) => {
853 if !(f.is_finite() && f > 0.0) {
854 bail!("A duration can only be divided by a finite value greater than 0.");
855 }
856 let secs = d.as_secs_f64() / f;
857
858 let res = StdDuration::try_from_secs_f64(secs)?;
859 Ok(Value::Duration(Duration(res)))
860 }
861 (Self::Duration(d), Self::Number(Number::Decimal(dec))) => {
862 if !dec.is_sign_positive() || dec.is_zero() {
863 bail!("A duration can only be divided by a value greater than 0.");
864 }
865
866 let nanos: Decimal = d.nanos().into();
867
868 let divided = (nanos / dec).trunc();
869
870 let divided_nanos: u128 = divided
871 .to_u128()
872 .ok_or_else(|| anyhow::anyhow!("Resulting duration is out of range"))?;
873
874 let secs: u64 = (divided_nanos / 1_000_000_000)
875 .try_into()
876 .map_err(|_| anyhow::anyhow!("Resulting duration seconds out of range"))?;
877
878 let subsec_nanos: u32 = (divided_nanos % 1_000_000_000).try_into()?;
879
880 Ok(Value::Duration(Duration(StdDuration::new(secs, subsec_nanos))))
881 }
882
883 (v, w) => bail!(Error::TryDiv(v.kind_of().to_owned(), w.kind_of().to_owned())),
884 }
885 }
886}
887
888pub trait TryFloatDiv<Rhs = Self> {
891 type Output;
892 fn try_float_div(self, v: Self) -> Result<Self::Output>;
893}
894
895impl TryFloatDiv for Value {
896 type Output = Self;
897 fn try_float_div(self, other: Self) -> Result<Self::Output> {
898 Ok(match (self, other) {
899 (Self::Number(v), Self::Number(w)) => Self::Number(v.try_float_div(w)?),
900 (v, w) => bail!(Error::TryDiv(v.kind_of().to_owned(), w.kind_of().to_owned())),
901 })
902 }
903}
904
905pub trait TryRem<Rhs = Self> {
908 type Output;
909 fn try_rem(self, v: Self) -> Result<Self::Output>;
910}
911
912impl TryRem for Value {
913 type Output = Self;
914 fn try_rem(self, other: Self) -> Result<Self> {
915 Ok(match (self, other) {
916 (Self::Number(v), Self::Number(w)) => Self::Number(v.try_rem(w)?),
917 (v, w) => bail!(Error::TryRem(v.kind_of().to_owned(), w.kind_of().to_owned())),
918 })
919 }
920}
921
922pub trait TryPow<Rhs = Self> {
925 type Output;
926 fn try_pow(self, v: Self) -> Result<Self::Output>;
927}
928
929impl TryPow for Value {
930 type Output = Self;
931 fn try_pow(self, other: Self) -> Result<Self> {
932 Ok(match (self, other) {
933 (Value::Number(v), Value::Number(w)) => Self::Number(v.try_pow(w)?),
934 (v, w) => bail!(Error::TryPow(v.kind_of().to_owned(), w.kind_of().to_owned())),
935 })
936 }
937}
938
939pub trait TryNeg<Rhs = Self> {
942 type Output;
943 fn try_neg(self) -> Result<Self::Output>;
944}
945
946impl TryNeg for Value {
947 type Output = Self;
948 fn try_neg(self) -> Result<Self> {
949 Ok(match self {
950 Self::Number(n) => Self::Number(n.try_neg()?),
951 v => bail!(Error::TryNeg(v.kind_of().to_owned())),
952 })
953 }
954}
955
956macro_rules! subtypes {
960 ($($name:ident$( ( $($t:tt)* ) )? => ($is:ident,$as:ident,$into:ident)),*$(,)?) => {
961 impl Value {
962 $(
963 subtypes!{@method $name $( ($($t)*) )? => $is,$as,$into}
964 )*
965 }
966
967 $(
968 subtypes!{@from $name $( ($($t)*) )? => $is,$as,$into}
969 )*
970
971 };
972
973 (@pat $name:ident($t:ty)) => {
974 Value::$name(_)
975 };
976
977 (@pat $name:ident) => {
978 Value::$name
979 };
980
981 (@method $name:ident($t:ty) => $is:ident,$as:ident,$into:ident) => {
982 #[doc = concat!("Check if the value is a [`",stringify!($name),"`]")]
983 #[allow(dead_code)]
984 pub fn $is(&self) -> bool{
985 matches!(self,Value::$name(_))
986 }
987
988 #[doc = concat!("Return a reference to [`",stringify!($name),"`] if the value is of that type")]
989 #[allow(dead_code)]
990 pub fn $as(&self) -> Option<&$t>{
991 if let Value::$name(x) = self{
992 Some(x)
993 }else{
994 None
995 }
996 }
997
998 #[doc = concat!("Turns the value into a [`",stringify!($name),"`] returning None if the value is not of that type")]
999 #[allow(dead_code)]
1000 pub fn $into(self) -> Option<$t>{
1001 if let Value::$name(x) = self{
1002 Some(x)
1003 }else{
1004 None
1005 }
1006 }
1007 };
1008
1009 (@method $name:ident => $is:ident,$as:ident,$into:ident) => {
1010 #[doc = concat!("Check if the value is a [`",stringify!($name),"`]")]
1011 #[allow(dead_code)]
1012 pub fn $is(&self) -> bool{
1013 matches!(self,Value::$name)
1014 }
1015 };
1016
1017
1018 (@from $name:ident(Box<$inner:ident>) => $is:ident,$as:ident,$into:ident) => {
1019 impl From<$inner> for Value {
1020 fn from(v: $inner) -> Self{
1021 Value::$name(Box::new(v))
1022 }
1023 }
1024
1025 impl From<Box<$inner>> for Value {
1026 fn from(v: Box<$inner>) -> Self{
1027 Value::$name(v)
1028 }
1029 }
1030 };
1031
1032 (@from $name:ident($t:ident) => $is:ident,$as:ident,$into:ident) => {
1033 impl From<$t> for Value {
1034 fn from(v: $t) -> Self{
1035 Value::$name(v)
1036 }
1037 }
1038 };
1039
1040 (@from $name:ident => $is:ident,$as:ident,$into:ident) => {
1041 };
1043
1044}
1045
1046subtypes! {
1047 None => (is_none,_unused,_unused),
1048 Null => (is_null,_unused,_unused),
1049 Bool(bool) => (is_bool,as_bool,into_bool),
1050 Number(Number) => (is_number,as_number,into_number),
1051 String(Strand) => (is_strand,as_strand,into_strand),
1052 Table(TableName) => (is_table,as_table,into_table),
1053 Duration(Duration) => (is_duration,as_duration,into_duration),
1054 Datetime(Datetime) => (is_datetime,as_datetime,into_datetime),
1055 Uuid(Uuid) => (is_uuid,as_uuid,into_uuid),
1056 Array(Array) => (is_array,as_array,into_array),
1057 Set(Set) => (is_set,as_set,into_set),
1058 Object(Object) => (is_object,as_object,into_object),
1059 Geometry(Geometry) => (is_geometry,as_geometry,into_geometry),
1060 Bytes(Bytes) => (is_bytes,as_bytes,into_bytes),
1061 RecordId(RecordId) => (is_record,as_record,into_record),
1062 Regex(Regex) => (is_regex,as_regex,into_regex),
1063 Range(Box<Range>) => (is_range,as_range,into_range),
1064 Closure(Box<Closure>) => (is_closure,as_closure,into_closure),
1065 File(File) => (is_file,as_file,into_file),
1066}
1067
1068macro_rules! impl_from_number {
1069 ($($n:ident),*$(,)?) => {
1070 $(
1071 impl From<$n> for Value{
1072 fn from(v: $n) -> Self{
1073 Value::Number(Number::from(v))
1074 }
1075 }
1076 )*
1077 };
1078}
1079impl_from_number!(i8, i16, i32, i64, u8, u16, u32, isize, f32, f64, Decimal);
1080
1081impl From<Vec<Value>> for Value {
1082 fn from(value: Vec<Value>) -> Self {
1083 Value::Array(Array(value))
1084 }
1085}
1086
1087impl From<Null> for Value {
1088 fn from(_v: Null) -> Self {
1089 Value::Null
1090 }
1091}
1092
1093impl From<u64> for Value {
1096 fn from(v: u64) -> Self {
1097 Value::Number(Number::from(v))
1098 }
1099}
1100
1101impl From<usize> for Value {
1102 fn from(v: usize) -> Self {
1103 Value::Number(Number::from(v))
1104 }
1105}
1106
1107impl TryFrom<i128> for Value {
1110 type Error = Error;
1111 fn try_from(v: i128) -> Result<Self, Self::Error> {
1112 Ok(Value::Number(Number::try_from(v)?))
1113 }
1114}
1115
1116impl TryFrom<u128> for Value {
1117 type Error = Error;
1118 fn try_from(v: u128) -> Result<Self, Self::Error> {
1119 Ok(Value::Number(Number::try_from(v)?))
1120 }
1121}
1122
1123impl From<&str> for Value {
1124 fn from(v: &str) -> Self {
1125 Self::String(Strand::from(v))
1126 }
1127}
1128
1129impl From<String> for Value {
1130 fn from(v: String) -> Self {
1131 Self::String(Strand::from(v))
1132 }
1133}
1134
1135impl From<::uuid::Uuid> for Value {
1136 fn from(v: ::uuid::Uuid) -> Self {
1137 Value::Uuid(Uuid::from(v))
1138 }
1139}
1140
1141impl From<DateTime<Utc>> for Value {
1142 fn from(v: DateTime<Utc>) -> Self {
1143 Value::Datetime(Datetime::from(v))
1144 }
1145}
1146
1147impl From<Point<f64>> for Value {
1148 fn from(v: Point<f64>) -> Self {
1149 Value::Geometry(Geometry::from(v))
1150 }
1151}
1152
1153impl From<HashMap<&str, Value>> for Value {
1154 fn from(v: HashMap<&str, Value>) -> Self {
1155 Value::Object(Object::from(v))
1156 }
1157}
1158
1159impl From<HashMap<String, Value>> for Value {
1160 fn from(v: HashMap<String, Value>) -> Self {
1161 Value::Object(Object::from(v))
1162 }
1163}
1164
1165impl From<BTreeMap<String, Value>> for Value {
1166 fn from(v: BTreeMap<String, Value>) -> Self {
1167 Value::Object(Object::from(v))
1168 }
1169}
1170
1171impl From<VecMap<String, Value>> for Value {
1172 fn from(v: VecMap<String, Value>) -> Self {
1173 Value::Object(Object::from(v))
1174 }
1175}
1176
1177impl From<VecMap<Strand, Value>> for Value {
1178 fn from(v: VecMap<Strand, Value>) -> Self {
1179 Value::Object(Object(v))
1180 }
1181}
1182
1183impl From<VecMap<&str, Value>> for Value {
1184 fn from(v: VecMap<&str, Value>) -> Self {
1185 Value::Object(Object::from(v))
1186 }
1187}
1188
1189impl From<BTreeMap<&str, Value>> for Value {
1190 fn from(v: BTreeMap<&str, Value>) -> Self {
1191 Value::Object(Object::from(v))
1192 }
1193}
1194
1195impl TryFrom<Value> for crate::types::PublicValue {
1196 type Error = anyhow::Error;
1197
1198 fn try_from(s: Value) -> Result<Self, Self::Error> {
1199 convert_value_to_public_value(s)
1200 }
1201}
1202
1203impl From<crate::types::PublicValue> for Value {
1204 fn from(s: crate::types::PublicValue) -> Self {
1205 convert_public_value_to_internal(s)
1206 }
1207}
1208
1209impl FromIterator<Value> for Value {
1210 fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
1211 Value::Array(Array(iter.into_iter().collect()))
1212 }
1213}
1214
1215impl FromIterator<(String, Value)> for Value {
1216 fn from_iter<I: IntoIterator<Item = (String, Value)>>(iter: I) -> Self {
1217 Value::Object(Object::from_iter(iter))
1218 }
1219}
1220
1221pub const MAX_VALUE_DEPTH: usize = 256;
1244
1245enum DepthNode<'a> {
1249 Value(&'a Value),
1250 Key(&'a crate::val::RecordIdKey),
1251}
1252
1253pub fn check_value_depth(value: &Value) -> Result<()> {
1265 use crate::val::RecordIdKey;
1266 let mut stack: Vec<(DepthNode<'_>, usize)> = vec![(DepthNode::Value(value), 1)];
1268 while let Some((node, depth)) = stack.pop() {
1269 if depth > MAX_VALUE_DEPTH {
1270 bail!(Error::ValueTooDeep {
1271 max: MAX_VALUE_DEPTH,
1272 });
1273 }
1274 match node {
1275 DepthNode::Value(value) => match value {
1276 Value::Array(v) => {
1277 stack.extend(v.0.iter().map(|v| (DepthNode::Value(v), depth + 1)))
1278 }
1279 Value::Set(v) => stack.extend(v.0.iter().map(|v| (DepthNode::Value(v), depth + 1))),
1280 Value::Object(v) => {
1281 stack.extend(v.0.values().map(|v| (DepthNode::Value(v), depth + 1)))
1282 }
1283 Value::Range(v) => {
1284 for bound in [&v.start, &v.end] {
1285 match bound {
1286 Bound::Included(v) | Bound::Excluded(v) => {
1287 stack.push((DepthNode::Value(v), depth + 1))
1288 }
1289 Bound::Unbounded => {}
1290 }
1291 }
1292 }
1293 Value::RecordId(v) => stack.push((DepthNode::Key(&v.key), depth + 1)),
1294 _ => {}
1298 },
1299 DepthNode::Key(key) => match key {
1300 RecordIdKey::Array(a) => {
1301 stack.extend(a.0.iter().map(|v| (DepthNode::Value(v), depth + 1)))
1302 }
1303 RecordIdKey::Object(o) => {
1304 stack.extend(o.0.values().map(|v| (DepthNode::Value(v), depth + 1)))
1305 }
1306 RecordIdKey::Range(r) => {
1307 for bound in [&r.start, &r.end] {
1308 match bound {
1309 Bound::Included(k) | Bound::Excluded(k) => {
1310 stack.push((DepthNode::Key(k), depth + 1))
1311 }
1312 Bound::Unbounded => {}
1313 }
1314 }
1315 }
1316 _ => {}
1318 },
1319 }
1320 }
1321 Ok(())
1322}
1323
1324pub fn convert_value_to_public_value(value: crate::val::Value) -> Result<surrealdb_types::Value> {
1325 convert_value_to_public_value_at(value, 1)
1326}
1327
1328fn convert_value_to_public_value_at(
1335 value: crate::val::Value,
1336 depth: usize,
1337) -> Result<surrealdb_types::Value> {
1338 if depth > MAX_VALUE_DEPTH {
1339 bail!(Error::ValueTooDeep {
1340 max: MAX_VALUE_DEPTH,
1341 });
1342 }
1343 match value {
1344 crate::val::Value::None => Ok(surrealdb_types::Value::None),
1345 crate::val::Value::Null => Ok(surrealdb_types::Value::Null),
1346 crate::val::Value::Bool(value) => Ok(surrealdb_types::Value::Bool(value)),
1347 crate::val::Value::Number(value) => convert_number_to_public(value),
1348 crate::val::Value::String(value) => Ok(surrealdb_types::Value::String(value.into())),
1349 crate::val::Value::Datetime(value) => convert_datetime_to_public(value),
1350 crate::val::Value::Duration(value) => convert_duration_to_public(value),
1351 crate::val::Value::Uuid(value) => convert_uuid_to_public(value),
1352 crate::val::Value::Array(value) => convert_array_to_public(value, depth),
1353 crate::val::Value::Set(value) => convert_set_to_public(value, depth),
1354 crate::val::Value::Object(value) => convert_object_to_public(value, depth),
1355 crate::val::Value::Geometry(value) => convert_geometry_to_public(value),
1356 crate::val::Value::Bytes(value) => convert_bytes_to_public(value),
1357 crate::val::Value::RecordId(value) => convert_record_id_to_public(value, depth),
1358 crate::val::Value::File(value) => convert_file_to_public(value),
1359 crate::val::Value::Range(value) => convert_range_to_public(*value),
1360 crate::val::Value::Regex(value) => convert_regex_to_public(value),
1361 crate::val::Value::Table(value) => {
1362 Ok(surrealdb_types::Value::Table(value.into_public_table()))
1363 }
1364 crate::val::Value::Closure(_) => {
1365 Err(anyhow::anyhow!("Closure values cannot be converted to public value"))
1366 }
1367 }
1368}
1369
1370fn convert_number_to_public(value: crate::val::Number) -> Result<surrealdb_types::Value> {
1371 let number = match value {
1372 crate::val::Number::Int(i) => surrealdb_types::Number::Int(i),
1373 crate::val::Number::Float(f) => surrealdb_types::Number::Float(f),
1374 crate::val::Number::Decimal(d) => surrealdb_types::Number::Decimal(d),
1375 };
1376 Ok(surrealdb_types::Value::Number(number))
1377}
1378
1379fn convert_datetime_to_public(value: crate::val::Datetime) -> Result<surrealdb_types::Value> {
1380 Ok(surrealdb_types::Value::Datetime(surrealdb_types::Datetime::from(value.0)))
1381}
1382
1383fn convert_duration_to_public(value: crate::val::Duration) -> Result<surrealdb_types::Value> {
1384 Ok(surrealdb_types::Value::Duration(surrealdb_types::Duration::from_std(value.0)))
1385}
1386
1387fn convert_uuid_to_public(value: crate::val::Uuid) -> Result<surrealdb_types::Value> {
1388 Ok(surrealdb_types::Value::Uuid(surrealdb_types::Uuid::from(value.0)))
1389}
1390
1391fn convert_bytes_to_public(value: crate::val::Bytes) -> Result<surrealdb_types::Value> {
1392 Ok(surrealdb_types::Value::Bytes(surrealdb_types::Bytes::from(value.0)))
1393}
1394
1395fn convert_regex_to_public(value: crate::val::Regex) -> Result<surrealdb_types::Value> {
1396 Ok(surrealdb_types::Value::Regex(surrealdb_types::Regex::from(value.0)))
1397}
1398
1399fn convert_file_to_public(value: crate::val::File) -> Result<surrealdb_types::Value> {
1400 Ok(surrealdb_types::Value::File(surrealdb_types::File::new(value.bucket, value.key)))
1401}
1402
1403fn convert_geometry_to_public(value: crate::val::Geometry) -> Result<surrealdb_types::Value> {
1404 use surrealdb_types::Geometry as PublicGeometry;
1405 let geometry = match value {
1406 crate::val::Geometry::Point(p) => PublicGeometry::Point(p),
1407 crate::val::Geometry::Line(l) => PublicGeometry::Line(l),
1408 crate::val::Geometry::Polygon(p) => PublicGeometry::Polygon(p),
1409 crate::val::Geometry::MultiPoint(mp) => PublicGeometry::MultiPoint(mp),
1410 crate::val::Geometry::MultiLine(ml) => PublicGeometry::MultiLine(ml),
1411 crate::val::Geometry::MultiPolygon(mp) => PublicGeometry::MultiPolygon(mp),
1412 crate::val::Geometry::Collection(c) => {
1413 let converted: Result<Vec<_>> = c
1414 .into_iter()
1415 .map(|g| {
1416 if let surrealdb_types::Value::Geometry(g) = convert_geometry_to_public(g)? {
1417 Ok(g)
1418 } else {
1419 Err(anyhow::anyhow!("Failed to convert geometry collection item"))
1420 }
1421 })
1422 .collect();
1423 PublicGeometry::Collection(converted?)
1424 }
1425 };
1426 Ok(surrealdb_types::Value::Geometry(geometry))
1427}
1428
1429fn convert_array_to_public(
1430 value: crate::val::Array,
1431 depth: usize,
1432) -> Result<surrealdb_types::Value> {
1433 let converted: Result<Vec<_>> =
1434 value.0.into_iter().map(|v| convert_value_to_public_value_at(v, depth + 1)).collect();
1435 Ok(surrealdb_types::Value::Array(surrealdb_types::Array::from(converted?)))
1436}
1437
1438fn convert_set_to_public(value: crate::val::Set, depth: usize) -> Result<surrealdb_types::Value> {
1439 let converted: Result<Vec<surrealdb_types::Value>> =
1441 value.0.into_iter().map(|v| convert_value_to_public_value_at(v, depth + 1)).collect();
1442 Ok(surrealdb_types::Value::Set(surrealdb_types::Set::from(converted?)))
1443}
1444
1445fn convert_object_to_public(
1446 value: crate::val::Object,
1447 depth: usize,
1448) -> Result<surrealdb_types::Value> {
1449 let converted = convert_object_to_public_map_at(value, depth)?;
1450 Ok(surrealdb_types::Value::Object(surrealdb_types::Object::from(converted)))
1451}
1452
1453pub fn convert_object_to_public_map(
1454 value: crate::val::Object,
1455) -> Result<BTreeMap<String, surrealdb_types::Value>> {
1456 convert_object_to_public_map_at(value, 1)
1457}
1458
1459fn convert_object_to_public_map_at(
1460 value: crate::val::Object,
1461 depth: usize,
1462) -> Result<BTreeMap<String, surrealdb_types::Value>> {
1463 value
1464 .0
1465 .into_iter()
1466 .map(|(k, v)| convert_value_to_public_value_at(v, depth + 1).map(|v| (k.into_string(), v)))
1467 .collect()
1468}
1469
1470fn convert_record_id_to_public(
1471 value: crate::val::RecordId,
1472 depth: usize,
1473) -> Result<surrealdb_types::Value> {
1474 let key = convert_record_id_key_to_public(value.key, depth)?;
1475 Ok(surrealdb_types::Value::RecordId(surrealdb_types::RecordId {
1476 table: value.table.into_public_table(),
1477 key,
1478 }))
1479}
1480
1481fn convert_record_id_key_to_public(
1482 key: crate::val::RecordIdKey,
1483 depth: usize,
1484) -> Result<surrealdb_types::RecordIdKey> {
1485 if depth > MAX_VALUE_DEPTH {
1486 bail!(Error::ValueTooDeep {
1487 max: MAX_VALUE_DEPTH,
1488 });
1489 }
1490 match key {
1491 crate::val::RecordIdKey::Number(n) => Ok(surrealdb_types::RecordIdKey::Number(n)),
1492 crate::val::RecordIdKey::String(s) => Ok(surrealdb_types::RecordIdKey::String(s.into())),
1493 crate::val::RecordIdKey::Uuid(u) => {
1494 Ok(surrealdb_types::RecordIdKey::Uuid(surrealdb_types::Uuid::from(u.0)))
1495 }
1496 crate::val::RecordIdKey::Array(a) => {
1497 let converted_array = convert_array_to_public(a, depth)?;
1498 if let surrealdb_types::Value::Array(arr) = converted_array {
1499 Ok(surrealdb_types::RecordIdKey::Array(arr))
1500 } else {
1501 Err(anyhow::anyhow!("Failed to convert record id key array"))
1502 }
1503 }
1504 crate::val::RecordIdKey::Object(o) => {
1505 let converted_object = convert_object_to_public(o, depth)?;
1506 if let surrealdb_types::Value::Object(obj) = converted_object {
1507 Ok(surrealdb_types::RecordIdKey::Object(obj))
1508 } else {
1509 Err(anyhow::anyhow!("Failed to convert record id key object"))
1510 }
1511 }
1512 crate::val::RecordIdKey::Range(r) => {
1513 Ok(surrealdb_types::RecordIdKey::Range(Box::new(surrealdb_types::RecordIdKeyRange {
1514 start: match r.start {
1515 Bound::Included(k) => {
1516 Bound::Included(convert_record_id_key_to_public(k, depth + 1)?)
1517 }
1518 Bound::Excluded(k) => {
1519 Bound::Excluded(convert_record_id_key_to_public(k, depth + 1)?)
1520 }
1521 Bound::Unbounded => Bound::Unbounded,
1522 },
1523 end: match r.end {
1524 Bound::Included(k) => {
1525 Bound::Included(convert_record_id_key_to_public(k, depth + 1)?)
1526 }
1527 Bound::Excluded(k) => {
1528 Bound::Excluded(convert_record_id_key_to_public(k, depth + 1)?)
1529 }
1530 Bound::Unbounded => Bound::Unbounded,
1531 },
1532 })))
1533 }
1534 }
1535}
1536
1537fn convert_range_to_public(value: crate::val::Range) -> Result<surrealdb_types::Value> {
1538 Ok(surrealdb_types::Value::Range(Box::new(surrealdb_types::Range {
1539 start: match value.start {
1540 Bound::Included(v) => Bound::Included(convert_value_to_public_value(v)?),
1541 Bound::Excluded(v) => Bound::Excluded(convert_value_to_public_value(v)?),
1542 Bound::Unbounded => Bound::Unbounded,
1543 },
1544 end: match value.end {
1545 Bound::Included(v) => Bound::Included(convert_value_to_public_value(v)?),
1546 Bound::Excluded(v) => Bound::Excluded(convert_value_to_public_value(v)?),
1547 Bound::Unbounded => Bound::Unbounded,
1548 },
1549 })))
1550}
1551
1552#[cfg(test)]
1553mod tests {
1554 use super::{MAX_VALUE_DEPTH, check_value_depth, convert_value_to_public_value};
1555 use crate::val::{Array, Object, Value};
1556
1557 fn nested_array(depth: usize) -> Value {
1560 let mut value = Value::from(1i64);
1561 for _ in 1..depth {
1562 value = Value::Array(Array::from(vec![value]));
1563 }
1564 value
1565 }
1566
1567 fn nested_object(depth: usize) -> Value {
1568 let mut value = Value::from(1i64);
1569 for _ in 1..depth {
1570 let mut obj = Object::default();
1571 obj.insert("v".to_owned(), value);
1572 value = Value::Object(obj);
1573 }
1574 value
1575 }
1576
1577 #[test]
1584 fn value_depth_within_the_cap_is_accepted() {
1585 check_value_depth(&nested_array(MAX_VALUE_DEPTH))
1586 .expect("a value exactly at the cap must be accepted");
1587 check_value_depth(&nested_object(MAX_VALUE_DEPTH))
1588 .expect("objects nest the same way as arrays");
1589 check_value_depth(&Value::from(1i64)).expect("a scalar is depth 1");
1590 }
1591
1592 #[test]
1593 fn value_depth_past_the_cap_is_rejected() {
1594 let err = check_value_depth(&nested_array(MAX_VALUE_DEPTH + 1))
1595 .expect_err("a value one level past the cap must be rejected");
1596 assert!(err.to_string().contains("nested too deeply"), "unexpected error: {err}");
1597 assert!(check_value_depth(&nested_object(MAX_VALUE_DEPTH + 1)).is_err());
1598 }
1599
1600 #[test]
1612 fn value_depth_check_does_not_recurse() {
1613 let deep = std::mem::ManuallyDrop::new(nested_array(200_000));
1614 assert!(
1615 check_value_depth(&deep).is_err(),
1616 "a very deeply nested value must be rejected, not overflow the stack"
1617 );
1618 }
1619
1620 #[test]
1624 fn public_value_conversion_rejects_values_past_the_cap() {
1625 convert_value_to_public_value(nested_array(MAX_VALUE_DEPTH))
1626 .expect("a value at the cap must still convert");
1627 let err = convert_value_to_public_value(nested_array(MAX_VALUE_DEPTH + 1))
1628 .expect_err("a value past the cap must not convert");
1629 assert!(err.to_string().contains("nested too deeply"), "unexpected error: {err}");
1630 }
1631
1632 #[test]
1637 fn record_id_key_depth_is_walked() {
1638 use crate::val::{RecordId, RecordIdKey};
1639
1640 fn record_id_with_nested_key(inner: usize) -> Value {
1642 Value::RecordId(RecordId {
1643 table: "t".into(),
1644 key: RecordIdKey::Array(Array::from(vec![nested_array(inner)])),
1645 })
1646 }
1647
1648 check_value_depth(&record_id_with_nested_key(8))
1649 .expect("a shallow compound key must be accepted");
1650 let err = check_value_depth(&record_id_with_nested_key(MAX_VALUE_DEPTH + 8))
1651 .expect_err("a record id whose key nests past the cap must be rejected");
1652 assert!(err.to_string().contains("nested too deeply"), "unexpected error: {err}");
1653 }
1654
1655 #[test]
1662 fn hash_agrees_with_eq_flags_numbers_at_any_depth() {
1663 use std::collections::BTreeMap;
1664
1665 use crate::val::{Number, Object, RecordId, RecordIdKey, Value};
1666
1667 let num = Value::Number(Number::Float(0.1));
1668 let nested =
1669 |v: Value| Value::Object(Object::from(BTreeMap::from([(Strand::from("v"), v)])));
1670
1671 for v in [
1672 Value::None,
1673 Value::Null,
1674 Value::Bool(true),
1675 Value::String("x".into()),
1676 Value::from(vec![Value::String("x".into())]),
1677 nested(Value::String("x".into())),
1678 Value::RecordId(RecordId {
1679 table: "t".into(),
1680 key: RecordIdKey::Number(1),
1681 }),
1682 ] {
1683 assert!(v.hash_agrees_with_eq(), "{v:?}");
1684 }
1685
1686 for v in [
1687 num.clone(),
1688 Value::from(vec![num.clone()]),
1689 nested(num.clone()),
1690 nested(Value::from(vec![num.clone()])),
1691 Value::RecordId(RecordId {
1692 table: "t".into(),
1693 key: RecordIdKey::Array(vec![num].into()),
1694 }),
1695 ] {
1696 assert!(!v.hash_agrees_with_eq(), "{v:?}");
1697 }
1698 }
1699
1700 #[test]
1701 fn table_value_renders_escaped() {
1702 use surrealdb_types::ToSql;
1703
1704 use crate::val::{TableName, Value};
1705
1706 assert_eq!(Value::Table(TableName::from("users")).to_sql(), "users");
1707 assert_eq!(Value::Table(TableName::from("table")).to_sql(), "`table`");
1708 assert_eq!(Value::Table(TableName::from("a b")).to_sql(), "`a b`");
1709 }
1710 use chrono::{TimeZone, Utc};
1711 use geo::{MultiLineString, MultiPoint, MultiPolygon, line_string, point, polygon};
1712 use rstest::rstest;
1713 use rust_decimal::Decimal;
1714 use serde_json::{Value as Json, json};
1715
1716 use super::*;
1717 use crate::syn;
1718 use crate::types::{
1719 PublicArray, PublicBytes, PublicDatetime, PublicDuration, PublicGeometry, PublicNumber,
1720 PublicObject, PublicRecordId, PublicRecordIdKey, PublicUuid, PublicValue,
1721 };
1722 use crate::val::Uuid;
1723
1724 macro_rules! parse_val {
1725 ($input:expr) => {
1726 crate::val::convert_public_value_to_internal(syn::value($input).unwrap())
1727 };
1728 }
1729
1730 #[test]
1731 fn check_none() {
1732 assert!(Value::None.is_none());
1733 assert!(!Value::Null.is_none());
1734 assert!(!Value::from(1).is_none());
1735 }
1736
1737 #[test]
1738 fn check_null() {
1739 assert!(Value::Null.is_null());
1740 assert!(!Value::None.is_null());
1741 assert!(!Value::from(1).is_null());
1742 }
1743
1744 #[test]
1745 fn convert_truthy() {
1746 assert!(!Value::None.is_truthy());
1747 assert!(!Value::Null.is_truthy());
1748 assert!(Value::Bool(true).is_truthy());
1749 assert!(!Value::Bool(false).is_truthy());
1750 assert!(!Value::from(0).is_truthy());
1751 assert!(Value::from(1).is_truthy());
1752 assert!(Value::from(-1).is_truthy());
1753 assert!(Value::from(1.1).is_truthy());
1754 assert!(Value::from(-1.1).is_truthy());
1755 assert!(Value::from("true").is_truthy());
1756 assert!(Value::from("false").is_truthy());
1757 assert!(Value::from("falsey").is_truthy());
1758 assert!(Value::from("something").is_truthy());
1759 assert!(Value::from(Uuid::nil()).is_truthy());
1760 assert!(Value::from(Utc.with_ymd_and_hms(1948, 12, 3, 0, 0, 0).unwrap()).is_truthy());
1761 }
1762
1763 #[test]
1764 fn convert_string() {
1765 assert_eq!(String::from("NONE"), Value::None.into_raw_string());
1766 assert_eq!(String::from("NULL"), Value::Null.into_raw_string());
1767 assert_eq!(String::from("true"), Value::Bool(true).into_raw_string());
1768 assert_eq!(String::from("false"), Value::Bool(false).into_raw_string());
1769 assert_eq!(String::from("0"), Value::from(0).into_raw_string());
1770 assert_eq!(String::from("1"), Value::from(1).into_raw_string());
1771 assert_eq!(String::from("-1"), Value::from(-1).into_raw_string());
1772 assert_eq!(String::from("1.1f"), Value::from(1.1).into_raw_string());
1773 assert_eq!(String::from("-1.1f"), Value::from(-1.1).into_raw_string());
1774 assert_eq!(String::from("3"), Value::from("3").into_raw_string());
1775 assert_eq!(String::from("true"), Value::from("true").into_raw_string());
1776 assert_eq!(String::from("false"), Value::from("false").into_raw_string());
1777 assert_eq!(String::from("something"), Value::from("something").into_raw_string());
1778 }
1779
1780 #[test]
1781 fn check_size() {
1782 assert!(64 >= std::mem::size_of::<Value>(), "size of value too big");
1783 }
1784
1785 #[rstest]
1786 #[case::none(Value::None, 2)]
1791 #[case::null(Value::Null, 2)]
1792 #[case::bool(Value::Bool(true), 3)]
1793 #[case::bool(Value::Bool(false), 3)]
1794 #[case::string(Value::from("test"), 11)]
1798 #[case::object(Value::from(syn::value("{ hello: 'world' }").unwrap()), 31)]
1807 #[case::object(Value::from(syn::value("{ compact: true, schema: 0 }").unwrap()), 40)]
1808 fn check_serialize(#[case] value: Value, #[case] expected: usize) {
1809 let enc: Vec<u8> = revision::to_vec(&value).unwrap();
1810 assert_eq!(expected, enc.len());
1811 }
1812
1813 #[test]
1814 fn serialize_deserialize() {
1815 let val = parse_val!(
1816 "{ test: { something: [1, 'two', null, test:tobie, { trueee: false, noneee: null }] } }"
1817 );
1818 let res = parse_val!(
1819 "{ test: { something: [1, 'two', null, test:tobie, { trueee: false, noneee: null }] } }"
1820 );
1821 let enc: Vec<u8> = revision::to_vec(&val).unwrap();
1822 let dec: Value = revision::from_slice(&enc).unwrap();
1823 assert_eq!(res, dec);
1824 }
1825
1826 #[rstest]
1827 #[case::none(PublicValue::None, json!(null), PublicValue::Null)]
1828 #[case::null(PublicValue::Null, json!(null), PublicValue::Null)]
1829 #[case::bool(PublicValue::Bool(true), json!(true), PublicValue::Bool(true))]
1830 #[case::bool(PublicValue::Bool(false), json!(false), PublicValue::Bool(false))]
1831 #[case::number(
1832 PublicValue::Number(PublicNumber::Int(i64::MIN)),
1833 json!(i64::MIN),
1834 PublicValue::Number(PublicNumber::Int(i64::MIN)),
1835 )]
1836 #[case::number(
1837 PublicValue::Number(PublicNumber::Int(i64::MAX)),
1838 json!(i64::MAX),
1839 PublicValue::Number(PublicNumber::Int(i64::MAX)),
1840 )]
1841 #[case::number(
1842 PublicValue::Number(PublicNumber::Float(1.23)),
1843 json!(1.23),
1844 PublicValue::Number(PublicNumber::Float(1.23)),
1845 )]
1846 #[case::number(
1847 PublicValue::Number(PublicNumber::Float(f64::NEG_INFINITY)),
1848 json!(null),
1849 PublicValue::Null,
1850 )]
1851 #[case::number(
1852 PublicValue::Number(PublicNumber::Float(f64::MIN)),
1853 json!(-1.7976931348623157e308),
1854 PublicValue::Number(PublicNumber::Float(f64::MIN)),
1855 )]
1856 #[case::number(
1857 PublicValue::Number(PublicNumber::Float(0.0)),
1858 json!(0.0),
1859 PublicValue::Number(PublicNumber::Float(0.0)),
1860 )]
1861 #[case::number(
1862 PublicValue::Number(PublicNumber::Float(f64::MAX)),
1863 json!(1.7976931348623157e308),
1864 PublicValue::Number(PublicNumber::Float(f64::MAX)),
1865 )]
1866 #[case::number(
1867 PublicValue::Number(PublicNumber::Float(f64::INFINITY)),
1868 json!(null),
1869 PublicValue::Null,
1870 )]
1871 #[case::number(
1872 PublicValue::Number(PublicNumber::Float(f64::NAN)),
1873 json!(null),
1874 PublicValue::Null,
1875 )]
1876 #[case::number(
1877 PublicValue::Number(PublicNumber::Decimal(Decimal::new(123, 2))),
1878 json!("1.23"),
1879 PublicValue::String("1.23".to_string()),
1880 )]
1881 #[case::strand(
1882 PublicValue::String("".to_string()),
1883 json!(""),
1884 PublicValue::String("".to_string()),
1885 )]
1886 #[case::strand(
1887 PublicValue::String("foo".to_string()),
1888 json!("foo"),
1889 PublicValue::String("foo".to_string()),
1890 )]
1891 #[case::duration(
1892 PublicValue::Duration(PublicDuration::ZERO),
1893 json!("0ns"),
1894 PublicValue::String("0ns".to_string()),
1895 )]
1896 #[case::duration(
1897 PublicValue::Duration(PublicDuration::MAX),
1898 json!("584942417355y3w5d7h15s999ms999µs999ns"),
1899 PublicValue::String("584942417355y3w5d7h15s999ms999µs999ns".to_string()),
1900 )]
1901 #[case::datetime(
1902 PublicValue::Datetime(PublicDatetime::MIN_UTC),
1903 json!("-262143-01-01T00:00:00Z"),
1904 PublicValue::Datetime(PublicDatetime::MIN_UTC),
1905 )]
1906 #[case::datetime(
1907 PublicValue::Datetime(PublicDatetime::MAX_UTC),
1908 json!("+262142-12-31T23:59:59.999999999Z"),
1909 PublicValue::Datetime(PublicDatetime::MAX_UTC),
1910 )]
1911 #[case::uuid(
1912 PublicValue::Uuid(PublicUuid::nil()),
1913 json!("00000000-0000-0000-0000-000000000000"),
1914 PublicValue::Uuid(PublicUuid::nil()),
1915 )]
1916 #[case::uuid(
1917 PublicValue::Uuid(PublicUuid::max()),
1918 json!("ffffffff-ffff-ffff-ffff-ffffffffffff"),
1919 PublicValue::Uuid(PublicUuid::max()),
1920 )]
1921 #[case::bytes(
1922 PublicValue::Bytes(PublicBytes::default()),
1923 json!([]),
1924 PublicValue::Array(PublicArray::new()),
1925 )]
1926 #[case::bytes(
1927 PublicValue::Bytes(PublicBytes::from(b"foo".to_vec())),
1928 json!([102, 111, 111]),
1929 PublicValue::Array(PublicArray::from(vec![
1930 PublicValue::Number(PublicNumber::Int(102)),
1931 PublicValue::Number(PublicNumber::Int(111)),
1932 PublicValue::Number(PublicNumber::Int(111)),
1933 ])),
1934 )]
1935 #[case::record_id(
1936 PublicValue::RecordId(PublicRecordId::new("foo", PublicRecordIdKey::String("bar".to_string()))) ,
1937 json!("foo:bar"),
1938 PublicValue::RecordId(PublicRecordId::new("foo", PublicRecordIdKey::String("bar".to_string()))) ,
1939 )]
1940 #[case::array(
1941 PublicValue::Array(PublicArray::new()),
1942 json!([]),
1943 PublicValue::Array(PublicArray::new()),
1944 )]
1945 #[case::array(
1946 PublicValue::Array(PublicArray::from(vec![PublicValue::Bool(true), PublicValue::Bool(false)])),
1947 json!([true, false]),
1948 PublicValue::Array(PublicArray::from(vec![PublicValue::Bool(true), PublicValue::Bool(false)])),
1949 )]
1950 #[case::object(
1951 PublicValue::Object(PublicObject::new()),
1952 json!({}),
1953 PublicValue::Object(PublicObject::new()),
1954 )]
1955 #[case::object(
1956 PublicValue::Object(PublicObject::from_iter([("done".to_owned(), PublicValue::Bool(true))])),
1957 json!({"done": true}),
1958 PublicValue::Object(PublicObject::from_iter([("done".to_owned(), PublicValue::Bool(true))])),
1959 )]
1960 #[case::geometry_point(
1961 PublicValue::Geometry(PublicGeometry::Point(point! { x: 10., y: 20. })),
1962 json!({ "type": "Point", "coordinates": [10., 20.]}),
1963 PublicValue::Geometry(PublicGeometry::Point(point! { x: 10., y: 20. })),
1964 )]
1965 #[case::geometry_line(
1966 PublicValue::Geometry(PublicGeometry::Line(line_string![
1967 ( x: 0., y: 0. ),
1968 ( x: 10., y: 0. ),
1969 ])),
1970 json!({ "type": "LineString", "coordinates": [[0., 0.], [10., 0.]]}),
1971 PublicValue::Geometry(PublicGeometry::Line(line_string![
1972 ( x: 0., y: 0. ),
1973 ( x: 10., y: 0. ),
1974 ])),
1975 )]
1976 #[case::geometry_polygon(
1977 PublicValue::Geometry(PublicGeometry::Polygon(polygon![
1978 (x: -111., y: 45.),
1979 (x: -111., y: 41.),
1980 (x: -104., y: 41.),
1981 (x: -104., y: 45.),
1982 ])),
1983 json!({ "type": "Polygon", "coordinates": [[
1984 [-111., 45.],
1985 [-111., 41.],
1986 [-104., 41.],
1987 [-104., 45.],
1988 [-111., 45.],
1989 ]]}),
1990 PublicValue::Geometry(PublicGeometry::Polygon(polygon![
1991 (x: -111., y: 45.),
1992 (x: -111., y: 41.),
1993 (x: -104., y: 41.),
1994 (x: -104., y: 45.),
1995 ])),
1996 )]
1997 #[case::geometry_multi_point(
1998 PublicValue::Geometry(PublicGeometry::MultiPoint(MultiPoint::new(vec![
1999 point! { x: 0., y: 0. },
2000 point! { x: 1., y: 2. },
2001 ]))),
2002 json!({ "type": "MultiPoint", "coordinates": [[0., 0.], [1., 2.]]}),
2003 PublicValue::Geometry(PublicGeometry::MultiPoint(MultiPoint::new(vec![
2004 point! { x: 0., y: 0. },
2005 point! { x: 1., y: 2. },
2006 ]))),
2007 )]
2008 #[case::geometry_multi_line(
2009 PublicValue::Geometry(
2010 PublicGeometry::MultiLine(
2011 MultiLineString::new(vec![
2012 line_string![( x: 0., y: 0. ), ( x: 1., y: 2. )],
2013 ])
2014 )
2015 ),
2016 json!({ "type": "MultiLineString", "coordinates": [[[0., 0.], [1., 2.]]]}),
2017 PublicValue::Geometry(
2018 PublicGeometry::MultiLine(
2019 MultiLineString::new(vec![
2020 line_string![( x: 0., y: 0. ), ( x: 1., y: 2. )],
2021 ])
2022 )
2023 ),
2024 )]
2025 #[case::geometry_multi_polygon(
2026 PublicValue::Geometry(PublicGeometry::MultiPolygon(MultiPolygon::new(vec![
2027 polygon![
2028 (x: -111., y: 45.),
2029 (x: -111., y: 41.),
2030 (x: -104., y: 41.),
2031 (x: -104., y: 45.),
2032 ],
2033 ]))),
2034 json!({ "type": "MultiPolygon", "coordinates": [[[
2035 [-111., 45.],
2036 [-111., 41.],
2037 [-104., 41.],
2038 [-104., 45.],
2039 [-111., 45.],
2040 ]]]})
2041 , PublicValue::Geometry(PublicGeometry::MultiPolygon(MultiPolygon::new(vec![
2042 polygon![
2043 (x: -111., y: 45.),
2044 (x: -111., y: 41.),
2045 (x: -104., y: 41.),
2046 (x: -104., y: 45.),
2047 ],
2048 ]))),
2049 )]
2050 #[case::geometry_collection(
2051 PublicValue::Geometry(PublicGeometry::Collection(vec![])),
2052 json!({
2053 "type": "GeometryCollection",
2054 "geometries": [],
2055 }),
2056 PublicValue::Geometry(PublicGeometry::Collection(vec![])),
2057 )]
2058 #[case::geometry_collection_with_point(
2059 PublicValue::Geometry(PublicGeometry::Collection(vec![PublicGeometry::Point(point! { x: 10., y: 20. })])),
2060 json!({
2061 "type": "GeometryCollection",
2062 "geometries": [ { "type": "Point", "coordinates": [10., 20.] } ],
2063 }),
2064 PublicValue::Geometry(PublicGeometry::Collection(vec![PublicGeometry::Point(point! { x: 10., y: 20. })])),
2065 )]
2066 #[case::geometry_collection_with_line(
2067 PublicValue::Geometry(PublicGeometry::Collection(vec![PublicGeometry::Line(line_string![
2068 ( x: 0., y: 0. ),
2069 ( x: 10., y: 0. ),
2070 ])])),
2071 json!({
2072 "type": "GeometryCollection",
2073 "geometries": [ { "type": "LineString", "coordinates": [[0., 0.], [10., 0.]] } ],
2074 }),
2075 PublicValue::Geometry(PublicGeometry::Collection(vec![PublicGeometry::Line(line_string![
2076 ( x: 0., y: 0. ),
2077 ( x: 10., y: 0. ),
2078 ])])),
2079 )]
2080
2081 fn test_json(
2082 #[case] value: PublicValue,
2083 #[case] expected: Json,
2084 #[case] expected_deserialized: PublicValue,
2085 ) {
2086 use surrealdb_syn::ParserConfig;
2087
2088 let json_value = value.into_json_value();
2089 assert_eq!(json_value, expected);
2090
2091 let json_str = serde_json::to_string(&json_value).expect("Failed to serialize to JSON");
2092 let deserialized_sql_value =
2093 crate::syn::value_legacy_strand(&json_str, &ParserConfig::default()).unwrap();
2094 assert_eq!(deserialized_sql_value, expected_deserialized);
2095 }
2096}