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