1use core::{
2 mem,
3 ops::{Add, Sub},
4};
5
6#[allow(clippy::len_without_is_empty)]
8pub trait Measure<Rhs: ?Sized = Self> {
9 type Len: Default + Add<Output = Self::Len> + Sub<Output = Self::Len> + PartialEq;
10
11 fn len(&self) -> Self::Len;
13
14 fn distance(&self, other: &Rhs) -> Self::Len;
16}
17
18impl Measure for char {
19 type Len = u64;
20
21 fn len(&self) -> u64 {
22 1
23 }
24
25 fn distance(&self, other: &char) -> u64 {
26 let mut a = *self as u64;
27 let mut b = *other as u64;
28
29 if a > b {
30 mem::swap(&mut a, &mut b);
31 }
32
33 if (..=0xd7ff).contains(&a) && (0xe000..).contains(&b) {
34 (b - 0xd000 + 1) + (0xd7ff - a)
35 } else {
36 b - a
37 }
38 }
39}
40
41macro_rules! impl_measure {
42 (@refl $ty:ty, $cast:ty, $len:ty) => {
47 impl_measure!($ty, $ty, $cast, $len);
48 };
49 (@both $ty1:ty, $ty2:ty, $cast:ty, $len:ty) => {
50 impl_measure!($ty1, $ty2, $cast, $len);
51 impl_measure!($ty2, $ty1, $cast, $len);
52 };
53 ($ty1:ty, $ty2:ty, $cast:ty, $len:ty) => {
54 impl Measure<$ty2> for $ty1 {
55 type Len = $len;
56
57 fn len(&self) -> $len {
58 1
59 }
60
61 fn distance(&self, other: &$ty2) -> $len {
62 let a = *self as $cast;
63 let b = *other as $cast;
64
65 if a > b {
66 (a - b) as $len
67 } else {
68 (b - a) as $len
69 }
70 }
71 }
72 };
73}
74
75impl_measure!(@refl u8, u8, u16);
78impl_measure!(@refl u16, u16, u32);
79impl_measure!(@refl u32, u32, u64);
80impl_measure!(@refl u64, u64, u128);
81impl_measure!(@refl i8, i16, u8);
82impl_measure!(@refl i16, i32, u16);
83impl_measure!(@refl i32, i64, u32);
84impl_measure!(@refl i64, i128, u64);
85impl_measure!(@both u8, u16, u16, u32);
86impl_measure!(@both u8, u32, u32, u64);
87impl_measure!(@both u8, u64, u64, u128);
88impl_measure!(@both u8, i8, i16, u16);
89impl_measure!(@both u8, i16, i32, u16);
90impl_measure!(@both u8, i32, i64, u32);
91impl_measure!(@both u8, i64, i128, u64);
92impl_measure!(@both u16, u32, u32, u64);
93impl_measure!(@both u16, u64, u64, u128);
94impl_measure!(@both u16, i8, i32, u32);
95impl_measure!(@both u16, i16, i32, u32);
96impl_measure!(@both u16, i32, i64, u32);
97impl_measure!(@both u16, i64, i128, u64);
98impl_measure!(@both u32, u64, u64, u128);
99impl_measure!(@both u32, i8, i64, u64);
100impl_measure!(@both u32, i16, i64, u64);
101impl_measure!(@both u32, i32, i64, u64);
102impl_measure!(@both u32, i64, i128, u64);
103impl_measure!(@both u64, i8, i128, u128);
104impl_measure!(@both u64, i16, i128, u128);
105impl_measure!(@both u64, i32, i128, u128);
106impl_measure!(@both u64, i64, i128, u128);
107impl_measure!(@both i8, i16, i32, u16);
108impl_measure!(@both i8, i32, i64, u32);
109impl_measure!(@both i8, i64, i128, u64);
110impl_measure!(@both i16, i32, i64, u32);
111impl_measure!(@both i16, i64, i128, u64);
112impl_measure!(@both i32, i64, i128, u64);
113#[cfg(target_pointer_width = "8")]
114impl_measure!(@refl usize, u8, u16);
115#[cfg(target_pointer_width = "8")]
116impl_measure!(@both usize, u8, u8, u16);
117#[cfg(target_pointer_width = "8")]
118impl_measure!(@both usize, u16, u16, u32);
119#[cfg(target_pointer_width = "8")]
120impl_measure!(@both usize, u32, u32, u64);
121#[cfg(target_pointer_width = "8")]
122impl_measure!(@both usize, u64, u64, u128);
123#[cfg(target_pointer_width = "8")]
124impl_measure!(@both usize, i8, i16, u16);
125#[cfg(target_pointer_width = "8")]
126impl_measure!(@both usize, i16, i32, u16);
127#[cfg(target_pointer_width = "8")]
128impl_measure!(@both usize, i32, i64, u32);
129#[cfg(target_pointer_width = "8")]
130impl_measure!(@both usize, i64, i128, u64);
131#[cfg(target_pointer_width = "16")]
132impl_measure!(@refl usize, u16, u32);
133#[cfg(target_pointer_width = "16")]
134impl_measure!(@both usize, u8, u16, u32);
135#[cfg(target_pointer_width = "16")]
136impl_measure!(@both usize, u16, u16, u32);
137#[cfg(target_pointer_width = "16")]
138impl_measure!(@both usize, u32, u32, u64);
139#[cfg(target_pointer_width = "16")]
140impl_measure!(@both usize, u64, u64, u128);
141#[cfg(target_pointer_width = "16")]
142impl_measure!(@both usize, i8, i32, u32);
143#[cfg(target_pointer_width = "16")]
144impl_measure!(@both usize, i16, i32, u32);
145#[cfg(target_pointer_width = "16")]
146impl_measure!(@both usize, i32, i64, u32);
147#[cfg(target_pointer_width = "16")]
148impl_measure!(@both usize, i64, i128, u64);
149#[cfg(target_pointer_width = "32")]
150impl_measure!(@refl usize, u32, u64);
151#[cfg(target_pointer_width = "32")]
152impl_measure!(@both usize, u8, u32, u64);
153#[cfg(target_pointer_width = "32")]
154impl_measure!(@both usize, u16, u32, u64);
155#[cfg(target_pointer_width = "32")]
156impl_measure!(@both usize, u32, u32, u64);
157#[cfg(target_pointer_width = "32")]
158impl_measure!(@both usize, u64, u64, u128);
159#[cfg(target_pointer_width = "32")]
160impl_measure!(@both usize, i8, i64, u64);
161#[cfg(target_pointer_width = "32")]
162impl_measure!(@both usize, i16, i64, u64);
163#[cfg(target_pointer_width = "32")]
164impl_measure!(@both usize, i32, i64, u64);
165#[cfg(target_pointer_width = "32")]
166impl_measure!(@both usize, i64, i128, u64);
167#[cfg(target_pointer_width = "64")]
168impl_measure!(@refl usize, u64, u128);
169#[cfg(target_pointer_width = "64")]
170impl_measure!(@both usize, u8, u64, u128);
171#[cfg(target_pointer_width = "64")]
172impl_measure!(@both usize, u16, u64, u128);
173#[cfg(target_pointer_width = "64")]
174impl_measure!(@both usize, u32, u64, u128);
175#[cfg(target_pointer_width = "64")]
176impl_measure!(@both usize, u64, u64, u128);
177#[cfg(target_pointer_width = "64")]
178impl_measure!(@both usize, i8, i128, u128);
179#[cfg(target_pointer_width = "64")]
180impl_measure!(@both usize, i16, i128, u128);
181#[cfg(target_pointer_width = "64")]
182impl_measure!(@both usize, i32, i128, u128);
183#[cfg(target_pointer_width = "64")]
184impl_measure!(@both usize, i64, i128, u128);
185
186macro_rules! impl_f_measure {
187 ($ty:ty, $zero:expr, $min:expr, $max:expr) => {
188 impl Measure<$ty> for $ty {
189 type Len = $ty;
190
191 fn len(&self) -> $ty {
192 $zero
193 }
194
195 fn distance(&self, other: &$ty) -> $ty {
196 if self.is_infinite() || other.is_infinite() {
197 $max
198 } else {
199 let a = *self as $ty;
200 let b = *other as $ty;
201
202 if a > b {
203 (a - b) as $ty
204 } else {
205 (b - a) as $ty
206 }
207 }
208 }
209 }
210 };
211}
212
213impl_f_measure!(f32, 0.0f32, f32::NEG_INFINITY, f32::INFINITY);
214impl_f_measure!(f64, 0.0f64, f64::NEG_INFINITY, f64::INFINITY);
215
216#[cfg(feature = "ordered-float")]
217mod ordered_float {
218 use super::Measure;
219 use ordered_float::NotNan;
220
221 impl_f_measure!(
222 NotNan<f32>,
223 unsafe { NotNan::new_unchecked(0.0f32) },
224 unsafe { NotNan::new_unchecked(f32::NEG_INFINITY) },
225 unsafe { NotNan::new_unchecked(f32::INFINITY) }
226 );
227
228 impl_f_measure!(
229 NotNan<f64>,
230 unsafe { NotNan::new_unchecked(0.0f64) },
231 unsafe { NotNan::new_unchecked(f64::NEG_INFINITY) },
232 unsafe { NotNan::new_unchecked(f64::INFINITY) }
233 );
234}