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