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