Skip to content

Commit 456c831

Browse files
authored
feat: implement Eq for Ipld (#17)
Implement the `Eq` trait for the `Ipld` enum. NaN floats are never equal to another. Though in the Ipld Data model they are forbidden. This means that we can implement `Eq` for it. As it's currently not strictly enforced that an `Ipld::Float` does not contain a NaN, we make at least sure that in case we would encounter it, that it is treated as equal. For more information about the dicussion about this topic, see ipld/libipld#171.
1 parent 612f1ec commit 456c831

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

src/ipld.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl fmt::Display for IndexError {
3434
impl std::error::Error for IndexError {}
3535

3636
/// Ipld
37-
#[derive(Clone, PartialEq)]
37+
#[derive(Clone)]
3838
pub enum Ipld {
3939
/// Represents the absence of a value or the value undefined.
4040
Null,
@@ -86,6 +86,31 @@ impl fmt::Debug for Ipld {
8686
}
8787
}
8888

89+
/// NaN floats are forbidden in the IPLD Data Model, but we do not enforce it. So in case such a
90+
/// value is introduced accidentally, make sure that it still compares as equal. This allows us
91+
/// to implement `Eq` for `Ipld`.
92+
impl PartialEq for Ipld {
93+
fn eq(&self, other: &Self) -> bool {
94+
match (self, other) {
95+
(Self::Null, Self::Null) => true,
96+
(Self::Bool(self_value), Self::Bool(other_value)) => self_value == other_value,
97+
(Self::Integer(self_value), Self::Integer(other_value)) => self_value == other_value,
98+
(Self::Float(self_value), Self::Float(other_value)) => {
99+
// Treat two NaNs as being equal.
100+
self_value == other_value || self_value.is_nan() && other_value.is_nan()
101+
}
102+
(Self::String(self_value), Self::String(other_value)) => self_value == other_value,
103+
(Self::Bytes(self_value), Self::Bytes(other_value)) => self_value == other_value,
104+
(Self::List(self_value), Self::List(other_value)) => self_value == other_value,
105+
(Self::Map(self_value), Self::Map(other_value)) => self_value == other_value,
106+
(Self::Link(self_value), Self::Link(other_value)) => self_value == other_value,
107+
_ => false,
108+
}
109+
}
110+
}
111+
112+
impl Eq for Ipld {}
113+
89114
/// IPLD Kind information without the actual value.
90115
///
91116
/// Sometimes it's useful to know the kind of an Ipld object without the actual value, e.g. for
@@ -363,4 +388,12 @@ mod tests {
363388
let ipld = Ipld::Map(map);
364389
assert_eq!(ipld.get("a").unwrap(), Some(&Ipld::Integer(0)));
365390
}
391+
392+
// NaN floats are forbidden in the IPLD Data Model, but still make sure they are treated as
393+
// equal in case they accidentally end up there.
394+
#[test]
395+
fn test_partial_eq_nan() {
396+
let invalid_ipld = Ipld::Float(f64::NAN);
397+
assert_eq!(invalid_ipld, invalid_ipld);
398+
}
366399
}

0 commit comments

Comments
 (0)