1use core::mem;
2
3use super::{Sealed, Util, Varint};
4
5macro_rules! const_assert {
6 ($($tt:tt)+) => {
7 const _: () = assert!($($tt)+);
8 };
9}
10
11pub trait Seq: Sealed {
13 fn encoded_len(&self) -> usize;
16}
17
18macro_rules! impl_slice_x8 {
19 ($name:ty) => {
20 impl Sealed for &[$name] {}
21 impl Seq for &[$name] {
22 fn encoded_len(&self) -> usize {
23 let mut sum = 0;
24 for x in *self {
25 sum += x.to_unsigned().encoded_len();
26 }
27 sum
28 }
29 }
30 };
31}
32impl_slice_x8!(u8);
33impl_slice_x8!(i8);
34
35macro_rules! impl_slice_x16 {
36 ($name:ty) => {
37 impl Sealed for &[$name] {}
38 impl Seq for &[$name] {
39 fn encoded_len(&self) -> usize {
40 let n = (self.len() / 32) * 32;
41 let mut sum = n;
42 let mut iter = self.iter();
43 for &x in (&mut iter).take(n) {
45 let x: u16 = x.to_unsigned();
46 if x > 0x7F {
47 sum += 1;
48 }
49 if x > 0x3FFF {
50 sum += 1;
51 }
52 }
53 for x in iter {
54 sum += x.encoded_len();
55 }
56 sum
57 }
58 }
59 };
60}
61impl_slice_x16!(u16);
62impl_slice_x16!(i16);
63
64macro_rules! impl_slice_x32 {
65 ($name:ty) => {
66 impl Sealed for &[$name] {}
67 impl Seq for &[$name] {
68 fn encoded_len(&self) -> usize {
69 let n = (self.len() / 32) * 32;
70 let mut sum = n;
71 let mut iter = self.iter();
72 for &x in (&mut iter).take(n) {
74 let x: u32 = x.to_unsigned();
75 if x > 0x7F {
76 sum += 1;
77 }
78 if x > 0x3FFF {
79 sum += 1;
80 }
81 if x > 0x1FFFFF {
82 sum += 1;
83 }
84 if x > 0xFFFFFFF {
85 sum += 1;
86 }
87 }
88 for x in iter {
89 sum += x.encoded_len();
90 }
91 sum
92 }
93 }
94 };
95}
96impl_slice_x32!(u32);
97impl_slice_x32!(i32);
98
99macro_rules! impl_slice_x64 {
100 ($name:ty) => {
101 impl Sealed for &[$name] {}
102 impl Seq for &[$name] {
103 fn encoded_len(&self) -> usize {
104 let n = (self.len() / 32) * 32;
105 let mut sum = n;
106 let mut iter = self.iter();
107 for &x in (&mut iter).take(n) {
109 let mut x: u64 = x.to_unsigned();
110 let tmp = if x > 1 << 35 { u64::MAX } else { 0 };
111 sum += (5 & tmp) as usize;
112 x >>= 35 & tmp;
113 if x > 0x7F {
114 sum += 1;
115 }
116 if x > 0x3FFF {
117 sum += 1;
118 }
119 if x > 0x1FFFFF {
120 sum += 1;
121 }
122 if x > 0xFFFFFFF {
123 sum += 1;
124 }
125 }
126 for x in iter {
127 sum += x.encoded_len();
128 }
129 sum
130 }
131 }
132 };
133}
134impl_slice_x64!(u64);
135impl_slice_x64!(i64);
136
137macro_rules! impl_slice_x128 {
138 ($name:ty) => {
139 impl Sealed for &[$name] {}
140 impl Seq for &[$name] {
141 fn encoded_len(&self) -> usize {
142 let mut sum = 0;
143 for x in *self {
144 sum += x.to_unsigned().encoded_len();
145 }
146 sum
147 }
148 }
149 };
150}
151impl_slice_x128!(u128);
152impl_slice_x128!(i128);
153
154unsafe trait Xsize {
159 type Alias;
160}
161const_assert!(mem::size_of::<usize>() == mem::size_of::<<usize as Xsize>::Alias>(),);
162const_assert!(mem::size_of::<isize>() == mem::size_of::<<isize as Xsize>::Alias>(),);
163
164macro_rules! xsize_impl {
165 ($cfg:literal, $unsigned:ty, $signed:ty) => {
166 #[cfg(target_pointer_width = $cfg)]
167 unsafe impl Xsize for usize {
170 type Alias = $unsigned;
171 }
172 #[cfg(target_pointer_width = $cfg)]
173 unsafe impl Xsize for isize {
176 type Alias = $signed;
177 }
178 };
179}
180xsize_impl!("64", u64, i64);
181xsize_impl!("32", u32, i32);
182xsize_impl!("16", u16, i16);
183
184macro_rules! impl_slice_xsize {
185 ($name:ty) => {
186 impl Sealed for &[$name] {}
187 impl Seq for &[$name] {
188 fn encoded_len(&self) -> usize {
189 let data =
190 unsafe { &*(*self as *const [$name] as *const [<$name as Xsize>::Alias]) };
193 data.encoded_len()
194 }
195 }
196 };
197}
198impl_slice_xsize!(usize);
199impl_slice_xsize!(isize);
200
201macro_rules! impl_vec {
202 ($($ty:ty),+ $(,)?) => {
203 $(
204 #[cfg(feature = "alloc")]
205 impl Sealed for ::alloc::vec::Vec<$ty> {}
206
207 #[cfg(feature = "alloc")]
208 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
209 impl Seq for ::alloc::vec::Vec<$ty> {
210 fn encoded_len(&self) -> usize {
211 self.as_slice().encoded_len()
212 }
213 }
214 )+
215 }
216}
217impl_vec! {
218 u8, u16, u32, u64, u128, usize,
219 i8, i16, i32, i64, i128, isize,
220}
221
222#[cfg(test)]
223mod tests {
224 use rand::prelude::*;
225
226 use super::*;
227
228 macro_rules! test_encoded_len {
229 ($name:ident, $ty:ty) => {
230 #[test]
231 fn $name() {
232 fn encoded_len(data: &[$ty]) -> usize {
233 let mut n = 0;
234 for x in data {
235 n += x.encoded_len();
236 }
237 n
238 }
239 let data = (0..100_000).map(|_| random()).collect::<Vec<$ty>>();
240 let got = data.encoded_len();
241 let want = encoded_len(&data);
242 assert_eq!(got, want);
243 }
244 };
245 }
246 test_encoded_len!(test_encoded_len_usize, usize);
247 test_encoded_len!(test_encoded_len_isize, isize);
248 test_encoded_len!(test_encoded_len_u64, u64);
249 test_encoded_len!(test_encoded_len_i64, i64);
250 test_encoded_len!(test_encoded_len_u32, u32);
251 test_encoded_len!(test_encoded_len_i32, i32);
252 test_encoded_len!(test_encoded_len_u16, u16);
253 test_encoded_len!(test_encoded_len_i16, i16);
254 test_encoded_len!(test_encoded_len_u8, u8);
255 test_encoded_len!(test_encoded_len_i8, i8);
256}