use std::{fmt, time::Duration};
mod scalar;
pub use self::scalar::{Type as ScalarType, Value as ScalarValue};
pub trait ToValueType {
fn to_value_type(&self) -> ValueType;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ValueType {
Scalar(ScalarType),
Duration,
String,
Bytes,
}
const TYPE_STR_DURATION: &str = "duration";
const TYPE_STR_STRING: &str = "string";
const TYPE_STR_BYTES: &str = "bytes";
impl ValueType {
#[must_use]
pub const fn to_scalar(self) -> Option<ScalarType> {
match self {
Self::Scalar(s) => Some(s),
_ => None,
}
}
#[must_use]
pub const fn is_scalar(self) -> bool {
self.to_scalar().is_some()
}
#[must_use]
pub const fn from_scalar(scalar: ScalarType) -> Self {
Self::Scalar(scalar)
}
const fn as_str(self) -> &'static str {
match self {
Self::Scalar(s) => s.as_str(),
Self::Duration => TYPE_STR_DURATION,
Self::String => TYPE_STR_STRING,
Self::Bytes => TYPE_STR_BYTES,
}
}
#[must_use]
pub fn try_from_str(s: &str) -> Option<Self> {
ScalarType::try_from_str(s).map(Into::into).or(match s {
TYPE_STR_DURATION => Some(Self::Duration),
TYPE_STR_STRING => Some(Self::String),
TYPE_STR_BYTES => Some(Self::Bytes),
_ => None,
})
}
}
impl From<ScalarType> for ValueType {
fn from(from: ScalarType) -> Self {
Self::from_scalar(from)
}
}
impl fmt::Display for ValueType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Scalar(ScalarValue),
Duration(Duration),
String(String),
Bytes(Vec<u8>),
}
impl From<Duration> for Value {
fn from(from: Duration) -> Value {
Self::Duration(from)
}
}
impl From<String> for Value {
fn from(from: String) -> Value {
Self::String(from)
}
}
impl From<Vec<u8>> for Value {
fn from(from: Vec<u8>) -> Value {
Self::Bytes(from)
}
}
impl Value {
#[must_use]
pub const fn to_type(&self) -> ValueType {
match self {
Self::Scalar(value) => ValueType::Scalar(value.to_type()),
Self::Duration(_) => ValueType::Duration,
Self::String(_) => ValueType::String,
Self::Bytes(_) => ValueType::Bytes,
}
}
#[must_use]
pub const fn to_scalar(&self) -> Option<ScalarValue> {
match self {
Self::Scalar(scalar) => Some(*scalar),
_ => None,
}
}
#[must_use]
pub const fn from_scalar(scalar: ScalarValue) -> Self {
Self::Scalar(scalar)
}
pub fn to_i32(&self) -> Option<i32> {
self.to_scalar().and_then(ScalarValue::to_i32)
}
pub fn to_u32(&self) -> Option<u32> {
self.to_scalar().and_then(ScalarValue::to_u32)
}
pub fn to_i64(&self) -> Option<i64> {
self.to_scalar().and_then(ScalarValue::to_i64)
}
pub fn to_u64(&self) -> Option<u64> {
self.to_scalar().and_then(ScalarValue::to_u64)
}
pub fn to_f32(&self) -> Option<f32> {
self.to_scalar().and_then(ScalarValue::to_f32)
}
pub fn to_f64(&self) -> Option<f64> {
self.to_scalar().and_then(ScalarValue::to_f64)
}
}
impl ToValueType for Value {
fn to_value_type(&self) -> ValueType {
self.to_type()
}
}
impl<S> From<S> for Value
where
S: Into<ScalarValue>,
{
fn from(from: S) -> Self {
Value::Scalar(from.into())
}
}