serde_hashkey/float/
ordered_float.rs

1use crate::error::Error;
2use crate::float::{FloatPolicy, FloatRepr};
3use crate::key::Key;
4use num_traits02 as nt02;
5use ordered_float3 as of3;
6use serde::{de, ser};
7use std::cmp;
8use std::fmt;
9use std::hash;
10
11/// An opaque floating-point representation which has a total ordering. This is
12/// used by [OrderedFloatPolicy].
13#[derive(Clone, Copy)]
14pub struct OrderedFloat<T>(pub T);
15
16impl<T> fmt::Debug for OrderedFloat<T>
17where
18    T: fmt::Debug,
19{
20    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
21        fmt::Debug::fmt(&self.0, fmt)
22    }
23}
24
25impl FloatRepr<f32> for OrderedFloat<f32> {
26    fn serialize(float: f32) -> Result<Self, Error> {
27        Ok(OrderedFloat(float))
28    }
29
30    fn visit<'de, V>(&self, visitor: V) -> Result<V::Value, Error>
31    where
32        V: de::Visitor<'de>,
33    {
34        visitor.visit_f32(self.0)
35    }
36}
37
38impl FloatRepr<f64> for OrderedFloat<f64> {
39    fn serialize(float: f64) -> Result<Self, Error> {
40        Ok(OrderedFloat(float))
41    }
42
43    fn visit<'de, V>(&self, visitor: V) -> Result<V::Value, Error>
44    where
45        V: de::Visitor<'de>,
46    {
47        visitor.visit_f64(self.0)
48    }
49}
50
51impl<T> serde::Serialize for OrderedFloat<T>
52where
53    T: serde::Serialize,
54{
55    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
56    where
57        S: serde::Serializer,
58    {
59        self.0.serialize(serializer)
60    }
61}
62
63impl<T> PartialEq for OrderedFloat<T>
64where
65    T: nt02::Float,
66{
67    fn eq(&self, other: &Self) -> bool {
68        of3::OrderedFloat(self.0) == of3::OrderedFloat(other.0)
69    }
70}
71
72impl<T> Eq for OrderedFloat<T> where T: nt02::Float {}
73
74impl<T> PartialOrd for OrderedFloat<T>
75where
76    T: nt02::Float,
77{
78    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
79        Some(of3::OrderedFloat(self.0).cmp(&of3::OrderedFloat(other.0)))
80    }
81}
82
83impl<T> cmp::Ord for OrderedFloat<T>
84where
85    T: nt02::Float,
86{
87    fn cmp(&self, other: &Self) -> cmp::Ordering {
88        of3::OrderedFloat(self.0).cmp(&of3::OrderedFloat(other.0))
89    }
90}
91
92impl<T> hash::Hash for OrderedFloat<T>
93where
94    T: nt02::Float,
95{
96    fn hash<H: hash::Hasher>(&self, state: &mut H) {
97        of3::OrderedFloat(self.0).hash(state)
98    }
99}
100
101/// A float serialization policy which delegates decisions to the
102/// `ordered-float` crate. This policy is used by the
103/// [to_key_with_ordered_float] function.
104///
105/// [Key]: crate::Key
106#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
107pub struct OrderedFloatPolicy(());
108
109impl FloatPolicy for OrderedFloatPolicy {
110    type F32 = OrderedFloat<f32>;
111    type F64 = OrderedFloat<f64>;
112}
113
114/// Serialize the given value to a [Key] using [OrderedFloatPolicy].
115///
116/// This policy is derived from the [`OrderedFloat` type] in the
117/// [`ordered-float` crate].
118///
119/// [`OrderedFloat` type]:
120///     https://docs.rs/ordered-float/2/ordered_float/struct.OrderedFloat.html
121/// [`ordered-float` crate]: https://docs.rs/ordered-float/2/ordered_float/
122///
123/// # Examples
124///
125/// ```
126/// use serde_derive::{Deserialize, Serialize};
127/// use serde_hashkey::{from_key, to_key_with_ordered_float, OrderedFloat, Key};
128/// use std::collections::HashMap;
129///
130/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
131/// struct Author {
132///     name: String,
133///     age: f32,
134/// }
135///
136/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
137/// struct Book {
138///     title: String,
139///     author: Author,
140/// }
141///
142/// # fn main() -> serde_hashkey::Result<()> {
143/// let book = Book {
144///     title: String::from("Birds of a feather"),
145///     author: Author {
146///         name: String::from("Noah"),
147///         age: 42.5,
148///     },
149/// };
150///
151/// let key = to_key_with_ordered_float(&book)?;
152/// let book2 = from_key(&key)?;
153///
154/// assert_eq!(book, book2);
155/// # Ok(())
156/// # }
157/// ```
158pub fn to_key_with_ordered_float<T>(value: &T) -> Result<Key<OrderedFloatPolicy>, Error>
159where
160    T: ser::Serialize,
161{
162    crate::ser::to_key_with_policy::<T, OrderedFloatPolicy>(value)
163}