summaryrefslogtreecommitdiffstats
path: root/vendor/writeable/src/ops.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/writeable/src/ops.rs')
-rw-r--r--vendor/writeable/src/ops.rs291
1 files changed, 291 insertions, 0 deletions
diff --git a/vendor/writeable/src/ops.rs b/vendor/writeable/src/ops.rs
new file mode 100644
index 000000000..3ed4406d7
--- /dev/null
+++ b/vendor/writeable/src/ops.rs
@@ -0,0 +1,291 @@
+// 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<LengthHint> 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<LengthHint> for LengthHint {
+ fn add_assign(&mut self, other: Self) {
+ *self = *self + other;
+ }
+}
+
+impl core::iter::Sum<LengthHint> for LengthHint {
+ fn sum<I>(iter: I) -> Self
+ where
+ I: Iterator<Item = LengthHint>,
+ {
+ iter.fold(LengthHint::exact(0), core::ops::Add::add)
+ }
+}
+
+impl core::ops::Add<usize> 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<usize> for LengthHint {
+ fn add_assign(&mut self, other: usize) {
+ *self = *self + other;
+ }
+}
+
+impl core::ops::Mul<usize> 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<usize> for LengthHint {
+ fn mul_assign(&mut self, other: usize) {
+ *self = *self * other;
+ }
+}
+
+impl core::ops::BitOr<LengthHint> 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<W: fmt::Write + ?Sized>(&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<LengthHint> for LengthHint {
+ fn bitor_assign(&mut self, other: Self) {
+ *self = *self | other;
+ }
+}
+
+impl core::iter::Sum<usize> for LengthHint {
+ fn sum<I>(iter: I) -> Self
+ where
+ I: Iterator<Item = usize>,
+ {
+ LengthHint::exact(iter.sum::<usize>())
+ }
+}
+
+#[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 = vec![
+ LengthHint::exact(4),
+ LengthHint::exact(1),
+ LengthHint::exact(1),
+ ];
+ assert_eq!(
+ lens.iter().copied().sum::<LengthHint>(),
+ LengthHint::exact(6)
+ );
+
+ let lens = vec![
+ LengthHint::exact(4),
+ LengthHint::undefined(),
+ LengthHint::at_least(1),
+ ];
+ assert_eq!(
+ lens.iter().copied().sum::<LengthHint>(),
+ LengthHint::at_least(5)
+ );
+
+ let lens = vec![
+ LengthHint::exact(4),
+ LengthHint::undefined(),
+ LengthHint::at_most(1),
+ ];
+ assert_eq!(
+ lens.iter().copied().sum::<LengthHint>(),
+ LengthHint::at_least(4)
+ );
+
+ let lens = vec![4, 1, 1];
+ assert_eq!(
+ lens.iter().copied().sum::<LengthHint>(),
+ 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));
+ }
+}