use crate::low::v7400::AttributeType;
#[derive(Debug, Clone, PartialEq)]
pub enum AttributeValue {
Bool(bool),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
ArrBool(Vec<bool>),
ArrI32(Vec<i32>),
ArrI64(Vec<i64>),
ArrF32(Vec<f32>),
ArrF64(Vec<f64>),
String(String),
Binary(Vec<u8>),
}
macro_rules! impl_val_getter {
($variant:ident, $ty_ret:ty, $opt_getter:ident, $opt_doc:expr, $res_getter:ident, $res_doc:expr,) => {
#[doc = $opt_doc]
#[inline]
#[must_use]
pub fn $opt_getter(&self) -> Option<$ty_ret> {
match self {
AttributeValue::$variant(v) => Some(*v),
_ => None,
}
}
#[doc = $res_doc]
pub fn $res_getter(&self) -> Result<$ty_ret, AttributeType> {
match self {
AttributeValue::$variant(v) => Ok(*v),
_ => Err(self.type_()),
}
}
};
}
macro_rules! impl_ref_getter {
($variant:ident, $ty_ret:ty, $opt_getter:ident, $opt_doc:expr, $res_getter:ident, $res_doc:expr,) => {
#[doc = $opt_doc]
#[inline]
#[must_use]
pub fn $opt_getter(&self) -> Option<&$ty_ret> {
match self {
AttributeValue::$variant(v) => Some(v),
_ => None,
}
}
#[doc = $res_doc]
pub fn $res_getter(&self) -> Result<&$ty_ret, AttributeType> {
match self {
AttributeValue::$variant(v) => Ok(v),
_ => Err(self.type_()),
}
}
};
}
impl AttributeValue {
#[must_use]
pub fn type_(&self) -> AttributeType {
match self {
AttributeValue::Bool(_) => AttributeType::Bool,
AttributeValue::I16(_) => AttributeType::I16,
AttributeValue::I32(_) => AttributeType::I32,
AttributeValue::I64(_) => AttributeType::I64,
AttributeValue::F32(_) => AttributeType::F32,
AttributeValue::F64(_) => AttributeType::F64,
AttributeValue::ArrBool(_) => AttributeType::ArrBool,
AttributeValue::ArrI32(_) => AttributeType::ArrI32,
AttributeValue::ArrI64(_) => AttributeType::ArrI64,
AttributeValue::ArrF32(_) => AttributeType::ArrF32,
AttributeValue::ArrF64(_) => AttributeType::ArrF64,
AttributeValue::String(_) => AttributeType::String,
AttributeValue::Binary(_) => AttributeType::Binary,
}
}
impl_val_getter! {
Bool,
bool,
get_bool,
"Returns the the inner `bool` value, if available.",
get_bool_or_type,
"Returns the the inner `bool` value, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_val_getter! {
I16,
i16,
get_i16,
"Returns the the inner `i16` value, if available.",
get_i16_or_type,
"Returns the the inner `i16` value, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_val_getter! {
I32,
i32,
get_i32,
"Returns the the inner `i32` value, if available.",
get_i32_or_type,
"Returns the the inner `i32` value, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_val_getter! {
I64,
i64,
get_i64,
"Returns the the inner `i64` value, if available.",
get_i64_or_type,
"Returns the the inner `i64` value, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_val_getter! {
F32,
f32,
get_f32,
"Returns the the inner `f32` value, if available.",
get_f32_or_type,
"Returns the the inner `f32` value, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_val_getter! {
F64,
f64,
get_f64,
"Returns the the inner `f64` value, if available.",
get_f64_or_type,
"Returns the the inner `f64` value, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_ref_getter! {
ArrBool,
[bool],
get_arr_bool,
"Returns the reference to the inner `bool` slice, if available.",
get_arr_bool_or_type,
"Returns the reference to the inner `bool` slice, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_ref_getter! {
ArrI32,
[i32],
get_arr_i32,
"Returns the reference to the inner `i32` slice, if available.",
get_arr_i32_or_type,
"Returns the reference to the inner `i32` slice, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_ref_getter! {
ArrI64,
[i64],
get_arr_i64,
"Returns the reference to the inner `i64` slice, if available.",
get_arr_i64_or_type,
"Returns the reference to the inner `i64` slice, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_ref_getter! {
ArrF32,
[f32],
get_arr_f32,
"Returns the reference to the inner `f32` slice, if available.",
get_arr_f32_or_type,
"Returns the reference to the inner `f32` slice, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_ref_getter! {
ArrF64,
[f64],
get_arr_f64,
"Returns the reference to the inner `f64` slice, if available.",
get_arr_f64_or_type,
"Returns the reference to the inner `f64` slice, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_ref_getter! {
String,
str,
get_string,
"Returns the reference to the inner string slice, if available.",
get_string_or_type,
"Returns the reference to the inner string slice, if available.\n\nReturns `Err(type)` on type mismatch.",
}
impl_ref_getter! {
Binary,
[u8],
get_binary,
"Returns the reference to the inner binary data, if available.",
get_binary_or_type,
"Returns the reference to the inner binary data, if available.\n\nReturns `Err(type)` on type mismatch.",
}
pub fn strict_eq(&self, other: &Self) -> bool {
use AttributeValue::*;
match (self, other) {
(Bool(l), Bool(r)) => l == r,
(I16(l), I16(r)) => l == r,
(I32(l), I32(r)) => l == r,
(I64(l), I64(r)) => l == r,
(F32(l), F32(r)) => l.to_bits() == r.to_bits(),
(F64(l), F64(r)) => l.to_bits() == r.to_bits(),
(ArrBool(l), ArrBool(r)) => l == r,
(ArrI32(l), ArrI32(r)) => l == r,
(ArrI64(l), ArrI64(r)) => l == r,
(ArrF32(l), ArrF32(r)) => l
.iter()
.map(|v| v.to_bits())
.eq(r.iter().map(|v| v.to_bits())),
(ArrF64(l), ArrF64(r)) => l
.iter()
.map(|v| v.to_bits())
.eq(r.iter().map(|v| v.to_bits())),
(Binary(l), Binary(r)) => l == r,
(String(l), String(r)) => l == r,
_ => false,
}
}
}
macro_rules! impl_from {
(direct: $ty:ty, $variant:ident) => {
impl From<$ty> for AttributeValue {
#[inline]
fn from(v: $ty) -> Self {
AttributeValue::$variant(v.into())
}
}
};
(map: $ty:ty, $variant:ident, $arg:ident, $v:expr) => {
impl From<$ty> for AttributeValue {
#[inline]
fn from($arg: $ty) -> Self {
AttributeValue::$variant($v)
}
}
};
}
impl_from! { direct: bool, Bool }
impl_from! { direct: i16, I16 }
impl_from! { direct: i32, I32 }
impl_from! { direct: i64, I64 }
impl_from! { direct: f32, F32 }
impl_from! { direct: f64, F64 }
impl_from! { direct: Vec<bool>, ArrBool }
impl_from! { direct: Vec<i32>, ArrI32 }
impl_from! { direct: Vec<i64>, ArrI64 }
impl_from! { direct: Vec<f32>, ArrF32 }
impl_from! { direct: Vec<f64>, ArrF64 }
impl_from! { direct: Vec<u8>, Binary }
impl_from! { direct: String, String }
impl_from! { map: &[bool], ArrBool, v, v.to_owned() }
impl_from! { map: &[i32], ArrI32, v, v.to_owned() }
impl_from! { map: &[i64], ArrI64, v, v.to_owned() }
impl_from! { map: &[f32], ArrF32, v, v.to_owned() }
impl_from! { map: &[f64], ArrF64, v, v.to_owned() }
impl_from! { map: &[u8], Binary, v, v.to_owned() }
impl_from! { map: &str, String, v, v.to_owned() }