import_stdlib!();
use super::varint::{EncodeVarInt, MajorType};
use crate::{CBOR, CBORCase, Error, Result, float::f64_cbor_data};
#[derive(Clone)]
pub enum Simple {
False,
True,
Null,
Float(f64),
}
impl Eq for Simple {
fn assert_receiver_is_total_eq(&self) {}
}
impl hash::Hash for Simple {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
match self {
Self::False => (0u8).hash(state),
Self::True => (1u8).hash(state),
Self::Null => (2u8).hash(state),
Self::Float(v) => v.to_bits().hash(state),
}
}
}
impl Simple {
pub fn name(&self) -> String { format!("{:?}", self) }
pub fn is_float(&self) -> bool { matches!(self, Self::Float(_)) }
pub fn is_nan(&self) -> bool {
matches!(self, Self::Float(v) if v.is_nan())
}
pub fn cbor_data(&self) -> Vec<u8> {
match self {
Self::False => (20u8).encode_varint(MajorType::Simple),
Self::True => (21u8).encode_varint(MajorType::Simple),
Self::Null => (22u8).encode_varint(MajorType::Simple),
Self::Float(v) => f64_cbor_data(*v),
}
}
}
impl From<Simple> for CBOR {
fn from(value: Simple) -> Self { CBORCase::Simple(value.clone()).into() }
}
impl TryFrom<CBOR> for Simple {
type Error = Error;
fn try_from(cbor: CBOR) -> Result<Self> {
match cbor.into_case() {
CBORCase::Simple(simple) => Ok(simple),
_ => Err(Error::WrongType),
}
}
}
impl PartialEq for Simple {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::False, Self::False) => true,
(Self::True, Self::True) => true,
(Self::Null, Self::Null) => true,
(Self::Float(v1), Self::Float(v2)) => {
v1 == v2 || (v1.is_nan() && v2.is_nan())
}
_ => false,
}
}
}
impl fmt::Debug for Simple {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::False => "false".to_owned(),
Self::True => "true".to_owned(),
Self::Null => "null".to_owned(),
Self::Float(v) => format!("{:?}", v),
};
f.write_str(&s)
}
}
impl fmt::Display for Simple {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::False => "false".to_owned(),
Self::True => "true".to_owned(),
Self::Null => "null".to_owned(),
Self::Float(v) => {
if v.is_nan() {
"NaN".to_owned()
} else if v.is_infinite() {
if v.is_sign_positive() {
"Infinity".to_owned()
} else {
"-Infinity".to_owned()
}
} else {
format!("{:?}", v)
}
}
};
f.write_str(&s)
}
}