Skip to main content

hipstr/string/
cmp.rs

1//! Comparison trait implementations for `HipStr`
2
3use alloc::borrow::Cow;
4use alloc::boxed::Box;
5use alloc::string::String;
6
7use super::HipStr;
8use crate::macros::{symmetric_eq, symmetric_ord};
9use crate::Backend;
10
11// Equality
12
13impl<B> Eq for HipStr<'_, B> where B: Backend {}
14
15impl<B1, B2> PartialEq<HipStr<'_, B1>> for HipStr<'_, B2>
16where
17    B1: Backend,
18    B2: Backend,
19{
20    #[inline]
21    fn eq(&self, other: &HipStr<B1>) -> bool {
22        self.0 == other.0
23    }
24}
25
26#[inline]
27fn str_eq(a: impl AsRef<str>, b: impl AsRef<str>) -> bool {
28    a.as_ref() == b.as_ref()
29}
30
31symmetric_eq! {
32    [B] [where B: Backend] (str, HipStr<'_, B>) = str_eq;
33    [B] [where B: Backend] (&str, HipStr<'_, B>) = str_eq;
34    [B] [where B: Backend] (String, HipStr<'_, B>) = str_eq;
35    [B] [where B: Backend] (Box<str>, HipStr<'_, B>) = str_eq;
36    [B] [where B: Backend] (Cow<'_, str>, HipStr<'_, B>) = str_eq;
37}
38
39#[cfg(feature = "std")]
40#[inline]
41fn os_str_eq(a: impl AsRef<std::ffi::OsStr>, b: impl AsRef<str>) -> bool {
42    a.as_ref() == b.as_ref()
43}
44
45#[cfg(feature = "std")]
46symmetric_eq! {
47    [B] [where B: Backend] (std::ffi::OsStr, HipStr<'_, B>) = os_str_eq;
48    [B] [where B: Backend] (&std::ffi::OsStr, HipStr<'_, B>) = os_str_eq;
49    [B] [where B: Backend] (std::ffi::OsString, HipStr<'_, B>) = os_str_eq;
50    [B] [where B: Backend] (&std::ffi::OsString, HipStr<'_, B>) = os_str_eq;
51}
52
53// Order
54
55impl<B> Ord for HipStr<'_, B>
56where
57    B: Backend,
58{
59    #[inline]
60    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
61        self.as_str().cmp(other.as_str())
62    }
63}
64
65impl<B1, B2> PartialOrd<HipStr<'_, B1>> for HipStr<'_, B2>
66where
67    B1: Backend,
68    B2: Backend,
69{
70    #[inline]
71    fn partial_cmp(&self, other: &HipStr<'_, B1>) -> Option<core::cmp::Ordering> {
72        self.as_str().partial_cmp(other.as_str())
73    }
74}
75
76#[inline]
77fn str_cmp(a: impl AsRef<str>, b: impl AsRef<str>) -> Option<core::cmp::Ordering> {
78    a.as_ref().partial_cmp(b.as_ref())
79}
80
81symmetric_ord! {
82    [B] [where B: Backend] (str, HipStr<'_, B>) = str_cmp;
83    [B] [where B: Backend] (&str, HipStr<'_, B>) = str_cmp;
84    [B] [where B: Backend] (String, HipStr<'_, B>) = str_cmp;
85}
86
87#[cfg(feature = "std")]
88#[inline]
89fn os_str_cmp(a: impl AsRef<std::ffi::OsStr>, b: impl AsRef<str>) -> Option<core::cmp::Ordering> {
90    a.as_ref().partial_cmp(b.as_ref())
91}
92
93#[cfg(feature = "std")]
94symmetric_ord! {
95    [B] [where B: Backend] (std::ffi::OsStr, HipStr<'_, B>) = os_str_cmp;
96    [B] [where B: Backend] (&std::ffi::OsStr, HipStr<'_, B>) = os_str_cmp;
97    [B] [where B: Backend] (std::ffi::OsString, HipStr<'_, B>) = os_str_cmp;
98    [B] [where B: Backend] (&std::ffi::OsString, HipStr<'_, B>) = os_str_cmp;
99}
100
101#[cfg(test)]
102mod tests {
103    use alloc::borrow::Cow;
104    use alloc::boxed::Box;
105    use core::cmp::Ordering;
106
107    use crate::HipStr;
108
109    #[test]
110    fn test_eq() {
111        let string = "A".repeat(42);
112        let slice: &str = &string;
113        let b: Box<str> = Box::from(slice);
114        let c: Cow<str> = Cow::Borrowed(slice);
115        let h = HipStr::from(slice);
116        let h2 = HipStr::borrowed(slice);
117
118        assert_eq!(h, h);
119        assert_eq!(h2, h2);
120        assert_eq!(h, h2);
121        assert_ne!(h2, h2.slice(0..4));
122
123        assert_eq!(h, slice);
124        assert_eq!(slice, h);
125
126        assert_eq!(h, *slice);
127        assert_eq!(*slice, h);
128
129        assert_eq!(h, string);
130        assert_eq!(string, h);
131
132        assert_eq!(h, b);
133        assert_eq!(b, h);
134
135        assert_eq!(h, c);
136        assert_eq!(c, h);
137    }
138
139    #[test]
140    #[cfg(feature = "std")]
141    fn test_eq_os_str() {
142        let s = "abc";
143        let os: &std::ffi::OsStr = s.as_ref();
144        let h = HipStr::from(s);
145        assert_eq!(h, os);
146        assert_eq!(os, h);
147        assert_eq!(&h, os);
148        assert_eq!(os, &h);
149    }
150
151    #[test]
152    #[cfg(feature = "std")]
153    fn test_eq_os_string() {
154        let s = "abc";
155        let os: &std::ffi::OsStr = s.as_ref();
156        let oss = os.to_os_string();
157        let h = HipStr::from(s);
158        assert_eq!(h, oss);
159        assert_eq!(oss, h);
160    }
161
162    #[cfg(feature = "bstr")]
163    #[test]
164    fn test_eq_bstr() {
165        let s = "abc";
166        let b: &bstr::BStr = s.as_ref();
167        let h = HipStr::from(s);
168        assert_eq!(h, b);
169        assert_eq!(b, h);
170        assert_eq!(&h, b);
171        assert_eq!(b, &h);
172    }
173
174    #[cfg(feature = "bstr")]
175    #[test]
176    fn test_eq_bstring() {
177        let s = "abc";
178        let bs = bstr::BString::from(s);
179        let h = HipStr::from(s);
180        assert_eq!(h, bs);
181        assert_eq!(bs, h);
182    }
183
184    static BB_H: HipStr = HipStr::borrowed("bb");
185    static BC_H: HipStr = HipStr::borrowed("bc");
186
187    #[test]
188    fn test_cmp() {
189        assert_eq!(BB_H.partial_cmp(&BB_H), Some(Ordering::Equal));
190        assert_eq!(BB_H.cmp(&BB_H), Ordering::Equal);
191
192        assert!(BB_H < BC_H);
193        assert_eq!(BB_H.cmp(&BC_H), Ordering::Less);
194        assert_eq!(BB_H.partial_cmp(&BC_H), Some(Ordering::Less));
195        assert_eq!(BC_H.cmp(&BB_H), Ordering::Greater);
196        assert_eq!(BC_H.partial_cmp(&BB_H), Some(Ordering::Greater));
197    }
198
199    #[test]
200    fn test_cmp_str() {
201        assert!(&BB_H < "bc");
202        assert!(&BB_H > "ba");
203        assert!(&BB_H >= "bb");
204
205        assert!("bc" > &BB_H);
206        assert!("ba" < &BB_H);
207        assert!("bb" <= &BB_H);
208
209        assert!(BB_H < "bc");
210        assert!(BB_H > "ba");
211        assert!(BB_H >= "bb");
212
213        assert!("bc" > BB_H);
214        assert!("ba" < BB_H);
215        assert!("bb" <= BB_H);
216    }
217
218    #[test]
219    fn test_cmp_string() {
220        use alloc::string::String;
221
222        assert!(BB_H < String::from("bc"));
223        assert!(BB_H > String::from("ba"));
224        assert!(BB_H >= String::from("bb"));
225
226        assert!(String::from("bc") > BB_H);
227        assert!(String::from("ba") < BB_H);
228        assert!(String::from("bb") <= BB_H);
229    }
230
231    #[test]
232    #[cfg(feature = "std")]
233    fn test_cmp_os_str() {
234        use std::ffi::OsStr;
235
236        assert!(OsStr::new("bc") > &BB_H);
237        assert!(OsStr::new("ba") < &BB_H);
238        assert!(OsStr::new("bb") <= &BB_H);
239
240        assert!(&BB_H < OsStr::new("bc"));
241        assert!(&BB_H > OsStr::new("ba"));
242        assert!(&BB_H >= OsStr::new("bb"));
243
244        assert!(OsStr::new("bc") > BB_H);
245        assert!(OsStr::new("ba") < BB_H);
246        assert!(OsStr::new("bb") <= BB_H);
247
248        assert!(BB_H < OsStr::new("bc"));
249        assert!(BB_H > OsStr::new("ba"));
250        assert!(BB_H >= OsStr::new("bb"));
251    }
252
253    #[test]
254    #[cfg(feature = "std")]
255    fn test_cmp_os_string() {
256        use std::ffi::OsString;
257
258        assert!(OsString::from("bc") > BB_H);
259        assert!(OsString::from("ba") < BB_H);
260        assert!(OsString::from("bb") <= BB_H);
261
262        assert!(BB_H < OsString::from("bc"));
263        assert!(BB_H > OsString::from("ba"));
264        assert!(BB_H >= OsString::from("bb"));
265    }
266
267    #[cfg(feature = "bstr")]
268    #[test]
269    fn test_cmp_bstr() {
270        use bstr::BStr;
271
272        assert!(BStr::new("bc") > &BB_H);
273        assert!(BStr::new("ba") < &BB_H);
274        assert!(BStr::new("bb") <= &BB_H);
275
276        assert!(&BB_H < BStr::new("bc"));
277        assert!(&BB_H > BStr::new("ba"));
278        assert!(&BB_H >= BStr::new("bb"));
279
280        assert!(BStr::new("bc") > BB_H);
281        assert!(BStr::new("ba") < BB_H);
282        assert!(BStr::new("bb") <= BB_H);
283
284        assert!(BB_H < BStr::new("bc"));
285        assert!(BB_H > BStr::new("ba"));
286        assert!(BB_H >= BStr::new("bb"));
287    }
288
289    #[cfg(feature = "bstr")]
290    #[test]
291    fn test_cmp_bstring() {
292        use bstr::BString;
293
294        assert!(BString::from("bc") > BB_H);
295        assert!(BString::from("ba") < BB_H);
296        assert!(BString::from("bb") <= BB_H);
297
298        assert!(BB_H < BString::from("bc"));
299        assert!(BB_H > BString::from("ba"));
300        assert!(BB_H >= BString::from("bb"));
301    }
302}