writeable/
cmp.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5use core::cmp::Ordering;
6use core::fmt;
7
8pub(crate) struct WriteComparator<'a> {
9    string: &'a [u8],
10    result: Ordering,
11}
12
13/// This is an infallible impl. Functions always return Ok, not Err.
14impl<'a> fmt::Write for WriteComparator<'a> {
15    #[inline]
16    fn write_str(&mut self, other: &str) -> fmt::Result {
17        if self.result != Ordering::Equal {
18            return Ok(());
19        }
20        let cmp_len = core::cmp::min(other.len(), self.string.len());
21        let (this, remainder) = self.string.split_at(cmp_len);
22        self.string = remainder;
23        self.result = this.cmp(other.as_bytes());
24        Ok(())
25    }
26}
27
28impl<'a> WriteComparator<'a> {
29    #[inline]
30    pub fn new(string: &'a (impl AsRef<[u8]> + ?Sized)) -> Self {
31        Self {
32            string: string.as_ref(),
33            result: Ordering::Equal,
34        }
35    }
36
37    #[inline]
38    pub fn finish(self) -> Ordering {
39        if matches!(self.result, Ordering::Equal) && !self.string.is_empty() {
40            // Self is longer than Other
41            Ordering::Greater
42        } else {
43            self.result
44        }
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51    use core::fmt::Write;
52
53    mod data {
54        include!("../tests/data/data.rs");
55    }
56
57    #[test]
58    fn test_write_char() {
59        for a in data::KEBAB_CASE_STRINGS {
60            for b in data::KEBAB_CASE_STRINGS {
61                let mut wc = WriteComparator::new(a);
62                for ch in b.chars() {
63                    wc.write_char(ch).unwrap();
64                }
65                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
66            }
67        }
68    }
69
70    #[test]
71    fn test_write_str() {
72        for a in data::KEBAB_CASE_STRINGS {
73            for b in data::KEBAB_CASE_STRINGS {
74                let mut wc = WriteComparator::new(a);
75                wc.write_str(b).unwrap();
76                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
77            }
78        }
79    }
80
81    #[test]
82    fn test_mixed() {
83        for a in data::KEBAB_CASE_STRINGS {
84            for b in data::KEBAB_CASE_STRINGS {
85                let mut wc = WriteComparator::new(a);
86                let mut first = true;
87                for substr in b.split('-') {
88                    if first {
89                        first = false;
90                    } else {
91                        wc.write_char('-').unwrap();
92                    }
93                    wc.write_str(substr).unwrap();
94                }
95                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
96            }
97        }
98    }
99}