// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use core::cmp::Ordering; use core::fmt; pub(crate) struct WriteComparator<'a> { string: &'a [u8], result: Ordering, } /// This is an infallible impl. Functions always return Ok, not Err. impl<'a> fmt::Write for WriteComparator<'a> { #[inline] fn write_str(&mut self, other: &str) -> fmt::Result { if self.result != Ordering::Equal { return Ok(()); } let cmp_len = core::cmp::min(other.len(), self.string.len()); let (this, remainder) = self.string.split_at(cmp_len); self.string = remainder; self.result = this.cmp(other.as_bytes()); Ok(()) } } impl<'a> WriteComparator<'a> { #[inline] pub fn new(string: &'a (impl AsRef<[u8]> + ?Sized)) -> Self { Self { string: string.as_ref(), result: Ordering::Equal, } } #[inline] pub fn finish(self) -> Ordering { if matches!(self.result, Ordering::Equal) && !self.string.is_empty() { // Self is longer than Other Ordering::Greater } else { self.result } } } #[cfg(test)] mod tests { use super::*; use core::fmt::Write; mod data { include!("../tests/data/data.rs"); } #[test] fn test_write_char() { for a in data::KEBAB_CASE_STRINGS { for b in data::KEBAB_CASE_STRINGS { let mut wc = WriteComparator::new(a); for ch in b.chars() { wc.write_char(ch).unwrap(); } assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}"); } } } #[test] fn test_write_str() { for a in data::KEBAB_CASE_STRINGS { for b in data::KEBAB_CASE_STRINGS { let mut wc = WriteComparator::new(a); wc.write_str(b).unwrap(); assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}"); } } } #[test] fn test_mixed() { for a in data::KEBAB_CASE_STRINGS { for b in data::KEBAB_CASE_STRINGS { let mut wc = WriteComparator::new(a); let mut first = true; for substr in b.split('-') { if first { first = false; } else { wc.write_char('-').unwrap(); } wc.write_str(substr).unwrap(); } assert_eq!(a.cmp(b), wc.finish(), "{a} <=> {b}"); } } } }