use std::{
borrow::Cow,
convert::{TryFrom, TryInto},
rc::Rc,
sync::Arc,
};
use bytes::{Bytes, BytesMut};
use crate::BastehError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]
pub enum ValueKind {
Number = 0,
String = 1,
Bytes = 2,
List = 3,
}
impl ValueKind {
pub fn from_u8(n: u8) -> Option<Self> {
match n {
0 => Some(ValueKind::Number),
1 => Some(ValueKind::String),
2 => Some(ValueKind::Bytes),
3 => Some(ValueKind::List),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value<'a> {
Number(i64),
String(Cow<'a, str>),
Bytes(Bytes),
List(Vec<Value<'a>>),
}
impl<'a> Value<'a> {
pub fn kind(&self) -> ValueKind {
match self {
Self::Number(_) => ValueKind::Number,
Self::String(_) => ValueKind::String,
Self::Bytes(_) => ValueKind::Bytes,
Self::List(_) => ValueKind::List,
}
}
pub fn to_owned(&self) -> OwnedValue {
match &self {
Value::Number(n) => OwnedValue::Number(*n),
Value::String(s) => OwnedValue::String(s.clone().into_owned()),
Value::Bytes(b) => OwnedValue::Bytes(b.iter().collect()),
Value::List(l) => OwnedValue::List(l.iter().map(|v| v.to_owned()).collect()),
}
}
pub fn into_owned(self) -> OwnedValue {
match self {
Value::Number(n) => OwnedValue::Number(n),
Value::String(s) => OwnedValue::String(s.into_owned()),
Value::Bytes(b) => OwnedValue::Bytes(b.iter().collect()),
Value::List(l) => OwnedValue::List(l.into_iter().map(|v| v.into_owned()).collect()),
}
}
}
impl<'a> From<&'a str> for Value<'a> {
fn from(value: &'a str) -> Self {
Self::String(Cow::Borrowed(value))
}
}
impl<'a> From<&'a Rc<str>> for Value<'a> {
fn from(value: &'a Rc<str>) -> Self {
Self::String(Cow::Borrowed(value))
}
}
impl<'a> From<&'a Arc<str>> for Value<'a> {
fn from(value: &'a Arc<str>) -> Self {
Self::String(Cow::Borrowed(value))
}
}
impl<'a> From<String> for Value<'a> {
fn from(value: String) -> Self {
Self::String(Cow::Owned(value))
}
}
impl<'a> From<&'a String> for Value<'a> {
fn from(value: &'a String) -> Self {
Self::String(Cow::Borrowed(value))
}
}
impl<'a> From<Bytes> for Value<'a> {
fn from(value: Bytes) -> Self {
Self::Bytes(value.clone())
}
}
impl<'a> From<&'a Bytes> for Value<'a> {
fn from(value: &'a Bytes) -> Self {
Self::Bytes(value.clone())
}
}
impl<'a, 'b, T> From<&'b [T]> for Value<'a>
where
&'b T: Into<Value<'a>> + 'static,
{
fn from(value: &'b [T]) -> Self {
Value::List(value.into_iter().map(Into::into).collect())
}
}
impl<'a, T, const N: usize> From<[T; N]> for Value<'a>
where
T: Into<Value<'a>>,
{
fn from(value: [T; N]) -> Self {
Value::List(value.map(Into::into).to_vec())
}
}
impl<'a, 'b, T> From<&'b Vec<T>> for Value<'a>
where
&'b T: Into<Value<'a>> + 'static,
{
fn from(value: &'b Vec<T>) -> Self {
Value::List(value.into_iter().map(Into::into).collect())
}
}
impl<'a, T> From<Vec<T>> for Value<'a>
where
T: Into<Value<'a>>,
{
fn from(value: Vec<T>) -> Self {
Value::List(value.into_iter().map(Into::into).collect())
}
}
macro_rules! impl_from_number {
($number:ty) => {
impl<'a> From<$number> for Value<'a> {
fn from(value: $number) -> Self {
Self::Number(value as i64)
}
}
impl<'a, 'b> From<&'b $number> for Value<'a> {
fn from(value: &'b $number) -> Self {
Self::Number(*value as i64)
}
}
};
}
impl_from_number!(u8);
impl_from_number!(i8);
impl_from_number!(u16);
impl_from_number!(i16);
impl_from_number!(u32);
impl_from_number!(i32);
impl_from_number!(i64);
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum OwnedValue {
Number(i64),
String(String),
Bytes(BytesMut),
List(Vec<OwnedValue>),
}
impl OwnedValue {
pub fn kind(&self) -> ValueKind {
match self {
Self::Number(_) => ValueKind::Number,
Self::String(_) => ValueKind::String,
Self::Bytes(_) => ValueKind::Bytes,
Self::List(_) => ValueKind::List,
}
}
pub fn as_value(&self) -> Value<'_> {
match &self {
OwnedValue::Number(n) => Value::Number(*n),
OwnedValue::String(s) => Value::String(Cow::Borrowed(&s)),
OwnedValue::Bytes(b) => Value::Bytes(b.clone().freeze()),
OwnedValue::List(l) => Value::List(l.into_iter().map(|v| v.as_value()).collect()),
}
}
}
impl<'a> TryFrom<OwnedValue> for String {
type Error = BastehError;
fn try_from(value: OwnedValue) -> Result<Self, Self::Error> {
match value {
OwnedValue::String(val) => Ok(val),
OwnedValue::Number(n) => Ok(n.to_string()),
OwnedValue::Bytes(b) => Ok(String::from_utf8_lossy(&b).into_owned()),
OwnedValue::List(_) => Err(BastehError::TypeConversion),
}
}
}
impl<'a> TryFrom<OwnedValue> for Bytes {
type Error = BastehError;
fn try_from(value: OwnedValue) -> Result<Self, Self::Error> {
match value {
OwnedValue::String(val) => Ok(Bytes::from(val.into_bytes())),
OwnedValue::Bytes(b) => Ok(b.freeze()),
_ => Err(BastehError::TypeConversion),
}
}
}
impl<'a> TryFrom<OwnedValue> for BytesMut {
type Error = BastehError;
fn try_from(value: OwnedValue) -> Result<Self, Self::Error> {
match value {
OwnedValue::String(val) => Ok(BytesMut::from(val.as_bytes())),
OwnedValue::Bytes(b) => Ok(b),
_ => Err(BastehError::TypeConversion),
}
}
}
macro_rules! impl_from_value_for_number {
($number:ty) => {
impl<'a> TryFrom<OwnedValue> for $number {
type Error = BastehError;
fn try_from(value: OwnedValue) -> Result<Self, Self::Error> {
match value {
OwnedValue::Number(val) => {
val.try_into().map_err(|_| BastehError::TypeConversion)
}
_ => Err(BastehError::TypeConversion),
}
}
}
};
}
impl_from_value_for_number!(u8);
impl_from_value_for_number!(i8);
impl_from_value_for_number!(u16);
impl_from_value_for_number!(i16);
impl_from_value_for_number!(u32);
impl_from_value_for_number!(i32);
impl_from_value_for_number!(i64);
impl_from_value_for_number!(u64);