weavatrix_graph/
attribute.rs1use serde::{Deserialize, Deserializer, Serialize, de::Error as _};
2use std::collections::BTreeMap;
3use std::hash::{Hash, Hasher};
4
5#[derive(Debug, Clone, Copy, Serialize)]
10pub struct FiniteF64(f64);
11
12impl FiniteF64 {
13 pub fn new(value: f64) -> Result<Self, String> {
19 if value.is_finite() {
20 Ok(Self(value))
21 } else {
22 Err(format!("float attribute must be finite: {value}"))
23 }
24 }
25
26 #[must_use]
27 pub const fn get(self) -> f64 {
28 self.0
29 }
30}
31
32impl PartialEq for FiniteF64 {
33 fn eq(&self, other: &Self) -> bool {
34 self.0.to_bits() == other.0.to_bits()
35 }
36}
37
38impl Eq for FiniteF64 {}
39
40impl PartialOrd for FiniteF64 {
41 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
42 Some(self.cmp(other))
43 }
44}
45
46impl Ord for FiniteF64 {
47 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
48 self.0.total_cmp(&other.0)
49 }
50}
51
52impl Hash for FiniteF64 {
53 fn hash<H: Hasher>(&self, state: &mut H) {
54 self.0.to_bits().hash(state);
55 }
56}
57
58impl<'de> Deserialize<'de> for FiniteF64 {
59 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
60 where
61 D: Deserializer<'de>,
62 {
63 Self::new(f64::deserialize(deserializer)?).map_err(D::Error::custom)
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
69#[serde(untagged)]
70#[non_exhaustive]
71pub enum AttributeValue {
72 Null,
73 Bool(bool),
74 Integer(i64),
75 Unsigned(u64),
76 Float(FiniteF64),
77 String(String),
78 List(Vec<AttributeValue>),
79 Object(BTreeMap<String, AttributeValue>),
80}
81
82impl From<bool> for AttributeValue {
83 fn from(value: bool) -> Self {
84 Self::Bool(value)
85 }
86}
87
88impl From<i64> for AttributeValue {
89 fn from(value: i64) -> Self {
90 Self::Integer(value)
91 }
92}
93
94impl From<u64> for AttributeValue {
95 fn from(value: u64) -> Self {
96 Self::Unsigned(value)
97 }
98}
99
100impl From<i32> for AttributeValue {
101 fn from(value: i32) -> Self {
102 Self::Integer(i64::from(value))
103 }
104}
105
106impl From<u32> for AttributeValue {
107 fn from(value: u32) -> Self {
108 Self::Unsigned(u64::from(value))
109 }
110}
111
112impl TryFrom<f64> for AttributeValue {
113 type Error = String;
114
115 fn try_from(value: f64) -> Result<Self, Self::Error> {
116 Ok(Self::Float(FiniteF64::new(value)?))
117 }
118}
119
120impl From<String> for AttributeValue {
121 fn from(value: String) -> Self {
122 Self::String(value)
123 }
124}
125
126impl From<&str> for AttributeValue {
127 fn from(value: &str) -> Self {
128 Self::String(value.to_owned())
129 }
130}
131
132impl From<Vec<AttributeValue>> for AttributeValue {
133 fn from(value: Vec<AttributeValue>) -> Self {
134 Self::List(value)
135 }
136}
137
138impl From<BTreeMap<String, AttributeValue>> for AttributeValue {
139 fn from(value: BTreeMap<String, AttributeValue>) -> Self {
140 Self::Object(value)
141 }
142}