use crate::{Duration, Time};
use itertools::Itertools;
use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::iter::FromIterator;
pub type MessageValue = HashMap<String, Value>;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Value {
Bool(bool),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
String(String),
Time(Time),
Duration(Duration),
Array(Vec<Value>),
Message(MessageValue),
}
impl Value {
fn fmt_indented(&self, indentation: usize, step: usize, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Value::Bool(v) => v.fmt(f),
Value::I8(v) => v.fmt(f),
Value::I16(v) => v.fmt(f),
Value::I32(v) => v.fmt(f),
Value::I64(v) => v.fmt(f),
Value::U8(v) => v.fmt(f),
Value::U16(v) => v.fmt(f),
Value::U32(v) => v.fmt(f),
Value::U64(v) => v.fmt(f),
Value::F32(v) => v.fmt(f),
Value::F64(v) => v.fmt(f),
Value::String(v) => write!(f, "{:?}", v),
Value::Time(v) => v.fmt(f),
Value::Duration(v) => v.fmt(f),
Value::Array(items) => {
for item in items {
writeln!(f)?;
write!(f, "{:indent$}- ", "", indent = indentation)?;
item.fmt_indented(indentation + step, step, f)?;
}
Ok(())
}
Value::Message(items) => {
for (key, item) in items.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0)) {
writeln!(f)?;
write!(f, "{:indent$}{}: ", "", key, indent = indentation)?;
item.fmt_indented(indentation + step, step, f)?;
}
Ok(())
}
}
}
pub fn as_bool(&self) -> Option<bool> {
if let Value::Bool(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_i8(&self) -> Option<i8> {
if let Value::I8(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_i16(&self) -> Option<i16> {
if let Value::I16(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_i32(&self) -> Option<i32> {
if let Value::I32(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_i64(&self) -> Option<i64> {
if let Value::I64(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_u8(&self) -> Option<u8> {
if let Value::U8(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_u16(&self) -> Option<u16> {
if let Value::U16(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_u32(&self) -> Option<u32> {
if let Value::U32(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_u64(&self) -> Option<u64> {
if let Value::U64(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_f32(&self) -> Option<f32> {
if let Value::F32(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_f64(&self) -> Option<f64> {
if let Value::F64(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_str(&self) -> Option<&str> {
if let Value::String(value) = self {
Some(value)
} else {
None
}
}
pub fn try_into_string(self) -> Option<String> {
if let Value::String(value) = self {
Some(value)
} else {
None
}
}
pub fn as_time(&self) -> Option<Time> {
if let Value::Time(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_duration(&self) -> Option<Duration> {
if let Value::Duration(value) = self {
Some(*value)
} else {
None
}
}
pub fn as_slice(&self) -> Option<&[Value]> {
if let Value::Array(value) = self {
Some(value)
} else {
None
}
}
pub fn try_into_vec(self) -> Option<Vec<Value>> {
if let Value::Array(value) = self {
Some(value)
} else {
None
}
}
pub fn as_map(&self) -> Option<&MessageValue> {
if let Value::Message(value) = self {
Some(value)
} else {
None
}
}
pub fn try_into_map(self) -> Option<MessageValue> {
if let Value::Message(value) = self {
Some(value)
} else {
None
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.fmt_indented(0, 2, f)
}
}
impl From<bool> for Value {
fn from(v: bool) -> Self {
Self::Bool(v)
}
}
impl From<i8> for Value {
fn from(v: i8) -> Self {
Self::I8(v)
}
}
impl From<i16> for Value {
fn from(v: i16) -> Self {
Self::I16(v)
}
}
impl From<i32> for Value {
fn from(v: i32) -> Self {
Self::I32(v)
}
}
impl From<i64> for Value {
fn from(v: i64) -> Self {
Self::I64(v)
}
}
impl From<u8> for Value {
fn from(v: u8) -> Self {
Self::U8(v)
}
}
impl From<u16> for Value {
fn from(v: u16) -> Self {
Self::U16(v)
}
}
impl From<u32> for Value {
fn from(v: u32) -> Self {
Self::U32(v)
}
}
impl From<u64> for Value {
fn from(v: u64) -> Self {
Self::U64(v)
}
}
impl From<f32> for Value {
fn from(v: f32) -> Self {
Self::F32(v)
}
}
impl From<f64> for Value {
fn from(v: f64) -> Self {
Self::F64(v)
}
}
impl From<String> for Value {
fn from(v: String) -> Self {
Self::String(v)
}
}
impl From<Time> for Value {
fn from(v: Time) -> Self {
Self::Time(v)
}
}
impl From<Duration> for Value {
fn from(v: Duration) -> Self {
Self::Duration(v)
}
}
impl<T: Into<Value>> From<Vec<T>> for Value {
fn from(v: Vec<T>) -> Self {
Self::Array(v.into_iter().map(Into::into).collect())
}
}
impl<T: Into<Value>, const L: usize> From<[T; L]> for Value {
fn from(v: [T; L]) -> Self {
Self::Array(IntoIterator::into_iter(v).map(Into::into).collect())
}
}
impl From<HashMap<String, Value>> for Value {
fn from(v: HashMap<String, Value>) -> Self {
Self::Message(v)
}
}
impl TryFrom<Value> for bool {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_bool().ok_or(())
}
}
impl TryFrom<Value> for i8 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_i8().ok_or(())
}
}
impl TryFrom<Value> for i16 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_i16().ok_or(())
}
}
impl TryFrom<Value> for i32 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_i32().ok_or(())
}
}
impl TryFrom<Value> for i64 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_i64().ok_or(())
}
}
impl TryFrom<Value> for u8 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_u8().ok_or(())
}
}
impl TryFrom<Value> for u16 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_u16().ok_or(())
}
}
impl TryFrom<Value> for u32 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_u32().ok_or(())
}
}
impl TryFrom<Value> for u64 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_u64().ok_or(())
}
}
impl TryFrom<Value> for f32 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_f32().ok_or(())
}
}
impl TryFrom<Value> for f64 {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_f64().ok_or(())
}
}
impl TryFrom<Value> for String {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.try_into_string().ok_or(())
}
}
impl TryFrom<Value> for Time {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_time().ok_or(())
}
}
impl TryFrom<Value> for Duration {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.as_duration().ok_or(())
}
}
impl<T: TryFrom<Value>> TryFrom<Value> for Vec<T> {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
let value = value.try_into_vec().ok_or(())?;
value
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Self, _>>()
.map_err(|_| ())
}
}
impl<T: TryFrom<Value>, const L: usize> TryFrom<Value> for [T; L] {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
let value = value.try_into_vec().ok_or(())?;
if value.len() != L {
return Err(());
}
array_init::from_iter(value.into_iter().filter_map(|v| v.try_into().ok())).ok_or(())
}
}
impl TryFrom<Value> for HashMap<String, Value> {
type Error = ();
fn try_from(value: Value) -> Result<Self, Self::Error> {
value.try_into_map().ok_or(())
}
}
impl<K: Into<String>, T: Into<Value>> FromIterator<(K, T)> for Value {
fn from_iter<I: IntoIterator<Item = (K, T)>>(iter: I) -> Self {
Self::Message(
iter.into_iter()
.map(|(key, value)| (key.into(), value.into()))
.collect(),
)
}
}
impl<T: Into<Value>> FromIterator<T> for Value {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self::Array(iter.into_iter().map(Into::into).collect())
}
}