/rust/registry/src/index.crates.io-1949cf8c6b5b557f/writeable-0.6.4/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::<icu_provider::baked::zerotrie::EarlyExitCursor> 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 | } Unexecuted instantiation: <str as writeable::Writeable>::writeable_length_hint Unexecuted instantiation: <str as writeable::Writeable>::writeable_length_hint |
108 | | |
109 | | #[inline] |
110 | 0 | fn writeable_borrow(&self) -> Option<&str> { |
111 | 0 | Some(self) |
112 | 0 | } |
113 | | } |
114 | | |
115 | | #[cfg(feature = "alloc")] |
116 | | crate::impl_writeable_delegate!(String, |&self| self.as_str()); |
117 | | |
118 | | impl Writeable for char { |
119 | | #[inline] |
120 | 0 | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
121 | 0 | sink.write_char(*self) |
122 | 0 | } |
123 | | |
124 | | #[inline] |
125 | 0 | fn writeable_length_hint(&self) -> LengthHint { |
126 | 0 | LengthHint::exact(self.len_utf8()) |
127 | 0 | } |
128 | | |
129 | | #[inline] |
130 | | #[cfg(feature = "alloc")] |
131 | | fn write_to_string(&self) -> Cow<'_, str> { |
132 | | let mut s = String::with_capacity(self.len_utf8()); |
133 | | s.push(*self); |
134 | | Cow::Owned(s) |
135 | | } |
136 | | } |
137 | | |
138 | | crate::impl_writeable_delegate!(&T, |&self| *self, #[cfg(feature = "alloc")] fn write_to_string, where T: Writeable + ?Sized); |
139 | | |
140 | | #[cfg(feature = "alloc")] |
141 | | macro_rules! impl_write_smart_pointer { |
142 | | ($ty:path, T: $extra_bound:path) => { |
143 | | #[allow(unused_qualifications)] |
144 | | impl<T: ?Sized + Writeable + $extra_bound> Writeable for $ty { |
145 | | #[inline] |
146 | | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
147 | | core::borrow::Borrow::<T>::borrow(self).write_to(sink) |
148 | | } |
149 | | #[inline] |
150 | | fn write_to_parts<W: PartsWrite + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
151 | | core::borrow::Borrow::<T>::borrow(self).write_to_parts(sink) |
152 | | } |
153 | | #[inline] |
154 | | fn writeable_length_hint(&self) -> LengthHint { |
155 | | core::borrow::Borrow::<T>::borrow(self).writeable_length_hint() |
156 | | } |
157 | | #[inline] |
158 | | fn writeable_borrow(&self) -> Option<&str> { |
159 | | core::borrow::Borrow::<T>::borrow(self).writeable_borrow() |
160 | | } |
161 | | #[inline] |
162 | | fn write_to_string(&self) -> Cow<'_, str> { |
163 | | core::borrow::Borrow::<T>::borrow(self).write_to_string() |
164 | | } |
165 | | } |
166 | | }; |
167 | | ($ty:path) => { |
168 | | // Add a harmless duplicate Writeable bound |
169 | | impl_write_smart_pointer!($ty, T: Writeable); |
170 | | }; |
171 | | } |
172 | | |
173 | | #[cfg(feature = "alloc")] |
174 | | impl_write_smart_pointer!(Cow<'_, T>, T: alloc::borrow::ToOwned); |
175 | | #[cfg(feature = "alloc")] |
176 | | impl_write_smart_pointer!(alloc::boxed::Box<T>); |
177 | | #[cfg(feature = "alloc")] |
178 | | impl_write_smart_pointer!(alloc::rc::Rc<T>); |
179 | | #[cfg(feature = "alloc")] |
180 | | impl_write_smart_pointer!(alloc::sync::Arc<T>); |
181 | | |
182 | | #[test] |
183 | | fn test_string_impls() { |
184 | | fn check_writeable_slice<W: Writeable + core::fmt::Display>(writeables: &[W]) { |
185 | | assert_writeable_eq!(&writeables[0], ""); |
186 | | assert_writeable_eq!(&writeables[1], "abc"); |
187 | | assert!(matches!(writeables[0].write_to_string(), Cow::Borrowed(_))); |
188 | | assert!(matches!(writeables[1].write_to_string(), Cow::Borrowed(_))); |
189 | | } |
190 | | |
191 | | // test str impl |
192 | | let arr: &[&str] = &["", "abc"]; |
193 | | check_writeable_slice(arr); |
194 | | |
195 | | // test String impl |
196 | | let arr: &[String] = &[String::new(), "abc".to_owned()]; |
197 | | check_writeable_slice(arr); |
198 | | |
199 | | // test char impl |
200 | | let chars = ['a', 'β', '你', '😀']; |
201 | | for i in 0..chars.len() { |
202 | | let s = String::from(chars[i]); |
203 | | assert_writeable_eq!(&chars[i], s); |
204 | | for j in 0..chars.len() { |
205 | | assert_eq!( |
206 | | cmp_str(&chars[j], &s), |
207 | | chars[j].cmp(&chars[i]), |
208 | | "{:?} vs {:?}", |
209 | | chars[j], |
210 | | chars[i] |
211 | | ); |
212 | | } |
213 | | } |
214 | | |
215 | | // test Cow impl |
216 | | let arr: &[Cow<str>] = &[Cow::Borrowed(""), Cow::Owned("abc".to_string())]; |
217 | | check_writeable_slice(arr); |
218 | | |
219 | | // test Box impl |
220 | | let arr: &[Box<str>] = &["".into(), "abc".into()]; |
221 | | check_writeable_slice(arr); |
222 | | |
223 | | // test Rc impl |
224 | | let arr: &[alloc::rc::Rc<str>] = &["".into(), "abc".into()]; |
225 | | check_writeable_slice(arr); |
226 | | |
227 | | // test Arc impl |
228 | | let arr: &[alloc::sync::Arc<str>] = &["".into(), "abc".into()]; |
229 | | check_writeable_slice(arr); |
230 | | |
231 | | // test &T impl |
232 | | let arr: &[&String] = &[&String::new(), &"abc".to_owned()]; |
233 | | check_writeable_slice(arr); |
234 | | } |