Skip to main content

nodedb_types/value/
convert.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! `From` conversions for [`Value`].
4
5use std::sync::Arc;
6
7use crate::datetime::{NdbDateTime, NdbDuration};
8use crate::geometry::Geometry;
9use crate::value::core::Value;
10
11impl From<&str> for Value {
12    fn from(s: &str) -> Self {
13        Value::String(s.to_owned())
14    }
15}
16
17impl From<String> for Value {
18    fn from(s: String) -> Self {
19        Value::String(s)
20    }
21}
22
23impl From<i64> for Value {
24    fn from(i: i64) -> Self {
25        Value::Integer(i)
26    }
27}
28
29impl Value {
30    /// An unsigned integer as a `Value` that keeps its exact number.
31    ///
32    /// A value up to `i64::MAX` is an `Integer`. A larger value is a
33    /// `Decimal`, because an `Integer` cannot hold it without wrapping.
34    pub fn from_u64(u: u64) -> Self {
35        match i64::try_from(u) {
36            Ok(i) => Value::Integer(i),
37            Err(_) => Value::Decimal(rust_decimal::Decimal::from(u)),
38        }
39    }
40
41    /// The `u64` that `d` stands for when `d` is a `Decimal`
42    /// [`Value::from_u64`] produces: scale `0`, above `i64::MAX`, at most
43    /// `u64::MAX`. `None` for any other decimal.
44    ///
45    /// Msgpack writers encode such a decimal as a `uint64`, the number type
46    /// that holds it, and readers decode a `uint64` through `from_u64`, so
47    /// the value round-trips to the same `Decimal`. Every other decimal stays
48    /// text: an `Integer`-range or scaled decimal would not read back as a
49    /// `Decimal` of the same scale.
50    pub fn decimal_as_wide_u64(d: &rust_decimal::Decimal) -> Option<u64> {
51        use rust_decimal::prelude::ToPrimitive;
52        if d.scale() != 0 {
53            return None;
54        }
55        d.to_u64().filter(|u| i64::try_from(*u).is_err())
56    }
57}
58
59impl From<f64> for Value {
60    fn from(f: f64) -> Self {
61        Value::Float(f)
62    }
63}
64
65impl From<bool> for Value {
66    fn from(b: bool) -> Self {
67        Value::Bool(b)
68    }
69}
70
71impl From<Vec<u8>> for Value {
72    fn from(b: Vec<u8>) -> Self {
73        Value::Bytes(b)
74    }
75}
76
77impl From<NdbDateTime> for Value {
78    fn from(dt: NdbDateTime) -> Self {
79        Value::DateTime(dt)
80    }
81}
82
83impl From<NdbDuration> for Value {
84    fn from(d: NdbDuration) -> Self {
85        Value::Duration(d)
86    }
87}
88
89impl From<rust_decimal::Decimal> for Value {
90    fn from(d: rust_decimal::Decimal) -> Self {
91        Value::Decimal(d)
92    }
93}
94
95impl From<Geometry> for Value {
96    fn from(g: Geometry) -> Self {
97        Value::Geometry(g)
98    }
99}
100
101impl From<Vec<f32>> for Value {
102    fn from(v: Vec<f32>) -> Self {
103        Value::Vector(v.into())
104    }
105}
106
107impl From<Arc<[f32]>> for Value {
108    fn from(v: Arc<[f32]>) -> Self {
109        Value::Vector(v)
110    }
111}
112
113impl From<&[f32]> for Value {
114    fn from(v: &[f32]) -> Self {
115        Value::Vector(v.into())
116    }
117}