1use crate::{ParseError, Uint};
2use core::{
3 ops::{
4 BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Index, Not, Shl, ShlAssign,
5 Shr, ShrAssign,
6 },
7 str::FromStr,
8};
9
10#[cfg(feature = "alloc")]
11#[allow(unused_imports)]
12use alloc::{borrow::Cow, vec::Vec};
13
14#[derive(Clone, Copy, Default, Eq, PartialEq, Hash)]
17#[cfg_attr(feature = "alloc", derive(Debug))]
18pub struct Bits<const BITS: usize, const LIMBS: usize>(Uint<BITS, LIMBS>);
19
20impl<const BITS: usize, const LIMBS: usize> From<Uint<BITS, LIMBS>> for Bits<BITS, LIMBS> {
21 #[inline]
22 fn from(value: Uint<BITS, LIMBS>) -> Self {
23 Self(value)
24 }
25}
26
27impl<const BITS: usize, const LIMBS: usize> From<Bits<BITS, LIMBS>> for Uint<BITS, LIMBS> {
28 #[inline]
29 fn from(value: Bits<BITS, LIMBS>) -> Self {
30 value.0
31 }
32}
33
34impl<const BITS: usize, const LIMBS: usize> FromStr for Bits<BITS, LIMBS> {
35 type Err = <Uint<BITS, LIMBS> as FromStr>::Err;
36
37 #[inline]
38 fn from_str(src: &str) -> Result<Self, Self::Err> {
39 src.parse().map(Self)
40 }
41}
42
43impl<const BITS: usize, const LIMBS: usize> Bits<BITS, LIMBS> {
44 pub const LIMBS: usize = Uint::<BITS, LIMBS>::LIMBS;
46
47 pub const BITS: usize = Uint::<BITS, LIMBS>::BITS;
49
50 pub const BYTES: usize = Uint::<BITS, LIMBS>::BYTES;
52
53 pub const ZERO: Self = Self(Uint::<BITS, LIMBS>::ZERO);
56
57 #[must_use]
59 #[inline(always)]
60 pub const fn into_inner(self) -> Uint<BITS, LIMBS> {
61 self.0
62 }
63
64 #[must_use]
66 #[inline(always)]
67 pub const fn as_uint(&self) -> &Uint<BITS, LIMBS> {
68 &self.0
69 }
70
71 #[must_use]
73 #[inline(always)]
74 pub fn as_uint_mut(&mut self) -> &mut Uint<BITS, LIMBS> {
75 &mut self.0
76 }
77}
78
79macro_rules! forward_attributes {
80 ($fnname:ident, $item:item $(,must_use: true)?) => {
81 #[doc = concat!("See [`Uint::", stringify!($fnname),"`] for documentation.")]
82 #[inline(always)]
83 #[must_use]
84 $item
85 };
86 ($fnname:ident, $item:item,must_use: false) => {
87 #[doc = concat!("See [`Uint::", stringify!($fnname),"`] for documentation.")]
88 #[inline(always)]
89 $item
90 };
91}
92
93macro_rules! forward {
96 ($(fn $fnname:ident(self) -> $res:ty;)*) => {
97 $(
98 forward_attributes!(
99 $fnname,
100 pub fn $fnname(self) -> $res {
101 Uint::$fnname(self.0).into()
102 }
103 );
104 )*
105 };
106 ($(fn $fnname:ident$(<$(const $generic_arg:ident: $generic_ty:ty),+>)?(&self) -> $res:ty;)*) => {
107 $(
108 forward_attributes!(
109 $fnname,
110 pub fn $fnname$(<$(const $generic_arg: $generic_ty),+>)?(&self) -> $res {
111 Uint::$fnname(&self.0).into()
112 }
113 );
114 )*
115 };
116 ($(unsafe fn $fnname:ident(&mut self) -> $res:ty;)*) => {
117 $(
118 forward_attributes!(
119 $fnname,
120 pub unsafe fn $fnname(&mut self) -> $res {
121 Uint::$fnname(&mut self.0).into()
122 }
123 );
124 )*
125 };
126 ($(fn $fnname:ident(self, $arg:ident: $arg_ty:ty) -> Option<Self>;)*) => {
127 $(
128 forward_attributes!(
129 $fnname,
130 pub fn $fnname(self, $arg: $arg_ty) -> Option<Self> {
131 Uint::$fnname(self.0, $arg).map(Bits::from)
132 }
133 );
134 )*
135 };
136 ($(fn $fnname:ident(self, $arg:ident: $arg_ty:ty) -> (Self, bool);)*) => {
137 $(
138 forward_attributes!(
139 $fnname,
140 pub fn $fnname(self, $arg: $arg_ty) -> (Self, bool) {
141 let (value, flag) = Uint::$fnname(self.0, $arg);
142 (value.into(), flag)
143 }
144 );
145 )*
146 };
147 ($(fn $fnname:ident(self, $arg:ident: $arg_ty:ty) -> $res:ty;)*) => {
148 $(
149 forward_attributes!(
150 $fnname,
151 pub fn $fnname(self, $arg: $arg_ty) -> $res {
152 Uint::$fnname(self.0, $arg).into()
153 }
154 );
155 )*
156 };
157 ($(fn $fnname:ident$(<$(const $generic_arg:ident: $generic_ty:ty),+>)?($($arg:ident: $arg_ty:ty),+) -> Option<Self>;)*) => {
158 $(
159 forward_attributes!(
160 $fnname,
161 pub fn $fnname$(<$(const $generic_arg: $generic_ty),+>)?($($arg: $arg_ty),+) -> Option<Self> {
162 Uint::$fnname($($arg),+).map(Bits::from)
163 }
164 );
165 )*
166 };
167 ($(fn $fnname:ident$(<$(const $generic_arg:ident: $generic_ty:ty),+>)?($($arg:ident: $arg_ty:ty),+) -> Result<Self, $err_ty:ty>;)*) => {
168 $(
169 forward_attributes!(
170 $fnname,
171 pub fn $fnname$(<$(const $generic_arg: $generic_ty),+>)?($($arg: $arg_ty),+) -> Result<Self, $err_ty> {
172 Uint::$fnname($($arg),+).map(Bits::from)
173 },
174 must_use: false
175 );
176 )*
177 };
178 ($(fn $fnname:ident$(<$(const $generic_arg:ident: $generic_ty:ty),+>)?($($arg:ident: $arg_ty:ty),+) -> $res:ty;)*) => {
179 $(
180 forward_attributes!(
181 $fnname,
182 pub fn $fnname$(<$(const $generic_arg: $generic_ty),+>)?($($arg: $arg_ty),+) -> $res {
183 Uint::$fnname($($arg),+).into()
184 }
185 );
186 )*
187 };
188 ($(const fn $fnname:ident$(<$(const $generic_arg:ident: $generic_ty:ty),+>)?($($arg:ident: $arg_ty:ty),+) -> Self;)*) => {
189 $(
190 forward_attributes!(
191 $fnname,
192 pub const fn $fnname$(<$(const $generic_arg: $generic_ty),+>)?($($arg: $arg_ty),+) -> Self {
193 Bits(Uint::$fnname($($arg),+))
194 }
195 );
196 )*
197 };
198 ($(const fn $fnname:ident$(<$(const $generic_arg:ident: $generic_ty:ty),+>)?(&self) -> $res_ty:ty;)*) => {
199 $(
200 forward_attributes!(
201 $fnname,
202 pub const fn $fnname$(<$(const $generic_arg: $generic_ty),+>)?(&self) -> $res_ty {
203 Uint::$fnname(&self.0)
204 }
205 );
206 )*
207 };
208}
209
210#[allow(clippy::missing_safety_doc, clippy::missing_errors_doc)]
211impl<const BITS: usize, const LIMBS: usize> Bits<BITS, LIMBS> {
212 forward! {
213 fn reverse_bits(self) -> Self;
214 }
215 #[cfg(feature = "alloc")]
216 forward! {
217 fn as_le_bytes(&self) -> Cow<'_, [u8]>;
218 fn to_be_bytes_vec(&self) -> Vec<u8>;
219 }
220 forward! {
221 fn to_le_bytes<const BYTES: usize>(&self) -> [u8; BYTES];
222 fn to_be_bytes<const BYTES: usize>(&self) -> [u8; BYTES];
223 fn leading_zeros(&self) -> usize;
224 fn leading_ones(&self) -> usize;
225 fn trailing_zeros(&self) -> usize;
226 fn trailing_ones(&self) -> usize;
227 }
228 forward! {
229 unsafe fn as_limbs_mut(&mut self) -> &mut [u64; LIMBS];
230 }
231 forward! {
232 fn checked_shl(self, rhs: usize) -> Option<Self>;
233 fn checked_shr(self, rhs: usize) -> Option<Self>;
234 }
235 forward! {
236 fn overflowing_shl(self, rhs: usize) -> (Self, bool);
237 fn overflowing_shr(self, rhs: usize) -> (Self, bool);
238 }
239 forward! {
240 fn wrapping_shl(self, rhs: usize) -> Self;
241 fn wrapping_shr(self, rhs: usize) -> Self;
242 fn rotate_left(self, rhs: usize) -> Self;
243 fn rotate_right(self, rhs: usize) -> Self;
244 }
245 forward! {
246 fn try_from_be_slice(bytes: &[u8]) -> Option<Self>;
247 fn try_from_le_slice(bytes: &[u8]) -> Option<Self>;
248 }
249 forward! {
250 fn from_str_radix(src: &str, radix: u64) -> Result<Self, ParseError>;
251 }
252 forward! {
253 fn from_be_bytes<const BYTES: usize>(bytes: [u8; BYTES]) -> Self;
254 fn from_le_bytes<const BYTES: usize>(bytes: [u8; BYTES]) -> Self;
255 }
256 forward! {
257 const fn from_limbs(limbs: [u64; LIMBS]) -> Self;
258 }
259 forward! {
260 const fn as_limbs(&self) -> &[u64; LIMBS];
261 }
262}
263
264impl<const BITS: usize, const LIMBS: usize> Index<usize> for Bits<BITS, LIMBS> {
265 type Output = bool;
266
267 #[inline]
268 fn index(&self, index: usize) -> &Self::Output {
269 if self.0.bit(index) {
270 &true
271 } else {
272 &false
273 }
274 }
275}
276
277impl<const BITS: usize, const LIMBS: usize> Not for Bits<BITS, LIMBS> {
278 type Output = Self;
279
280 #[inline]
281 fn not(self) -> Self {
282 self.0.not().into()
283 }
284}
285
286impl<const BITS: usize, const LIMBS: usize> Not for &Bits<BITS, LIMBS> {
287 type Output = Bits<BITS, LIMBS>;
288
289 #[inline]
290 fn not(self) -> Bits<BITS, LIMBS> {
291 self.0.not().into()
292 }
293}
294
295macro_rules! impl_bit_op {
296 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => {
297 impl<const BITS: usize, const LIMBS: usize> $trait_assign<Bits<BITS, LIMBS>>
298 for Bits<BITS, LIMBS>
299 {
300 #[inline(always)]
301 fn $fn_assign(&mut self, rhs: Bits<BITS, LIMBS>) {
302 self.0.$fn_assign(&rhs.0);
303 }
304 }
305 impl<const BITS: usize, const LIMBS: usize> $trait_assign<&Bits<BITS, LIMBS>>
306 for Bits<BITS, LIMBS>
307 {
308 #[inline(always)]
309 fn $fn_assign(&mut self, rhs: &Bits<BITS, LIMBS>) {
310 self.0.$fn_assign(rhs.0);
311 }
312 }
313 impl<const BITS: usize, const LIMBS: usize> $trait<Bits<BITS, LIMBS>>
314 for Bits<BITS, LIMBS>
315 {
316 type Output = Bits<BITS, LIMBS>;
317
318 #[inline(always)]
319 fn $fn(mut self, rhs: Bits<BITS, LIMBS>) -> Self::Output {
320 self.0.$fn_assign(rhs.0);
321 self
322 }
323 }
324 impl<const BITS: usize, const LIMBS: usize> $trait<&Bits<BITS, LIMBS>>
325 for Bits<BITS, LIMBS>
326 {
327 type Output = Bits<BITS, LIMBS>;
328
329 #[inline(always)]
330 fn $fn(mut self, rhs: &Bits<BITS, LIMBS>) -> Self::Output {
331 self.0.$fn_assign(rhs.0);
332 self
333 }
334 }
335 impl<const BITS: usize, const LIMBS: usize> $trait<Bits<BITS, LIMBS>>
336 for &Bits<BITS, LIMBS>
337 {
338 type Output = Bits<BITS, LIMBS>;
339
340 #[inline(always)]
341 fn $fn(self, mut rhs: Bits<BITS, LIMBS>) -> Self::Output {
342 rhs.0.$fn_assign(self.0);
343 rhs
344 }
345 }
346 impl<const BITS: usize, const LIMBS: usize> $trait<&Bits<BITS, LIMBS>>
347 for &Bits<BITS, LIMBS>
348 {
349 type Output = Bits<BITS, LIMBS>;
350
351 #[inline(always)]
352 fn $fn(self, rhs: &Bits<BITS, LIMBS>) -> Self::Output {
353 self.0.clone().$fn(rhs.0).into()
354 }
355 }
356 };
357}
358
359impl_bit_op!(BitOr, bitor, BitOrAssign, bitor_assign);
360impl_bit_op!(BitAnd, bitand, BitAndAssign, bitand_assign);
361impl_bit_op!(BitXor, bitxor, BitXorAssign, bitxor_assign);
362
363macro_rules! impl_shift {
364 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => {
365 impl<const BITS: usize, const LIMBS: usize> $trait_assign<usize> for Bits<BITS, LIMBS> {
366 #[inline(always)]
367 fn $fn_assign(&mut self, rhs: usize) {
368 self.0.$fn_assign(rhs);
369 }
370 }
371
372 impl<const BITS: usize, const LIMBS: usize> $trait_assign<&usize> for Bits<BITS, LIMBS> {
373 #[inline(always)]
374 fn $fn_assign(&mut self, rhs: &usize) {
375 self.0.$fn_assign(rhs);
376 }
377 }
378
379 impl<const BITS: usize, const LIMBS: usize> $trait<usize> for Bits<BITS, LIMBS> {
380 type Output = Self;
381
382 #[inline(always)]
383 fn $fn(self, rhs: usize) -> Self {
384 self.0.$fn(rhs).into()
385 }
386 }
387
388 impl<const BITS: usize, const LIMBS: usize> $trait<usize> for &Bits<BITS, LIMBS> {
389 type Output = Bits<BITS, LIMBS>;
390
391 #[inline(always)]
392 fn $fn(self, rhs: usize) -> Self::Output {
393 self.0.$fn(rhs).into()
394 }
395 }
396
397 impl<const BITS: usize, const LIMBS: usize> $trait<&usize> for Bits<BITS, LIMBS> {
398 type Output = Self;
399
400 #[inline(always)]
401 fn $fn(self, rhs: &usize) -> Self {
402 self.0.$fn(rhs).into()
403 }
404 }
405
406 impl<const BITS: usize, const LIMBS: usize> $trait<&usize> for &Bits<BITS, LIMBS> {
407 type Output = Bits<BITS, LIMBS>;
408
409 #[inline(always)]
410 fn $fn(self, rhs: &usize) -> Self::Output {
411 self.0.$fn(rhs).into()
412 }
413 }
414 };
415}
416
417impl_shift!(Shl, shl, ShlAssign, shl_assign);
418impl_shift!(Shr, shr, ShrAssign, shr_assign);