Coverage Report

Created: 2025-09-27 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/writeable-0.6.1/src/cmp.rs
Line
Count
Source
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
5
use crate::Writeable;
6
use core::cmp::Ordering;
7
use core::fmt;
8
9
struct WriteComparator<'a> {
10
    code_units: &'a [u8],
11
    result: Ordering,
12
}
13
14
/// This is an infallible impl. Functions always return Ok, not Err.
15
impl fmt::Write for WriteComparator<'_> {
16
    #[inline]
17
0
    fn write_str(&mut self, other: &str) -> fmt::Result {
18
0
        if self.result != Ordering::Equal {
19
0
            return Ok(());
20
0
        }
21
0
        let (this, remainder) = self
22
0
            .code_units
23
0
            .split_at_checked(other.len())
24
0
            .unwrap_or((self.code_units, &[]));
25
0
        self.code_units = remainder;
26
0
        self.result = this.cmp(other.as_bytes());
27
0
        Ok(())
28
0
    }
Unexecuted instantiation: <writeable::cmp::WriteComparator as core::fmt::Write>::write_str
Unexecuted instantiation: <writeable::cmp::WriteComparator as core::fmt::Write>::write_str
29
}
30
31
impl<'a> WriteComparator<'a> {
32
    #[inline]
33
0
    fn new(code_units: &'a [u8]) -> Self {
34
0
        Self {
35
0
            code_units,
36
0
            result: Ordering::Equal,
37
0
        }
38
0
    }
Unexecuted instantiation: <writeable::cmp::WriteComparator>::new
Unexecuted instantiation: <writeable::cmp::WriteComparator>::new
39
40
    #[inline]
41
0
    fn finish(self) -> Ordering {
42
0
        if matches!(self.result, Ordering::Equal) && !self.code_units.is_empty() {
43
            // Self is longer than Other
44
0
            Ordering::Greater
45
        } else {
46
0
            self.result
47
        }
48
0
    }
Unexecuted instantiation: <writeable::cmp::WriteComparator>::finish
Unexecuted instantiation: <writeable::cmp::WriteComparator>::finish
49
}
50
51
/// Compares the contents of a [`Writeable`] to the given UTF-8 bytes without allocating memory.
52
///
53
/// For more details, see: [`cmp_str`]
54
0
pub fn cmp_utf8(writeable: &impl Writeable, other: &[u8]) -> Ordering {
55
0
    let mut wc = WriteComparator::new(other);
56
0
    let _ = writeable.write_to(&mut wc);
57
0
    wc.finish().reverse()
58
0
}
Unexecuted instantiation: writeable::cmp::cmp_utf8::<icu_locale_core::data::DataLocale>
Unexecuted instantiation: writeable::cmp::cmp_utf8::<icu_locale_core::langid::LanguageIdentifier>
Unexecuted instantiation: writeable::cmp::cmp_utf8::<icu_locale_core::locale::Locale>
Unexecuted instantiation: writeable::cmp::cmp_utf8::<icu_locale_core::extensions::unicode::value::Value>
Unexecuted instantiation: writeable::cmp::cmp_utf8::<icu_locale_core::extensions::unicode::keywords::Keywords>
Unexecuted instantiation: writeable::cmp::cmp_utf8::<_>
59
60
/// Compares the contents of a `Writeable` to the given bytes
61
/// without allocating a String to hold the `Writeable` contents.
62
///
63
/// This returns a lexicographical comparison, the same as if the Writeable
64
/// were first converted to a String and then compared with `Ord`. For a
65
/// string ordering suitable for display to end users, use a localized
66
/// collation crate, such as `icu_collator`.
67
///
68
/// # Examples
69
///
70
/// ```
71
/// use core::cmp::Ordering;
72
/// use core::fmt;
73
/// use writeable::Writeable;
74
///
75
/// struct WelcomeMessage<'s> {
76
///     pub name: &'s str,
77
/// }
78
///
79
/// impl<'s> Writeable for WelcomeMessage<'s> {
80
///     // see impl in Writeable docs
81
/// #    fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result {
82
/// #        sink.write_str("Hello, ")?;
83
/// #        sink.write_str(self.name)?;
84
/// #        sink.write_char('!')?;
85
/// #        Ok(())
86
/// #    }
87
/// }
88
///
89
/// let message = WelcomeMessage { name: "Alice" };
90
/// let message_str = message.write_to_string();
91
///
92
/// assert_eq!(Ordering::Equal, writeable::cmp_str(&message, "Hello, Alice!"));
93
///
94
/// assert_eq!(Ordering::Greater, writeable::cmp_str(&message, "Alice!"));
95
/// assert_eq!(Ordering::Greater, (*message_str).cmp("Alice!"));
96
///
97
/// assert_eq!(Ordering::Less, writeable::cmp_str(&message, "Hello, Bob!"));
98
/// assert_eq!(Ordering::Less, (*message_str).cmp("Hello, Bob!"));
99
/// ```
100
#[inline]
101
0
pub fn cmp_str(writeable: &impl Writeable, other: &str) -> Ordering {
102
0
    cmp_utf8(writeable, other.as_bytes())
103
0
}
104
105
#[cfg(test)]
106
mod tests {
107
    use super::*;
108
    use core::fmt::Write;
109
110
    mod data {
111
        include!("../tests/data/data.rs");
112
    }
113
114
    #[test]
115
    fn test_write_char() {
116
        for a in data::KEBAB_CASE_STRINGS {
117
            for b in data::KEBAB_CASE_STRINGS {
118
                let mut wc = WriteComparator::new(a.as_bytes());
119
                for ch in b.chars() {
120
                    wc.write_char(ch).unwrap();
121
                }
122
                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
123
            }
124
        }
125
    }
126
127
    #[test]
128
    fn test_write_str() {
129
        for a in data::KEBAB_CASE_STRINGS {
130
            for b in data::KEBAB_CASE_STRINGS {
131
                let mut wc = WriteComparator::new(a.as_bytes());
132
                wc.write_str(b).unwrap();
133
                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
134
            }
135
        }
136
    }
137
138
    #[test]
139
    fn test_mixed() {
140
        for a in data::KEBAB_CASE_STRINGS {
141
            for b in data::KEBAB_CASE_STRINGS {
142
                let mut wc = WriteComparator::new(a.as_bytes());
143
                let mut first = true;
144
                for substr in b.split('-') {
145
                    if first {
146
                        first = false;
147
                    } else {
148
                        wc.write_char('-').unwrap();
149
                    }
150
                    wc.write_str(substr).unwrap();
151
                }
152
                assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}");
153
            }
154
        }
155
    }
156
}