/rust/registry/src/index.crates.io-1949cf8c6b5b557f/writeable-0.6.1/src/impls.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::*; |
6 | | use core::fmt; |
7 | | |
8 | | macro_rules! impl_write_num { |
9 | | ($u:ty, $i:ty, $test:ident) => { |
10 | | impl $crate::Writeable for $u { |
11 | 0 | fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result { |
12 | | const MAX_LEN: usize = <$u>::MAX.ilog10() as usize + 1; |
13 | 0 | let mut buf = [b'0'; MAX_LEN]; |
14 | 0 | let mut n = *self; |
15 | 0 | let mut i = MAX_LEN; |
16 | | #[allow(clippy::indexing_slicing)] // n < 10^i |
17 | 0 | while n != 0 { |
18 | 0 | i -= 1; |
19 | 0 | buf[i] = b'0' + (n % 10) as u8; |
20 | 0 | n /= 10; |
21 | 0 | } |
22 | 0 | if i == MAX_LEN { |
23 | 0 | debug_assert_eq!(*self, 0); |
24 | 0 | i -= 1; |
25 | 0 | } |
26 | | #[allow(clippy::indexing_slicing)] // buf is ASCII |
27 | 0 | let s = unsafe { core::str::from_utf8_unchecked(&buf[i..]) }; |
28 | 0 | sink.write_str(s) |
29 | 0 | } Unexecuted instantiation: <u8 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <u16 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <u32 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <u64 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <u128 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <usize as writeable::Writeable>::write_to::<_> |
30 | | |
31 | 0 | fn writeable_length_hint(&self) -> $crate::LengthHint { |
32 | 0 | LengthHint::exact(self.checked_ilog10().unwrap_or(0) as usize + 1) |
33 | 0 | } Unexecuted instantiation: <u8 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <u16 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <u32 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <u64 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <u128 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <usize as writeable::Writeable>::writeable_length_hint |
34 | | } |
35 | | |
36 | | impl $crate::Writeable for $i { |
37 | 0 | fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result { |
38 | 0 | if self.is_negative() { |
39 | 0 | sink.write_str("-")?; |
40 | 0 | } |
41 | 0 | self.unsigned_abs().write_to(sink) |
42 | 0 | } Unexecuted instantiation: <i8 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <i16 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <i32 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <i64 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <i128 as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <isize as writeable::Writeable>::write_to::<_> |
43 | | |
44 | 0 | fn writeable_length_hint(&self) -> $crate::LengthHint { |
45 | 0 | $crate::LengthHint::exact(if self.is_negative() { 1 } else { 0 }) |
46 | 0 | + self.unsigned_abs().writeable_length_hint() |
47 | 0 | } Unexecuted instantiation: <i8 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <i16 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <i32 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <i64 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <i128 as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <isize as writeable::Writeable>::writeable_length_hint |
48 | | } |
49 | | |
50 | | #[test] |
51 | | fn $test() { |
52 | | use $crate::assert_writeable_eq; |
53 | | assert_writeable_eq!(&(0 as $u), "0"); |
54 | | assert_writeable_eq!(&(0 as $i), "0"); |
55 | | assert_writeable_eq!(&(-0 as $i), "0"); |
56 | | assert_writeable_eq!(&(1 as $u), "1"); |
57 | | assert_writeable_eq!(&(1 as $i), "1"); |
58 | | assert_writeable_eq!(&(-1 as $i), "-1"); |
59 | | assert_writeable_eq!(&(9 as $u), "9"); |
60 | | assert_writeable_eq!(&(9 as $i), "9"); |
61 | | assert_writeable_eq!(&(-9 as $i), "-9"); |
62 | | assert_writeable_eq!(&(10 as $u), "10"); |
63 | | assert_writeable_eq!(&(10 as $i), "10"); |
64 | | assert_writeable_eq!(&(-10 as $i), "-10"); |
65 | | assert_writeable_eq!(&(99 as $u), "99"); |
66 | | assert_writeable_eq!(&(99 as $i), "99"); |
67 | | assert_writeable_eq!(&(-99 as $i), "-99"); |
68 | | assert_writeable_eq!(&(100 as $u), "100"); |
69 | | assert_writeable_eq!(&(-100 as $i), "-100"); |
70 | | assert_writeable_eq!(&<$u>::MAX, <$u>::MAX.to_string()); |
71 | | assert_writeable_eq!(&<$i>::MAX, <$i>::MAX.to_string()); |
72 | | assert_writeable_eq!(&<$i>::MIN, <$i>::MIN.to_string()); |
73 | | |
74 | | use rand::{rngs::SmallRng, Rng, SeedableRng}; |
75 | | let mut rng = SmallRng::seed_from_u64(4); // chosen by fair dice roll. |
76 | | // guaranteed to be random. |
77 | | for _ in 0..1000 { |
78 | | let rand = rng.gen::<$u>(); |
79 | | assert_writeable_eq!(rand, rand.to_string()); |
80 | | } |
81 | | } |
82 | | }; |
83 | | } |
84 | | |
85 | | impl_write_num!(u8, i8, test_u8); |
86 | | impl_write_num!(u16, i16, test_u16); |
87 | | impl_write_num!(u32, i32, test_u32); |
88 | | impl_write_num!(u64, i64, test_u64); |
89 | | impl_write_num!(u128, i128, test_u128); |
90 | | impl_write_num!(usize, isize, test_usize); |
91 | | |
92 | | impl Writeable for str { |
93 | | #[inline] |
94 | 0 | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
95 | 0 | sink.write_str(self) |
96 | 0 | } Unexecuted instantiation: <str as writeable::Writeable>::write_to::<zerotrie::cursor::ZeroTrieSimpleAsciiCursor> Unexecuted instantiation: <str as writeable::Writeable>::write_to::<_> |
97 | | |
98 | | #[inline] |
99 | 0 | fn writeable_length_hint(&self) -> LengthHint { |
100 | 0 | LengthHint::exact(self.len()) |
101 | 0 | } |
102 | | |
103 | | /// Returns a borrowed `str`. |
104 | | /// |
105 | | /// # Examples |
106 | | /// |
107 | | /// ``` |
108 | | /// use std::borrow::Cow; |
109 | | /// use writeable::Writeable; |
110 | | /// |
111 | | /// let cow = "foo".write_to_string(); |
112 | | /// assert!(matches!(cow, Cow::Borrowed(_))); |
113 | | /// ``` |
114 | | #[inline] |
115 | 0 | fn write_to_string(&self) -> Cow<str> { |
116 | 0 | Cow::Borrowed(self) |
117 | 0 | } |
118 | | } |
119 | | |
120 | | impl Writeable for String { |
121 | | #[inline] |
122 | 0 | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
123 | 0 | sink.write_str(self) |
124 | 0 | } |
125 | | |
126 | | #[inline] |
127 | 0 | fn writeable_length_hint(&self) -> LengthHint { |
128 | 0 | LengthHint::exact(self.len()) |
129 | 0 | } |
130 | | |
131 | | #[inline] |
132 | 0 | fn write_to_string(&self) -> Cow<str> { |
133 | 0 | Cow::Borrowed(self) |
134 | 0 | } |
135 | | } |
136 | | |
137 | | impl Writeable for char { |
138 | | #[inline] |
139 | 0 | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
140 | 0 | sink.write_char(*self) |
141 | 0 | } |
142 | | |
143 | | #[inline] |
144 | 0 | fn writeable_length_hint(&self) -> LengthHint { |
145 | 0 | LengthHint::exact(self.len_utf8()) |
146 | 0 | } |
147 | | |
148 | | #[inline] |
149 | 0 | fn write_to_string(&self) -> Cow<str> { |
150 | 0 | let mut s = String::with_capacity(self.len_utf8()); |
151 | 0 | s.push(*self); |
152 | 0 | Cow::Owned(s) |
153 | 0 | } |
154 | | } |
155 | | |
156 | | impl<T: Writeable + ?Sized> Writeable for &T { |
157 | | #[inline] |
158 | 0 | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
159 | 0 | (*self).write_to(sink) |
160 | 0 | } Unexecuted instantiation: <&icu_locale_core::data::DataLocale as writeable::Writeable>::write_to::<core::fmt::Formatter> Unexecuted instantiation: <&icu_locale_core::langid::LanguageIdentifier as writeable::Writeable>::write_to::<core::fmt::Formatter> Unexecuted instantiation: <&_ as writeable::Writeable>::write_to::<_> |
161 | | |
162 | | #[inline] |
163 | 0 | fn write_to_parts<W: PartsWrite + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
164 | 0 | (*self).write_to_parts(sink) |
165 | 0 | } |
166 | | |
167 | | #[inline] |
168 | 0 | fn writeable_length_hint(&self) -> LengthHint { |
169 | 0 | (*self).writeable_length_hint() |
170 | 0 | } |
171 | | |
172 | | #[inline] |
173 | 0 | fn write_to_string(&self) -> Cow<str> { |
174 | 0 | (*self).write_to_string() |
175 | 0 | } |
176 | | } |
177 | | |
178 | | macro_rules! impl_write_smart_pointer { |
179 | | ($ty:path, T: $extra_bound:path) => { |
180 | | impl<'a, T: ?Sized + Writeable + $extra_bound> Writeable for $ty { |
181 | | #[inline] |
182 | 0 | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
183 | 0 | core::borrow::Borrow::<T>::borrow(self).write_to(sink) |
184 | 0 | } Unexecuted instantiation: <alloc::borrow::Cow<_> as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <alloc::boxed::Box<_> as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <alloc::rc::Rc<_> as writeable::Writeable>::write_to::<_> Unexecuted instantiation: <alloc::sync::Arc<_> as writeable::Writeable>::write_to::<_> |
185 | | #[inline] |
186 | 0 | fn write_to_parts<W: PartsWrite + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
187 | 0 | core::borrow::Borrow::<T>::borrow(self).write_to_parts(sink) |
188 | 0 | } Unexecuted instantiation: <alloc::borrow::Cow<_> as writeable::Writeable>::write_to_parts::<_> Unexecuted instantiation: <alloc::boxed::Box<_> as writeable::Writeable>::write_to_parts::<_> Unexecuted instantiation: <alloc::rc::Rc<_> as writeable::Writeable>::write_to_parts::<_> Unexecuted instantiation: <alloc::sync::Arc<_> as writeable::Writeable>::write_to_parts::<_> |
189 | | #[inline] |
190 | 0 | fn writeable_length_hint(&self) -> LengthHint { |
191 | 0 | core::borrow::Borrow::<T>::borrow(self).writeable_length_hint() |
192 | 0 | } Unexecuted instantiation: <alloc::borrow::Cow<_> as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <alloc::boxed::Box<_> as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <alloc::rc::Rc<_> as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <alloc::sync::Arc<_> as writeable::Writeable>::writeable_length_hint |
193 | | #[inline] |
194 | 0 | fn write_to_string(&self) -> Cow<str> { |
195 | 0 | core::borrow::Borrow::<T>::borrow(self).write_to_string() |
196 | 0 | } Unexecuted instantiation: <alloc::borrow::Cow<_> as writeable::Writeable>::write_to_string Unexecuted instantiation: <alloc::boxed::Box<_> as writeable::Writeable>::write_to_string Unexecuted instantiation: <alloc::rc::Rc<_> as writeable::Writeable>::write_to_string Unexecuted instantiation: <alloc::sync::Arc<_> as writeable::Writeable>::write_to_string |
197 | | } |
198 | | }; |
199 | | ($ty:path) => { |
200 | | // Add a harmless duplicate Writeable bound |
201 | | impl_write_smart_pointer!($ty, T: Writeable); |
202 | | }; |
203 | | } |
204 | | |
205 | | impl_write_smart_pointer!(Cow<'a, T>, T: alloc::borrow::ToOwned); |
206 | | impl_write_smart_pointer!(alloc::boxed::Box<T>); |
207 | | impl_write_smart_pointer!(alloc::rc::Rc<T>); |
208 | | impl_write_smart_pointer!(alloc::sync::Arc<T>); |
209 | | |
210 | | #[test] |
211 | | fn test_string_impls() { |
212 | | fn check_writeable_slice<W: Writeable + core::fmt::Display>(writeables: &[W]) { |
213 | | assert_writeable_eq!(&writeables[0], ""); |
214 | | assert_writeable_eq!(&writeables[1], "abc"); |
215 | | assert!(matches!(writeables[0].write_to_string(), Cow::Borrowed(_))); |
216 | | assert!(matches!(writeables[1].write_to_string(), Cow::Borrowed(_))); |
217 | | } |
218 | | |
219 | | // test str impl |
220 | | let arr: &[&str] = &["", "abc"]; |
221 | | check_writeable_slice(arr); |
222 | | |
223 | | // test String impl |
224 | | let arr: &[String] = &[String::new(), "abc".to_owned()]; |
225 | | check_writeable_slice(arr); |
226 | | |
227 | | // test char impl |
228 | | let chars = ['a', 'β', '你', '😀']; |
229 | | for i in 0..chars.len() { |
230 | | let s = String::from(chars[i]); |
231 | | assert_writeable_eq!(&chars[i], s); |
232 | | for j in 0..chars.len() { |
233 | | assert_eq!( |
234 | | crate::cmp_str(&chars[j], &s), |
235 | | chars[j].cmp(&chars[i]), |
236 | | "{:?} vs {:?}", |
237 | | chars[j], |
238 | | chars[i] |
239 | | ); |
240 | | } |
241 | | } |
242 | | |
243 | | // test Cow impl |
244 | | let arr: &[Cow<str>] = &[Cow::Borrowed(""), Cow::Owned("abc".to_string())]; |
245 | | check_writeable_slice(arr); |
246 | | |
247 | | // test Box impl |
248 | | let arr: &[Box<str>] = &["".into(), "abc".into()]; |
249 | | check_writeable_slice(arr); |
250 | | |
251 | | // test Rc impl |
252 | | let arr: &[alloc::rc::Rc<str>] = &["".into(), "abc".into()]; |
253 | | check_writeable_slice(arr); |
254 | | |
255 | | // test Arc impl |
256 | | let arr: &[alloc::sync::Arc<str>] = &["".into(), "abc".into()]; |
257 | | check_writeable_slice(arr); |
258 | | |
259 | | // test &T impl |
260 | | let arr: &[&String] = &[&String::new(), &"abc".to_owned()]; |
261 | | check_writeable_slice(arr); |
262 | | } |