// 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 crate::LengthHint; impl core::ops::Add for LengthHint { type Output = Self; fn add(self, other: LengthHint) -> Self { LengthHint( self.0.saturating_add(other.0), match (self.1, other.1) { (Some(c), Some(d)) => c.checked_add(d), _ => None, }, ) } } impl core::ops::AddAssign for LengthHint { fn add_assign(&mut self, other: Self) { *self = *self + other; } } impl core::iter::Sum for LengthHint { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(LengthHint::exact(0), core::ops::Add::add) } } impl core::ops::Add for LengthHint { type Output = Self; fn add(self, other: usize) -> Self { Self( self.0.saturating_add(other), self.1.and_then(|upper| upper.checked_add(other)), ) } } impl core::ops::AddAssign for LengthHint { fn add_assign(&mut self, other: usize) { *self = *self + other; } } impl core::ops::Mul for LengthHint { type Output = Self; fn mul(self, other: usize) -> Self { Self( self.0.saturating_mul(other), self.1.and_then(|upper| upper.checked_mul(other)), ) } } impl core::ops::MulAssign for LengthHint { fn mul_assign(&mut self, other: usize) { *self = *self * other; } } impl core::ops::BitOr for LengthHint { type Output = Self; /// Returns a new hint that is correct wherever `self` is correct, and wherever /// `other` is correct. /// /// Example: /// ``` /// # use writeable::{LengthHint, Writeable}; /// # use core::fmt; /// # fn coin_flip() -> bool { true } /// /// struct NonDeterministicWriteable(String, String); /// /// impl Writeable for NonDeterministicWriteable { /// fn write_to( /// &self, /// sink: &mut W, /// ) -> fmt::Result { /// sink.write_str(if coin_flip() { &self.0 } else { &self.1 }) /// } /// /// fn writeable_length_hint(&self) -> LengthHint { /// LengthHint::exact(self.0.len()) | LengthHint::exact(self.1.len()) /// } /// } /// /// writeable::impl_display_with_writeable!(NonDeterministicWriteable); /// ``` fn bitor(self, other: LengthHint) -> Self { LengthHint( Ord::min(self.0, other.0), match (self.1, other.1) { (Some(c), Some(d)) => Some(Ord::max(c, d)), _ => None, }, ) } } impl core::ops::BitOrAssign for LengthHint { fn bitor_assign(&mut self, other: Self) { *self = *self | other; } } impl core::iter::Sum for LengthHint { fn sum(iter: I) -> Self where I: Iterator, { LengthHint::exact(iter.sum::()) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_add() { assert_eq!(LengthHint::exact(3) + 2, LengthHint::exact(5)); assert_eq!( LengthHint::exact(3) + LengthHint::exact(2), LengthHint::exact(5) ); assert_eq!( LengthHint::exact(3) + LengthHint::undefined(), LengthHint::at_least(3) ); assert_eq!(LengthHint::undefined() + 2, LengthHint::at_least(2)); assert_eq!( LengthHint::undefined() + LengthHint::exact(2), LengthHint::at_least(2) ); assert_eq!( LengthHint::undefined() + LengthHint::undefined(), LengthHint::undefined() ); assert_eq!( LengthHint::at_least(15) + LengthHint::exact(3), LengthHint::at_least(18) ); assert_eq!( LengthHint::at_least(15) + LengthHint::at_most(3), LengthHint::at_least(15) ); assert_eq!(LengthHint::between(48, 92) + 5, LengthHint::between(53, 97)); let mut len = LengthHint::exact(5); len += LengthHint::exact(3); assert_eq!(len, LengthHint::exact(8)); len += 2; assert_eq!(len, LengthHint::exact(10)); len += LengthHint::undefined(); assert_eq!(len, LengthHint::at_least(10)); len += LengthHint::exact(3); assert_eq!(len, LengthHint::at_least(13)); len += 2; assert_eq!(len, LengthHint::at_least(15)); len += LengthHint::undefined(); assert_eq!(len, LengthHint::at_least(15)); assert_eq!( LengthHint::between(usize::MAX - 10, usize::MAX - 5) + LengthHint::exact(20), LengthHint::at_least(usize::MAX) ); } #[test] fn test_sum() { let lens = [ LengthHint::exact(4), LengthHint::exact(1), LengthHint::exact(1), ]; assert_eq!( lens.iter().copied().sum::(), LengthHint::exact(6) ); let lens = [ LengthHint::exact(4), LengthHint::undefined(), LengthHint::at_least(1), ]; assert_eq!( lens.iter().copied().sum::(), LengthHint::at_least(5) ); let lens = [ LengthHint::exact(4), LengthHint::undefined(), LengthHint::at_most(1), ]; assert_eq!( lens.iter().copied().sum::(), LengthHint::at_least(4) ); let lens = [4, 1, 1]; assert_eq!( lens.iter().copied().sum::(), LengthHint::exact(6) ); } #[test] fn test_mul() { assert_eq!(LengthHint::exact(3) * 2, LengthHint::exact(6)); assert_eq!(LengthHint::undefined() * 2, LengthHint::undefined()); assert_eq!( LengthHint::between(48, 92) * 2, LengthHint::between(96, 184) ); let mut len = LengthHint::exact(5); len *= 2; assert_eq!(len, LengthHint::exact(10)); assert_eq!( LengthHint::between(usize::MAX - 10, usize::MAX - 5) * 2, LengthHint::at_least(usize::MAX) ); } #[test] fn test_bitor() { assert_eq!( LengthHint::exact(3) | LengthHint::exact(2), LengthHint::between(2, 3) ); assert_eq!( LengthHint::exact(3) | LengthHint::undefined(), LengthHint::undefined() ); assert_eq!( LengthHint::undefined() | LengthHint::undefined(), LengthHint::undefined() ); assert_eq!( LengthHint::exact(10) | LengthHint::exact(10), LengthHint::exact(10) ); assert_eq!( LengthHint::at_least(15) | LengthHint::exact(3), LengthHint::at_least(3) ); assert_eq!( LengthHint::at_least(15) | LengthHint::at_most(18), LengthHint::undefined() ); assert_eq!( LengthHint::at_least(15) | LengthHint::at_least(18), LengthHint::at_least(15) ); assert_eq!( LengthHint::at_most(15) | LengthHint::at_most(18), LengthHint::at_most(18) ); assert_eq!( LengthHint::between(5, 10) | LengthHint::at_most(3), LengthHint::at_most(10) ); let mut len = LengthHint::exact(5); len |= LengthHint::exact(3); assert_eq!(len, LengthHint::between(5, 3)); } }