1use core::cmp::Ordering;
6use core::fmt;
7
8pub(crate) struct WriteComparator<'a> {
9 string: &'a [u8],
10 result: Ordering,
11}
12
13impl<'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 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}