mod display;
mod impls;
mod opaque;
mod optional;
mod traits;
use crate::types::*;
use crate::{Error, Kind};
use std::collections::HashMap;
pub use opaque::*;
pub use optional::*;
pub use traits::*;
pub type StringValue = arc_slice::ArcStr;
pub type BytesValue = arc_slice::ArcBytes;
pub type Duration = chrono::Duration;
pub type Timestamp = chrono::DateTime<chrono::Utc>;
pub type ListValue = Vec<Value>;
pub type MapValue = HashMap<MapKey, Value>;
#[derive(Clone, PartialEq)]
pub struct StructValue {
type_name: String,
bytes: Vec<u8>,
}
impl StructValue {
pub fn from_bytes(type_name: impl Into<String>, bytes: impl Into<Vec<u8>>) -> Self {
Self {
type_name: type_name.into(),
bytes: bytes.into(),
}
}
pub fn type_name(&self) -> &str {
&self.type_name
}
pub fn to_bytes(&self) -> &[u8] {
&self.bytes
}
}
impl std::fmt::Debug for StructValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StructValue")
.field("type_name", &self.type_name())
.field("bytes_len", &self.to_bytes().len())
.finish()
}
}
pub type OpaqueValue = Box<dyn Opaque>;
pub type OptionalValue = Optional<Value>;
#[derive(Clone, Debug, PartialEq, Default)]
pub enum Value {
#[default]
Null,
Bool(bool),
Int(i64),
Uint(u64),
Double(f64),
String(StringValue),
Bytes(BytesValue),
Struct(StructValue),
Duration(Duration),
Timestamp(Timestamp),
List(ListValue),
Map(MapValue),
Unknown(()),
Type(ValueType),
Error(Error),
Opaque(OpaqueValue),
Optional(OptionalValue),
}
impl Value {
pub fn kind(&self) -> Kind {
match &self {
Value::Null => Kind::Null,
Value::Bool(_) => Kind::Bool,
Value::Int(_i) => Kind::Int,
Value::Uint(_u) => Kind::Uint,
Value::Double(_d) => Kind::Double,
Value::String(_s) => Kind::String,
Value::Bytes(_b) => Kind::Bytes,
Value::Struct(_s) => Kind::Struct,
Value::Duration(_d) => Kind::Duration,
Value::Timestamp(_t) => Kind::Timestamp,
Value::List(_l) => Kind::List,
Value::Map(_m) => Kind::Map,
Value::Unknown(_u) => Kind::Unknown,
Value::Type(_t) => Kind::Type,
Value::Error(_e) => Kind::Error,
Value::Opaque(_) | Value::Optional(_) => Kind::Opaque,
}
}
pub fn value_type(&self) -> ValueType {
match &self {
Value::Null => ValueType::Null,
Value::Bool(_) => ValueType::Bool,
Value::Int(_) => ValueType::Int,
Value::Uint(_) => ValueType::Uint,
Value::Double(_) => ValueType::Double,
Value::String(_) => ValueType::String,
Value::Bytes(_) => ValueType::Bytes,
Value::Struct(s) => {
ValueType::Struct(crate::types::StructType::new(s.type_name()))
}
Value::Duration(_) => ValueType::Duration,
Value::Timestamp(_) => ValueType::Timestamp,
Value::List(list) => {
let mut iter = list.iter();
if let Some(v) = iter.next() {
let elem_type = v.value_type();
if elem_type == ValueType::Dyn {
return ValueType::List(ListType::new(ValueType::Dyn));
}
for v in iter {
if v.value_type() != elem_type {
return ValueType::List(ListType::new(ValueType::Dyn));
}
}
return ValueType::List(ListType::new(elem_type));
}
ValueType::List(ListType::new(ValueType::Dyn))
}
Value::Map(m) => {
let mut iter = m.iter();
if let Some((k, v)) = iter.next() {
let mut key_type = Some(k.mapkey_type());
let mut val_type = v.value_type();
for (k, v) in iter {
if let Some(prev_key_type) = key_type.clone() {
if k.mapkey_type() != prev_key_type {
key_type = None;
}
}
if val_type != ValueType::Dyn && v.value_type() != val_type {
val_type = ValueType::Dyn;
}
if key_type.is_none() && val_type == ValueType::Dyn {
break;
}
}
ValueType::Map(MapType::new(key_type.unwrap_or(MapKeyType::Dyn), val_type))
} else {
ValueType::Map(MapType::new(MapKeyType::Dyn, ValueType::Dyn))
}
}
Value::Unknown(_u) => ValueType::Unknown,
Value::Opaque(o) => ValueType::Opaque(o.opaque_type()),
Value::Optional(opt) => {
if let Some(v) = opt.as_option() {
return ValueType::Optional(OptionalType::new(v.value_type()));
}
ValueType::Optional(OptionalType::new(ValueType::Dyn))
}
Value::Type(_t) => ValueType::Type(TypeType::new(None)),
Value::Error(_e) => ValueType::Error,
}
}
pub fn is_null(&self) -> bool {
matches!(self, Value::Null)
}
pub fn is_bool(&self) -> bool {
matches!(self, Value::Bool(_))
}
pub fn is_int(&self) -> bool {
matches!(self, Value::Int(_))
}
pub fn is_uint(&self) -> bool {
matches!(self, Value::Uint(_))
}
pub fn is_double(&self) -> bool {
matches!(self, Value::Double(_))
}
pub fn is_string(&self) -> bool {
matches!(self, Value::String(_))
}
pub fn is_bytes(&self) -> bool {
matches!(self, Value::Bytes(_))
}
pub fn is_struct(&self) -> bool {
matches!(self, Value::Struct(_))
}
pub fn is_duration(&self) -> bool {
matches!(self, Value::Duration(_))
}
pub fn is_timestamp(&self) -> bool {
matches!(self, Value::Timestamp(_))
}
pub fn is_list(&self) -> bool {
matches!(self, Value::List(_))
}
pub fn is_map(&self) -> bool {
matches!(self, Value::Map(_))
}
pub fn is_unknown(&self) -> bool {
matches!(self, Value::Unknown(_))
}
pub fn is_type(&self) -> bool {
matches!(self, Value::Type(_))
}
pub fn is_error(&self) -> bool {
matches!(self, Value::Error(_))
}
pub fn is_opaque(&self) -> bool {
matches!(self, Value::Opaque(_))
}
pub fn is_optional(&self) -> bool {
matches!(self, Value::Optional(_))
}
pub fn as_bool(&self) -> Option<&bool> {
match self {
Value::Bool(b) => Some(b),
_ => None,
}
}
pub fn as_int(&self) -> Option<&i64> {
match self {
Value::Int(i) => Some(i),
_ => None,
}
}
pub fn as_uint(&self) -> Option<&u64> {
match self {
Value::Uint(u) => Some(u),
_ => None,
}
}
pub fn as_double(&self) -> Option<&f64> {
match self {
Value::Double(d) => Some(d),
_ => None,
}
}
pub fn as_string(&self) -> Option<&StringValue> {
match self {
Value::String(s) => Some(s),
_ => None,
}
}
pub fn as_bytes(&self) -> Option<&BytesValue> {
match self {
Value::Bytes(b) => Some(b),
_ => None,
}
}
pub fn as_struct(&self) -> Option<&StructValue> {
match self {
Value::Struct(s) => Some(s),
_ => None,
}
}
pub fn as_duration(&self) -> Option<&Duration> {
match self {
Value::Duration(d) => Some(d),
_ => None,
}
}
pub fn as_timestamp(&self) -> Option<&Timestamp> {
match self {
Value::Timestamp(t) => Some(t),
_ => None,
}
}
pub fn as_list(&self) -> Option<&ListValue> {
match self {
Value::List(l) => Some(l),
_ => None,
}
}
pub fn as_map(&self) -> Option<&MapValue> {
match self {
Value::Map(m) => Some(m),
_ => None,
}
}
pub fn as_unknown(&self) -> Option<&()> {
match self {
Value::Unknown(u) => Some(u),
_ => None,
}
}
pub fn as_type(&self) -> Option<&ValueType> {
match self {
Value::Type(t) => Some(t),
_ => None,
}
}
pub fn as_error(&self) -> Option<&Error> {
match self {
Value::Error(e) => Some(e),
_ => None,
}
}
pub fn as_opaque(&self) -> Option<&OpaqueValue> {
match self {
Value::Opaque(o) => Some(o),
_ => None,
}
}
pub fn as_optional(&self) -> Option<&OptionalValue> {
match self {
Value::Optional(o) => Some(o),
_ => None,
}
}
pub fn as_bool_mut(&mut self) -> Option<&mut bool> {
match self {
Value::Bool(b) => Some(b),
_ => None,
}
}
pub fn as_int_mut(&mut self) -> Option<&mut i64> {
match self {
Value::Int(i) => Some(i),
_ => None,
}
}
pub fn as_uint_mut(&mut self) -> Option<&mut u64> {
match self {
Value::Uint(u) => Some(u),
_ => None,
}
}
pub fn as_double_mut(&mut self) -> Option<&mut f64> {
match self {
Value::Double(d) => Some(d),
_ => None,
}
}
pub fn as_string_mut(&mut self) -> Option<&mut StringValue> {
match self {
Value::String(s) => Some(s),
_ => None,
}
}
pub fn as_bytes_mut(&mut self) -> Option<&mut BytesValue> {
match self {
Value::Bytes(b) => Some(b),
_ => None,
}
}
pub fn as_duration_mut(&mut self) -> Option<&mut Duration> {
match self {
Value::Duration(d) => Some(d),
_ => None,
}
}
pub fn as_timestamp_mut(&mut self) -> Option<&mut Timestamp> {
match self {
Value::Timestamp(t) => Some(t),
_ => None,
}
}
pub fn as_list_mut(&mut self) -> Option<&mut ListValue> {
match self {
Value::List(l) => Some(l),
_ => None,
}
}
pub fn as_map_mut(&mut self) -> Option<&mut MapValue> {
match self {
Value::Map(m) => Some(m),
_ => None,
}
}
pub fn as_unknown_mut(&mut self) -> Option<&mut ()> {
match self {
Value::Unknown(u) => Some(u),
_ => None,
}
}
pub fn as_type_mut(&mut self) -> Option<&mut ValueType> {
match self {
Value::Type(t) => Some(t),
_ => None,
}
}
pub fn as_error_mut(&mut self) -> Option<&mut Error> {
match self {
Value::Error(e) => Some(e),
_ => None,
}
}
pub fn as_opaque_mut(&mut self) -> Option<&mut OpaqueValue> {
match self {
Value::Opaque(o) => Some(o),
_ => None,
}
}
pub fn as_optional_mut(&mut self) -> Option<&mut OptionalValue> {
match self {
Value::Optional(o) => Some(o),
_ => None,
}
}
pub fn into_null(self) -> Option<()> {
match self {
Value::Null => Some(()),
_ => None,
}
}
pub fn into_bool(self) -> Option<bool> {
match self {
Value::Bool(b) => Some(b),
_ => None,
}
}
pub fn into_int(self) -> Option<i64> {
match self {
Value::Int(i) => Some(i),
_ => None,
}
}
pub fn into_uint(self) -> Option<u64> {
match self {
Value::Uint(u) => Some(u),
_ => None,
}
}
pub fn into_double(self) -> Option<f64> {
match self {
Value::Double(d) => Some(d),
_ => None,
}
}
pub fn into_string(self) -> Option<StringValue> {
match self {
Value::String(s) => Some(s),
_ => None,
}
}
pub fn into_bytes(self) -> Option<BytesValue> {
match self {
Value::Bytes(b) => Some(b),
_ => None,
}
}
pub fn into_struct(self) -> Option<StructValue> {
match self {
Value::Struct(s) => Some(s),
_ => None,
}
}
pub fn into_duration(self) -> Option<Duration> {
match self {
Value::Duration(d) => Some(d),
_ => None,
}
}
pub fn into_timestamp(self) -> Option<Timestamp> {
match self {
Value::Timestamp(t) => Some(t),
_ => None,
}
}
pub fn into_list(self) -> Option<ListValue> {
match self {
Value::List(l) => Some(l),
_ => None,
}
}
pub fn into_map(self) -> Option<MapValue> {
match self {
Value::Map(m) => Some(m),
_ => None,
}
}
pub fn into_unknown(self) -> Option<()> {
match self {
Value::Unknown(u) => Some(u),
_ => None,
}
}
pub fn into_type(self) -> Option<ValueType> {
match self {
Value::Type(t) => Some(t),
_ => None,
}
}
pub fn into_error(self) -> Option<Error> {
match self {
Value::Error(e) => Some(e),
_ => None,
}
}
pub fn into_opaque(self) -> Option<OpaqueValue> {
match self {
Value::Opaque(o) => Some(o),
_ => None,
}
}
pub fn into_optional(self) -> Option<OptionalValue> {
match self {
Value::Optional(o) => Some(o),
_ => None,
}
}
pub fn unwrap_null(self) {
match self {
Value::Null => (),
_ => panic!("called `Value::unwrap_null()` on a non-null value: {self:?}",),
}
}
pub fn unwrap_bool(self) -> bool {
match self {
Value::Bool(b) => b,
_ => panic!("called `Value::unwrap_bool()` on a non-bool value: {self:?}",),
}
}
pub fn unwrap_int(self) -> i64 {
match self {
Value::Int(i) => i,
_ => panic!("called `Value::unwrap_int()` on a non-int value: {self:?}",),
}
}
pub fn unwrap_uint(self) -> u64 {
match self {
Value::Uint(u) => u,
_ => panic!("called `Value::unwrap_uint()` on a non-uint value: {self:?}",),
}
}
pub fn unwrap_double(self) -> f64 {
match self {
Value::Double(d) => d,
_ => panic!("called `Value::unwrap_double()` on a non-double value: {self:?}",),
}
}
pub fn unwrap_string(self) -> StringValue {
match self {
Value::String(s) => s,
_ => panic!("called `Value::unwrap_string()` on a non-string value: {self:?}",),
}
}
pub fn unwrap_bytes(self) -> BytesValue {
match self {
Value::Bytes(b) => b,
_ => panic!("called `Value::unwrap_bytes()` on a non-bytes value: {self:?}",),
}
}
pub fn unwrap_struct(self) -> StructValue {
match self {
Value::Struct(s) => s,
_ => panic!("called `Value::unwrap_struct()` on a non-struct value: {self:?}",),
}
}
pub fn unwrap_duration(self) -> Duration {
match self {
Value::Duration(d) => d,
_ => panic!("called `Value::unwrap_duration()` on a non-duration value: {self:?}",),
}
}
pub fn unwrap_timestamp(self) -> Timestamp {
match self {
Value::Timestamp(t) => t,
_ => panic!("called `Value::unwrap_timestamp()` on a non-timestamp value: {self:?}",),
}
}
pub fn unwrap_list(self) -> ListValue {
match self {
Value::List(l) => l,
_ => panic!("called `Value::unwrap_list()` on a non-list value: {self:?}",),
}
}
pub fn unwrap_map(self) -> MapValue {
match self {
Value::Map(m) => m,
_ => panic!("called `Value::unwrap_map()` on a non-map value: {self:?}",),
}
}
pub fn unwrap_unknown(self) {
match self {
Value::Unknown(u) => u,
_ => panic!("called `Value::unwrap_unknown()` on a non-unknown value: {self:?}",),
}
}
pub fn unwrap_type(self) -> ValueType {
match self {
Value::Type(t) => t,
_ => panic!("called `Value::unwrap_type()` on a non-type value: {self:?}",),
}
}
pub fn unwrap_error(self) -> Error {
match self {
Value::Error(e) => e,
_ => panic!("called `Value::unwrap_error()` on a non-error value: {self:?}",),
}
}
pub fn unwrap_opaque(self) -> OpaqueValue {
match self {
Value::Opaque(o) => o,
_ => panic!("called `Value::unwrap_opaque()` on a non-opaque value: {self:?}",),
}
}
pub fn unwrap_optional(self) -> OptionalValue {
match self {
Value::Optional(o) => o,
_ => panic!("called `Value::unwrap_optional()` on a non-optional value: {self:?}",),
}
}
pub fn expect_null(self, msg: &str) {
match self {
Value::Null => (),
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_bool(self, msg: &str) -> bool {
match self {
Value::Bool(b) => b,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_int(self, msg: &str) -> i64 {
match self {
Value::Int(i) => i,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_uint(self, msg: &str) -> u64 {
match self {
Value::Uint(u) => u,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_double(self, msg: &str) -> f64 {
match self {
Value::Double(d) => d,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_string(self, msg: &str) -> StringValue {
match self {
Value::String(s) => s,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_bytes(self, msg: &str) -> BytesValue {
match self {
Value::Bytes(b) => b,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_struct(self, msg: &str) -> StructValue {
match self {
Value::Struct(s) => s,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_duration(self, msg: &str) -> Duration {
match self {
Value::Duration(d) => d,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_timestamp(self, msg: &str) -> Timestamp {
match self {
Value::Timestamp(t) => t,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_list(self, msg: &str) -> ListValue {
match self {
Value::List(l) => l,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_map(self, msg: &str) -> MapValue {
match self {
Value::Map(m) => m,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_unknown(self, msg: &str) {
match self {
Value::Unknown(u) => u,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_type(self, msg: &str) -> ValueType {
match self {
Value::Type(t) => t,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_error(self, msg: &str) -> Error {
match self {
Value::Error(e) => e,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_opaque(self, msg: &str) -> OpaqueValue {
match self {
Value::Opaque(o) => o,
_ => panic!("{msg}: {self:?}"),
}
}
pub fn expect_optional(self, msg: &str) -> OptionalValue {
match self {
Value::Optional(o) => o,
_ => panic!("{msg}: {self:?}"),
}
}
}
impl From<MapKey> for Value {
fn from(key: MapKey) -> Self {
match key {
MapKey::Bool(b) => Value::Bool(b),
MapKey::Int(i) => Value::Int(i),
MapKey::Uint(u) => Value::Uint(u),
MapKey::String(s) => Value::String(s),
}
}
}
impl TryFrom<Value> for MapKey {
type Error = FromValueError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value {
Value::Bool(b) => Ok(MapKey::Bool(b)),
Value::Int(i) => Ok(MapKey::Int(i)),
Value::Uint(u) => Ok(MapKey::Uint(u)),
Value::String(s) => Ok(MapKey::String(s)),
_ => Err(FromValueError::new(value, "MapKey")),
}
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum MapKey {
Bool(bool),
Int(i64),
Uint(u64),
String(StringValue),
}
impl MapKey {
pub fn kind(&self) -> Kind {
match self {
MapKey::Bool(_) => Kind::Bool,
MapKey::Int(_) => Kind::Int,
MapKey::Uint(_) => Kind::Uint,
MapKey::String(_) => Kind::String,
}
}
pub fn mapkey_type(&self) -> MapKeyType {
match self {
MapKey::Bool(_) => MapKeyType::Bool,
MapKey::Int(_) => MapKeyType::Int,
MapKey::Uint(_) => MapKeyType::Uint,
MapKey::String(_) => MapKeyType::String,
}
}
pub fn from_value(value: Value) -> Result<Self, Value> {
match value {
Value::Bool(b) => Ok(MapKey::Bool(b)),
Value::Int(i) => Ok(MapKey::Int(i)),
Value::Uint(u) => Ok(MapKey::Uint(u)),
Value::String(s) => Ok(MapKey::String(s)),
_ => Err(value),
}
}
pub fn into_value(self) -> Value {
match self {
MapKey::Bool(b) => Value::Bool(b),
MapKey::Int(i) => Value::Int(i),
MapKey::Uint(u) => Value::Uint(u),
MapKey::String(s) => Value::String(s),
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub enum Constant {
#[default]
Null,
Bool(bool),
Int(i64),
Uint(u64),
Double(f64),
Bytes(BytesValue),
String(StringValue),
Duration(chrono::Duration),
Timestamp(chrono::DateTime<chrono::Utc>),
}
impl Constant {
pub fn value_type(&self) -> ValueType {
match self {
Self::Null => ValueType::Null,
Self::Bool(_) => ValueType::Bool,
Self::Int(_) => ValueType::Int,
Self::Uint(_) => ValueType::Uint,
Self::Double(_) => ValueType::Double,
Self::Bytes(_) => ValueType::Bytes,
Self::String(_) => ValueType::String,
Self::Duration(_) => ValueType::Duration,
Self::Timestamp(_) => ValueType::Timestamp,
}
}
pub fn value(&self) -> Value {
match self {
Self::Null => Value::Null,
Self::Bool(value) => Value::Bool(*value),
Self::Int(value) => Value::Int(*value),
Self::Uint(value) => Value::Uint(*value),
Self::Double(value) => Value::Double(*value),
Self::Bytes(value) => Value::Bytes(value.clone()),
Self::String(value) => Value::String(value.clone()),
Self::Duration(value) => Value::Duration(*value),
Self::Timestamp(value) => Value::Timestamp(*value),
}
}
}
impl TryFrom<Value> for Constant {
type Error = FromValueError;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value {
Value::Null => Ok(Constant::Null),
Value::Bool(b) => Ok(Constant::Bool(b)),
Value::Int(i) => Ok(Constant::Int(i)),
Value::Uint(u) => Ok(Constant::Uint(u)),
Value::Double(d) => Ok(Constant::Double(d)),
Value::Bytes(b) => Ok(Constant::Bytes(b)),
Value::String(s) => Ok(Constant::String(s)),
Value::Duration(d) => Ok(Constant::Duration(d)),
Value::Timestamp(t) => Ok(Constant::Timestamp(t)),
_ => Err(FromValueError::new(value, "Constant")),
}
}
}
impl From<&Constant> for cxx::UniquePtr<crate::ffi::Constant> {
fn from(constant: &Constant) -> Self {
use crate::ffi::Constant as FfiConstant;
match constant {
Constant::Null => FfiConstant::new_null(),
Constant::Bool(value) => FfiConstant::new_bool(*value),
Constant::Int(value) => FfiConstant::new_int(*value),
Constant::Uint(value) => FfiConstant::new_uint(*value),
Constant::Double(value) => FfiConstant::new_double(*value),
Constant::Bytes(value) => FfiConstant::new_bytes(&value.as_ref()),
Constant::String(value) => FfiConstant::new_string(&value.as_ref()),
Constant::Duration(value) => FfiConstant::new_duration((*value).into()),
Constant::Timestamp(value) => FfiConstant::new_timestamp((*value).into()),
}
}
}
impl From<Constant> for cxx::UniquePtr<crate::ffi::Constant> {
fn from(constant: Constant) -> Self {
Self::from(&constant)
}
}
impl From<&crate::ffi::Constant> for Constant {
fn from(constant: &crate::ffi::Constant) -> Self {
use crate::ffi::ConstantKindCase;
match constant.kind_case() {
ConstantKindCase::Unspecified => Constant::Null,
ConstantKindCase::Null => Constant::Null,
ConstantKindCase::Bool => Constant::Bool(constant.bool_value()),
ConstantKindCase::Int => Constant::Int(constant.int_value()),
ConstantKindCase::Uint => Constant::Uint(constant.uint_value()),
ConstantKindCase::Double => Constant::Double(constant.double_value()),
ConstantKindCase::Bytes => Constant::Bytes(BytesValue::from(constant.bytes_value().as_bytes())),
ConstantKindCase::String => Constant::String(StringValue::from(constant.string_value().to_string())),
ConstantKindCase::Duration => Constant::Duration(constant.duration_value().into()),
ConstantKindCase::Timestamp => Constant::Timestamp(constant.timestamp_value().into()),
}
}
}
impl From<crate::ffi::Constant> for Constant {
fn from(constant: crate::ffi::Constant) -> Self {
Self::from(&constant)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_value_kind() {
let cases = vec![
(Value::Null, Kind::Null),
(Value::Bool(true), Kind::Bool),
(Value::Int(1), Kind::Int),
(Value::Uint(1), Kind::Uint),
(Value::Double(1.0), Kind::Double),
(Value::String("test".into()), Kind::String),
(Value::Bytes(b"abc".into()), Kind::Bytes),
(
Value::Duration(chrono::Duration::seconds(1)),
Kind::Duration,
),
(Value::Timestamp(chrono::Utc::now()), Kind::Timestamp),
(Value::List(vec![]), Kind::List),
(Value::Map(HashMap::new()), Kind::Map),
(Value::Type(ValueType::Null), Kind::Type),
(
Value::Error(Error::invalid_argument("invalid")),
Kind::Error,
),
(Value::Optional(Optional::none()), Kind::Opaque),
];
for (value, expected_kind) in cases {
assert_eq!(value.kind(), expected_kind);
}
}
#[test]
fn test_key_kind() {
let cases = vec![
(MapKey::Bool(true), Kind::Bool),
(MapKey::Int(1), Kind::Int),
(MapKey::Uint(1), Kind::Uint),
(MapKey::String("test".into()), Kind::String),
];
for (key, expected_kind) in cases {
assert_eq!(key.kind(), expected_kind);
}
}
#[test]
fn test_value_type() {
let cases = vec![
(Value::Null, ValueType::Null),
(Value::Bool(true), ValueType::Bool),
(Value::Int(1), ValueType::Int),
(Value::Uint(1), ValueType::Uint),
(Value::Double(1.0), ValueType::Double),
(Value::String("test".into()), ValueType::String),
(Value::Bytes(b"abc".into()), ValueType::Bytes),
(
Value::Duration(chrono::Duration::seconds(1)),
ValueType::Duration,
),
(Value::Timestamp(chrono::Utc::now()), ValueType::Timestamp),
(
Value::List(vec![Value::Int(1), Value::Int(2), Value::Int(3)]),
ValueType::List(ListType::new(ValueType::Int)),
),
(
Value::Map(HashMap::from([(
MapKey::String("test".into()),
Value::Int(1),
)])),
ValueType::Map(MapType::new(MapKeyType::String, ValueType::Int)),
),
(
Value::Type(ValueType::Double),
ValueType::Type(TypeType::new(None)),
),
(
Value::Error(Error::invalid_argument("invalid")),
ValueType::Error,
),
(
Value::Optional(Optional::new(Value::Int(5))),
ValueType::Optional(OptionalType::new(ValueType::Int)),
),
];
for (i, (value, expected_type)) in cases.into_iter().enumerate() {
assert_eq!(value.value_type(), expected_type, "case {i} failed");
}
}
}