use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum FieldPresence {
Present(Value),
Null,
Absent,
}
impl FieldPresence {
#[must_use]
pub const fn is_present(&self) -> bool {
matches!(self, Self::Present(_))
}
#[must_use]
pub const fn is_absent(&self) -> bool {
matches!(self, Self::Absent)
}
#[must_use]
pub const fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
#[must_use]
pub const fn as_value(&self) -> Option<&Value> {
match self {
Self::Present(v) => Some(v),
Self::Null | Self::Absent => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Value {
Bool(bool),
Int(i64),
Float(f64),
Str(String),
Bytes(Vec<u8>),
CidLink(String),
Blob {
ref_: String,
mime: String,
size: u64,
},
Token(String),
Null,
Opaque {
type_: String,
fields: HashMap<String, Self>,
},
Unknown(HashMap<String, Self>),
}
impl Value {
#[must_use]
pub const fn type_name(&self) -> &'static str {
match self {
Self::Bool(_) => "bool",
Self::Int(_) => "int",
Self::Float(_) => "float",
Self::Str(_) => "str",
Self::Bytes(_) => "bytes",
Self::CidLink(_) => "cid-link",
Self::Blob { .. } => "blob",
Self::Token(_) => "token",
Self::Null => "null",
Self::Opaque { .. } => "opaque",
Self::Unknown(_) => "unknown",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn field_presence_predicates() {
let present = FieldPresence::Present(Value::Int(42));
assert!(present.is_present());
assert!(!present.is_null());
assert!(!present.is_absent());
let null = FieldPresence::Null;
assert!(null.is_null());
let absent = FieldPresence::Absent;
assert!(absent.is_absent());
}
#[test]
fn value_type_names() {
assert_eq!(Value::Bool(true).type_name(), "bool");
assert_eq!(Value::Str("hello".into()).type_name(), "str");
assert_eq!(Value::Null.type_name(), "null");
}
#[test]
fn field_presence_as_value() {
let present = FieldPresence::Present(Value::Int(42));
assert_eq!(present.as_value(), Some(&Value::Int(42)));
let null = FieldPresence::Null;
assert_eq!(null.as_value(), None);
}
}