|
| 1 | +//! This module contains traits that are simply delegated to the underlying [`NonEmptyString`]. |
| 2 | +//! |
| 3 | +//! The order of traits implemented here follow the same structure as defined in the standard library. |
| 4 | +//! When adding new ones, add them in the same order, so it's easy to keep track. |
| 5 | +//! |
| 6 | +//! The source at the moment of writing is [here](https://github.com/rust-lang/rust/blob/22d41ae90facbffdef9115809e8b6c1f71ebbf7c/library/alloc/src/string.rs#L2019). |
| 7 | +//! The link to master is [here](https://github.com/rust-lang/rust/blob/master/library/alloc/src/string.rs#L2019). |
| 8 | +//! |
| 9 | +
|
| 10 | +use crate::NonEmptyString; |
| 11 | +use std::borrow::Cow; |
| 12 | +use std::fmt::Display; |
| 13 | +use std::ops::{self, Add, AddAssign}; |
| 14 | + |
| 15 | +#[cfg(not(no_global_oom_handling))] |
| 16 | +impl Extend<char> for NonEmptyString { |
| 17 | + fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) { |
| 18 | + self.0.extend(iter) |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +#[cfg(not(no_global_oom_handling))] |
| 23 | +impl<'a> Extend<&'a char> for NonEmptyString { |
| 24 | + fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) { |
| 25 | + self.extend(iter.into_iter().cloned()); |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +#[cfg(not(no_global_oom_handling))] |
| 30 | +impl<'a> Extend<&'a str> for NonEmptyString { |
| 31 | + fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) { |
| 32 | + iter.into_iter().for_each(move |s| self.push_str(s)); |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | +#[cfg(not(no_global_oom_handling))] |
| 37 | +impl Extend<Box<str>> for NonEmptyString { |
| 38 | + fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) { |
| 39 | + iter.into_iter().for_each(move |s| self.push_str(&s)); |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +#[cfg(not(no_global_oom_handling))] |
| 44 | +impl Extend<String> for NonEmptyString { |
| 45 | + fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) { |
| 46 | + iter.into_iter().for_each(move |s| self.0.push_str(&s)); |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +#[cfg(not(no_global_oom_handling))] |
| 51 | +impl<'a> Extend<Cow<'a, str>> for NonEmptyString { |
| 52 | + fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) { |
| 53 | + iter.into_iter().for_each(move |s| self.push_str(&s)); |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +macro_rules! impl_eq { |
| 58 | + ($lhs:ty, $rhs: ty) => { |
| 59 | + #[allow(unused_lifetimes)] |
| 60 | + impl<'a, 'b> PartialEq<$rhs> for $lhs { |
| 61 | + #[inline] |
| 62 | + fn eq(&self, other: &$rhs) -> bool { |
| 63 | + PartialEq::eq(&self[..], &other[..]) |
| 64 | + } |
| 65 | + } |
| 66 | + |
| 67 | + #[allow(unused_lifetimes)] |
| 68 | + impl<'a, 'b> PartialEq<$lhs> for $rhs { |
| 69 | + #[inline] |
| 70 | + fn eq(&self, other: &$lhs) -> bool { |
| 71 | + PartialEq::eq(&self[..], &other[..]) |
| 72 | + } |
| 73 | + } |
| 74 | + }; |
| 75 | +} |
| 76 | + |
| 77 | +impl_eq! { NonEmptyString, str } |
| 78 | +impl_eq! { NonEmptyString, &'a str } |
| 79 | +#[cfg(not(no_global_oom_handling))] |
| 80 | +impl_eq! { Cow<'a, str>, NonEmptyString } |
| 81 | +#[cfg(not(no_global_oom_handling))] |
| 82 | +impl_eq! { String, NonEmptyString } |
| 83 | + |
| 84 | +// No sensible implementation for Default |
| 85 | +// impl Default for NonEmptyString { |
| 86 | +// } |
| 87 | + |
| 88 | +impl Display for NonEmptyString { |
| 89 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 90 | + Display::fmt(&self.0, f) |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +// Derived: |
| 95 | +// impl fmt::Debug for String { |
| 96 | +// } |
| 97 | + |
| 98 | +// Derived: |
| 99 | +// impl hash::Hash for NonEmptyString { |
| 100 | +// } |
| 101 | + |
| 102 | +#[cfg(not(no_global_oom_handling))] |
| 103 | +impl Add<&str> for NonEmptyString { |
| 104 | + type Output = NonEmptyString; |
| 105 | + |
| 106 | + #[inline] |
| 107 | + fn add(mut self, other: &str) -> NonEmptyString { |
| 108 | + self.push_str(other); |
| 109 | + self |
| 110 | + } |
| 111 | +} |
| 112 | + |
| 113 | +#[cfg(not(no_global_oom_handling))] |
| 114 | +impl AddAssign<&str> for NonEmptyString { |
| 115 | + #[inline] |
| 116 | + fn add_assign(&mut self, other: &str) { |
| 117 | + self.push_str(other); |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +macro_rules! index_impl { |
| 122 | + ($t:ty) => { |
| 123 | + impl ops::Index<$t> for NonEmptyString { |
| 124 | + type Output = str; |
| 125 | + |
| 126 | + #[inline] |
| 127 | + fn index(&self, index: $t) -> &str { |
| 128 | + <String as ops::Index<$t>>::index(&self.0, index) |
| 129 | + } |
| 130 | + } |
| 131 | + }; |
| 132 | +} |
| 133 | + |
| 134 | +index_impl!(ops::Range<usize>); |
| 135 | +index_impl!(ops::RangeTo<usize>); |
| 136 | +index_impl!(ops::RangeFrom<usize>); |
| 137 | +index_impl!(ops::RangeFull); |
| 138 | +index_impl!(ops::RangeInclusive<usize>); |
| 139 | +index_impl!(ops::RangeToInclusive<usize>); |
| 140 | + |
| 141 | +// Not 100% sure if index_mut allows turning a NonEmptyString into an empty string or not, let's leave it out until sure. |
| 142 | +// macro_rules! index_mut_impl { |
| 143 | +// ($t:ty) => { |
| 144 | +// impl ops::IndexMut<$t> for NonEmptyString { |
| 145 | +// #[inline] |
| 146 | +// fn index_mut(&mut self, index: $t) -> &mut str { |
| 147 | +// <String as ops::IndexMut<$t>>::index_mut(&mut self.0, index) |
| 148 | +// } |
| 149 | +// } |
| 150 | +// }; |
| 151 | +// } |
| 152 | + |
| 153 | +// index_mut_impl!(ops::Range<usize>); |
| 154 | +// index_mut_impl!(ops::RangeTo<usize>); |
| 155 | +// index_mut_impl!(ops::RangeFrom<usize>); |
| 156 | +// index_mut_impl!(ops::RangeFull); |
| 157 | +// index_mut_impl!(ops::RangeInclusive<usize>); |
| 158 | +// index_mut_impl!(ops::RangeToInclusive<usize>); |
| 159 | + |
| 160 | +// Point of discussion, see https://github.com/MidasLamb/non-empty-string/pull/11 |
| 161 | +// impl ops::Deref for NonEmptyString { |
| 162 | +// } |
| 163 | + |
| 164 | +// This would mean people could empty out the string, so no. |
| 165 | +// impl ops::DerefMut for NonEmptyString { |
| 166 | +// } |
| 167 | + |
| 168 | +#[cfg(not(no_global_oom_handling))] |
| 169 | +impl std::fmt::Write for NonEmptyString { |
| 170 | + #[inline] |
| 171 | + fn write_str(&mut self, s: &str) -> std::fmt::Result { |
| 172 | + self.push_str(s); |
| 173 | + Ok(()) |
| 174 | + } |
| 175 | + |
| 176 | + #[inline] |
| 177 | + fn write_char(&mut self, c: char) -> std::fmt::Result { |
| 178 | + self.push(c); |
| 179 | + Ok(()) |
| 180 | + } |
| 181 | +} |
0 commit comments