bva/
auto.rs

1use std::cmp::Ordering;
2use std::fmt::{Binary, Display, LowerHex, Octal, UpperHex};
3use std::hash::{Hash, Hasher};
4
5use std::ops::{
6    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
7    Mul, MulAssign, Not, Range, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
8};
9
10use crate::dynamic::Bvd;
11#[allow(unused_imports)]
12use crate::fixed::{Bv128, Bv16, Bv32, Bv64, Bv8, Bvf};
13use crate::iter::BitIterator;
14use crate::utils::{IArray, IArrayMut, Integer, StaticCast};
15use crate::Bit;
16use crate::{BitVector, ConvertionError, Endianness};
17
18// Choose a fixed Bvf type which should match the size of Bvd inside the enum
19#[cfg(target_pointer_width = "16")]
20pub(crate) type Bvp = Bv32;
21#[cfg(target_pointer_width = "32")]
22pub(crate) type Bvp = Bv64;
23#[cfg(target_pointer_width = "64")]
24pub(crate) type Bvp = Bv128;
25
26// ------------------------------------------------------------------------------------------------
27// Bit Vector automatic allocation implementation
28// ------------------------------------------------------------------------------------------------
29
30/// A bit vector with an automatically managed memory allocation type.
31///
32/// Depending on the required capacity, it might use a fixed capacity implementation to avoid
33/// unnecessary dynamic memory allocations, or it might use a dynamic capacity implementation
34/// when needed.
35///
36/// While avoiding memory allocation might improve performances, there is a slight performance cost
37/// due to the dynamic dispatch and extra capacity checks. The net effect will depend on the exact
38/// workload.
39///
40/// # Examples
41///
42/// ```
43/// use bva::{BitVector, Bv};
44///
45/// // This bit vector will be stack allocated.
46/// let a = Bv::from(27u8);
47/// assert_eq!(a.len(), 8);
48/// // This bit vector will be heap allocated.
49/// let b = Bv::ones(256);
50/// assert_eq!(b.len(), 256);
51/// // The result of this operation will also be heap allocated.
52/// let c = b + a;
53/// assert_eq!(c.len(), 256);
54/// assert_eq!(c.to_string(), "26");
55/// ```
56#[derive(Clone, Debug)]
57pub enum Bv {
58    #[doc(hidden)]
59    Fixed(Bvp),
60    #[doc(hidden)]
61    Dynamic(Bvd),
62}
63
64impl Bv {
65    /// Reserve will reserve room for at least `additional` bits in the bit vector. The actual
66    /// length of the bit vector will stay unchanged, see [`BitVector::resize`] to change the actual
67    /// length of the bit vector.
68    ///
69    /// Calling this method might cause the storage to become dynamically allocated.
70    ///
71    /// ```
72    /// use bva::{BitVector, Bv};
73    ///
74    /// let mut bv = Bv::ones(128);
75    /// assert_eq!(bv.capacity(), 128);
76    /// bv.reserve(128);
77    /// assert_eq!(bv.capacity(), 256);
78    /// ```
79    pub fn reserve(&mut self, additional: usize) {
80        match self {
81            &mut Bv::Fixed(ref b) => {
82                if b.len() + additional > Bvp::capacity() {
83                    let mut new_b = Bvd::from(b);
84                    new_b.reserve(additional);
85                    *self = Bv::Dynamic(new_b);
86                }
87            }
88            Bv::Dynamic(b) => b.reserve(additional),
89        }
90    }
91
92    /// Drop as much excess capacity as possible in the bit vector to fit the current length.
93    ///
94    /// Calling this method might cause the implementation to drop unnecessary dynamically
95    /// allocated memory.
96    ///
97    /// ```
98    /// use bva::{BitVector, Bv};
99    ///
100    /// let mut bv = Bv::ones(128);
101    /// bv.reserve(128);
102    /// assert_eq!(bv.capacity(), 256);
103    /// bv.shrink_to_fit();
104    /// assert_eq!(bv.capacity(), 128);
105    /// ```
106    pub fn shrink_to_fit(&mut self) {
107        if let Bv::Dynamic(b) = self {
108            if b.len() <= Bvp::capacity() {
109                let new_b = Bvp::try_from(&*b).unwrap();
110                *self = Bv::Fixed(new_b);
111            } else {
112                b.shrink_to_fit();
113            }
114        }
115    }
116}
117
118// ------------------------------------------------------------------------------------------------
119// Bv - Integer Array traits
120// ------------------------------------------------------------------------------------------------
121
122impl IArray for Bv {
123    type I = u64;
124
125    fn int_len<J: Integer>(&self) -> usize
126    where
127        u64: StaticCast<J>,
128    {
129        match self {
130            Bv::Fixed(bvf) => IArray::int_len(bvf),
131            Bv::Dynamic(bvd) => IArray::int_len(bvd),
132        }
133    }
134
135    fn get_int<J: Integer>(&self, idx: usize) -> Option<J>
136    where
137        u64: StaticCast<J>,
138    {
139        match self {
140            Bv::Fixed(bvf) => IArray::get_int(bvf, idx),
141            Bv::Dynamic(bvd) => IArray::get_int(bvd, idx),
142        }
143    }
144}
145
146impl IArrayMut for Bv {
147    type I = u64;
148
149    fn set_int<J: Integer>(&mut self, idx: usize, v: J) -> Option<J>
150    where
151        u64: StaticCast<J>,
152    {
153        match self {
154            Bv::Fixed(bvf) => IArrayMut::set_int(bvf, idx, v),
155            Bv::Dynamic(bvd) => IArrayMut::set_int(bvd, idx, v),
156        }
157    }
158}
159
160// ------------------------------------------------------------------------------------------------
161// Bv - Bit Vector core trait
162// ------------------------------------------------------------------------------------------------
163
164impl BitVector for Bv {
165    fn with_capacity(capacity: usize) -> Self {
166        if capacity <= Bvp::capacity() {
167            Bv::Fixed(Bvp::with_capacity(capacity))
168        } else {
169            Bv::Dynamic(Bvd::with_capacity(capacity))
170        }
171    }
172
173    fn zeros(length: usize) -> Self {
174        if length <= Bvp::capacity() {
175            Bv::Fixed(Bvp::zeros(length))
176        } else {
177            Bv::Dynamic(Bvd::zeros(length))
178        }
179    }
180
181    fn ones(length: usize) -> Self {
182        if length <= Bvp::capacity() {
183            Bv::Fixed(Bvp::ones(length))
184        } else {
185            Bv::Dynamic(Bvd::ones(length))
186        }
187    }
188
189    fn capacity(&self) -> usize {
190        match self {
191            Bv::Fixed(_) => Bvp::capacity(),
192            Bv::Dynamic(b) => b.capacity(),
193        }
194    }
195
196    fn len(&self) -> usize {
197        match self {
198            Bv::Fixed(b) => b.len(),
199            Bv::Dynamic(b) => b.len(),
200        }
201    }
202
203    fn from_binary<S: AsRef<str>>(string: S) -> Result<Self, ConvertionError> {
204        if string.as_ref().len() <= Bvp::capacity() {
205            Ok(Bv::Fixed(Bvp::from_binary(string)?))
206        } else {
207            Ok(Bv::Dynamic(Bvd::from_binary(string)?))
208        }
209    }
210
211    fn from_hex<S: AsRef<str>>(string: S) -> Result<Self, ConvertionError> {
212        if string.as_ref().len() * 4 <= Bvp::capacity() {
213            Ok(Bv::Fixed(Bvp::from_hex(string)?))
214        } else {
215            Ok(Bv::Dynamic(Bvd::from_hex(string)?))
216        }
217    }
218
219    fn from_bytes<B: AsRef<[u8]>>(
220        bytes: B,
221        endianness: Endianness,
222    ) -> Result<Self, ConvertionError> {
223        if bytes.as_ref().len() * 8 <= Bvp::capacity() {
224            Ok(Bv::Fixed(Bvp::from_bytes(bytes, endianness)?))
225        } else {
226            Ok(Bv::Dynamic(Bvd::from_bytes(bytes, endianness)?))
227        }
228    }
229
230    fn to_vec(&self, endianness: Endianness) -> Vec<u8> {
231        match self {
232            Bv::Fixed(b) => b.to_vec(endianness),
233            Bv::Dynamic(b) => b.to_vec(endianness),
234        }
235    }
236
237    fn read<R: std::io::Read>(
238        reader: &mut R,
239        length: usize,
240        endianness: Endianness,
241    ) -> std::io::Result<Self> {
242        if length <= Bvp::capacity() {
243            Ok(Bv::Fixed(Bvp::read(reader, length, endianness)?))
244        } else {
245            Ok(Bv::Dynamic(Bvd::read(reader, length, endianness)?))
246        }
247    }
248
249    fn write<W: std::io::Write>(
250        &self,
251        writer: &mut W,
252        endianness: Endianness,
253    ) -> std::io::Result<()> {
254        match self {
255            Bv::Fixed(b) => b.write(writer, endianness),
256            Bv::Dynamic(b) => b.write(writer, endianness),
257        }
258    }
259
260    fn get(&self, index: usize) -> Bit {
261        match self {
262            Bv::Fixed(b) => b.get(index),
263            Bv::Dynamic(b) => b.get(index),
264        }
265    }
266
267    fn set(&mut self, index: usize, bit: Bit) {
268        match self {
269            Bv::Fixed(b) => b.set(index, bit),
270            Bv::Dynamic(b) => b.set(index, bit),
271        }
272    }
273
274    fn copy_range(&self, range: Range<usize>) -> Self {
275        match self {
276            Bv::Fixed(b) => Bv::Fixed(b.copy_range(range)),
277            Bv::Dynamic(b) => {
278                let s = b.copy_range(range);
279                if s.len() <= Bvp::capacity() {
280                    Bv::Fixed(Bvp::try_from(s).unwrap())
281                } else {
282                    Bv::Dynamic(s)
283                }
284            }
285        }
286    }
287
288    fn push(&mut self, bit: Bit) {
289        self.reserve(1);
290        match self {
291            Bv::Fixed(b) => b.push(bit),
292            Bv::Dynamic(b) => b.push(bit),
293        }
294    }
295
296    fn pop(&mut self) -> Option<Bit> {
297        match self {
298            Bv::Fixed(b) => b.pop(),
299            Bv::Dynamic(b) => b.pop(),
300        }
301    }
302
303    fn resize(&mut self, new_length: usize, bit: Bit) {
304        if new_length > self.len() {
305            self.reserve(new_length - self.len());
306        }
307        match self {
308            Bv::Fixed(b) => b.resize(new_length, bit),
309            Bv::Dynamic(b) => b.resize(new_length, bit),
310        }
311    }
312
313    fn append<B: BitVector>(&mut self, suffix: &B) {
314        match self {
315            Bv::Fixed(bvf) => {
316                if bvf.len() + suffix.len() <= Bvp::capacity() {
317                    bvf.append(suffix);
318                } else {
319                    let mut bvd = Bvd::from(&*bvf);
320                    bvd.append(suffix);
321                    *self = Bv::Dynamic(bvd);
322                }
323            }
324            Bv::Dynamic(bvd) => {
325                bvd.append(suffix);
326            }
327        }
328    }
329
330    fn prepend<B: BitVector>(&mut self, prefix: &B) {
331        match self {
332            Bv::Fixed(bvf) => {
333                if bvf.len() + prefix.len() <= Bvp::capacity() {
334                    bvf.prepend(prefix);
335                } else {
336                    let mut bvd = Bvd::from(&*bvf);
337                    bvd.prepend(prefix);
338                    *self = Bv::Dynamic(bvd);
339                }
340            }
341            Bv::Dynamic(bvd) => {
342                bvd.prepend(prefix);
343            }
344        }
345    }
346
347    fn shl_in(&mut self, bit: Bit) -> Bit {
348        match self {
349            Bv::Fixed(b) => b.shl_in(bit),
350            Bv::Dynamic(b) => b.shl_in(bit),
351        }
352    }
353
354    fn shr_in(&mut self, bit: Bit) -> Bit {
355        match self {
356            Bv::Fixed(b) => b.shr_in(bit),
357            Bv::Dynamic(b) => b.shr_in(bit),
358        }
359    }
360
361    fn rotl(&mut self, rot: usize) {
362        match self {
363            Bv::Fixed(b) => b.rotl(rot),
364            Bv::Dynamic(b) => b.rotl(rot),
365        }
366    }
367
368    fn rotr(&mut self, rot: usize) {
369        match self {
370            Bv::Fixed(b) => b.rotr(rot),
371            Bv::Dynamic(b) => b.rotr(rot),
372        }
373    }
374
375    fn leading_zeros(&self) -> usize {
376        match self {
377            Bv::Fixed(b) => b.leading_zeros(),
378            Bv::Dynamic(b) => b.leading_zeros(),
379        }
380    }
381
382    fn leading_ones(&self) -> usize {
383        match self {
384            Bv::Fixed(b) => b.leading_ones(),
385            Bv::Dynamic(b) => b.leading_ones(),
386        }
387    }
388
389    fn trailing_zeros(&self) -> usize {
390        match self {
391            Bv::Fixed(b) => b.trailing_zeros(),
392            Bv::Dynamic(b) => b.trailing_zeros(),
393        }
394    }
395
396    fn trailing_ones(&self) -> usize {
397        match self {
398            Bv::Fixed(b) => b.trailing_ones(),
399            Bv::Dynamic(b) => b.trailing_ones(),
400        }
401    }
402
403    fn is_zero(&self) -> bool {
404        match self {
405            Bv::Fixed(b) => b.is_zero(),
406            Bv::Dynamic(b) => b.is_zero(),
407        }
408    }
409
410    fn div_rem<B: BitVector>(&self, divisor: &B) -> (Self, Self)
411    where
412        Self: for<'a> TryFrom<&'a B, Error: std::fmt::Debug>,
413    {
414        assert!(!divisor.is_zero(), "Division by zero");
415        let mut quotient = Bv::zeros(self.len());
416        let mut rem = self.clone();
417        if divisor.significant_bits() > self.significant_bits() {
418            return (quotient, rem);
419        }
420
421        let shift = self.significant_bits() - divisor.significant_bits();
422        let mut divisor: Bv = divisor.try_into().expect("should never fail");
423        divisor.resize(self.len(), Bit::Zero);
424        divisor <<= shift;
425
426        for i in (0..shift + 1).rev() {
427            if rem >= divisor {
428                rem -= &divisor;
429                quotient.set(i, Bit::One);
430            }
431            divisor >>= 1u32;
432        }
433
434        (quotient, rem)
435    }
436
437    fn iter(&self) -> BitIterator<'_, Self> {
438        self.into_iter()
439    }
440}
441
442impl Hash for Bv {
443    fn hash<H: Hasher>(&self, state: &mut H) {
444        self.len().hash(state);
445        for i in 0..Self::int_len::<u64>(self) {
446            self.get_int::<u64>(i).unwrap().hash(state);
447        }
448    }
449}
450
451// ------------------------------------------------------------------------------------------------
452// Bv - Bit iterator trait
453// ------------------------------------------------------------------------------------------------
454
455impl<'a> IntoIterator for &'a Bv {
456    type Item = Bit;
457    type IntoIter = BitIterator<'a, Bv>;
458
459    fn into_iter(self) -> Self::IntoIter {
460        BitIterator::new(self)
461    }
462}
463
464impl FromIterator<Bit> for Bv {
465    fn from_iter<T: IntoIterator<Item = Bit>>(iter: T) -> Self {
466        let iter = iter.into_iter();
467        let mut bv = Bv::with_capacity(iter.size_hint().0);
468        iter.for_each(|b| bv.push(b));
469        bv
470    }
471}
472
473impl Extend<Bit> for Bv {
474    fn extend<T: IntoIterator<Item = Bit>>(&mut self, iter: T) {
475        let iter = iter.into_iter();
476        self.reserve(iter.size_hint().0);
477        iter.for_each(|b| self.push(b));
478    }
479}
480
481// ------------------------------------------------------------------------------------------------
482// Bv - Formatting traits
483// ------------------------------------------------------------------------------------------------
484
485impl Binary for Bv {
486    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
487        match self {
488            Bv::Fixed(b) => Binary::fmt(b, f),
489            Bv::Dynamic(b) => Binary::fmt(b, f),
490        }
491    }
492}
493
494impl Display for Bv {
495    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
496        match self {
497            Bv::Fixed(b) => Display::fmt(b, f),
498            Bv::Dynamic(b) => Display::fmt(b, f),
499        }
500    }
501}
502
503impl LowerHex for Bv {
504    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
505        match self {
506            Bv::Fixed(b) => LowerHex::fmt(b, f),
507            Bv::Dynamic(b) => LowerHex::fmt(b, f),
508        }
509    }
510}
511
512impl UpperHex for Bv {
513    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
514        match self {
515            Bv::Fixed(b) => UpperHex::fmt(b, f),
516            Bv::Dynamic(b) => UpperHex::fmt(b, f),
517        }
518    }
519}
520
521impl Octal for Bv {
522    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
523        match self {
524            Bv::Fixed(b) => Octal::fmt(b, f),
525            Bv::Dynamic(b) => Octal::fmt(b, f),
526        }
527    }
528}
529
530// ------------------------------------------------------------------------------------------------
531// Bv - Comparison traits
532// ------------------------------------------------------------------------------------------------
533
534impl PartialEq for Bv {
535    fn eq(&self, other: &Self) -> bool {
536        match self {
537            Bv::Fixed(b1) => match other {
538                Bv::Fixed(b2) => b1.eq(b2),
539                Bv::Dynamic(b2) => b1.eq(b2),
540            },
541            Bv::Dynamic(b1) => match other {
542                Bv::Fixed(b2) => b1.eq(b2),
543                Bv::Dynamic(b2) => b1.eq(b2),
544            },
545        }
546    }
547}
548
549impl PartialEq<Bvd> for Bv {
550    fn eq(&self, other: &Bvd) -> bool {
551        match self {
552            Bv::Fixed(bvf) => bvf.eq(other),
553            Bv::Dynamic(bvd) => bvd.eq(other),
554        }
555    }
556}
557
558impl<I: Integer, const N: usize> PartialEq<Bvf<I, N>> for Bv
559where
560    u64: StaticCast<I>,
561{
562    fn eq(&self, other: &Bvf<I, N>) -> bool {
563        match self {
564            Bv::Fixed(bvf) => bvf.eq(other),
565            Bv::Dynamic(bvd) => bvd.eq(other),
566        }
567    }
568}
569
570impl Eq for Bv {}
571
572impl PartialOrd for Bv {
573    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
574        Some(self.cmp(other))
575    }
576}
577
578impl<I: Integer, const N: usize> PartialOrd<Bvf<I, N>> for Bv
579where
580    u64: StaticCast<I>,
581{
582    fn partial_cmp(&self, other: &Bvf<I, N>) -> Option<Ordering> {
583        match self {
584            Bv::Fixed(bvf) => bvf.partial_cmp(other),
585            Bv::Dynamic(bvd) => bvd.partial_cmp(other),
586        }
587    }
588}
589
590impl PartialOrd<Bvd> for Bv {
591    fn partial_cmp(&self, other: &Bvd) -> Option<Ordering> {
592        match self {
593            Bv::Fixed(bvf) => bvf.partial_cmp(other),
594            Bv::Dynamic(bvd) => bvd.partial_cmp(other),
595        }
596    }
597}
598
599impl Ord for Bv {
600    fn cmp(&self, other: &Self) -> Ordering {
601        match self {
602            Bv::Fixed(b1) => match other {
603                Bv::Fixed(b2) => b1.cmp(b2),
604                Bv::Dynamic(b2) => b1.partial_cmp(b2).unwrap(),
605            },
606            Bv::Dynamic(b1) => match other {
607                Bv::Fixed(b2) => b1.partial_cmp(b2).unwrap(),
608                Bv::Dynamic(b2) => b1.cmp(b2),
609            },
610        }
611    }
612}
613
614// ------------------------------------------------------------------------------------------------
615// Bv - Conversion traits
616// ------------------------------------------------------------------------------------------------
617
618impl From<&Bv> for Bv {
619    fn from(b: &Bv) -> Self {
620        match b {
621            Bv::Fixed(bvf) => Bv::Fixed(*bvf),
622            Bv::Dynamic(bvd) => Bv::Dynamic(bvd.clone()),
623        }
624    }
625}
626
627impl From<Bvd> for Bv {
628    fn from(b: Bvd) -> Self {
629        if let Ok(bvf) = Bvp::try_from(&b) {
630            Bv::Fixed(bvf)
631        } else {
632            Bv::Dynamic(b)
633        }
634    }
635}
636
637impl From<&'_ Bvd> for Bv {
638    fn from(b: &'_ Bvd) -> Self {
639        if let Ok(bvf) = Bvp::try_from(b) {
640            Bv::Fixed(bvf)
641        } else {
642            Bv::Dynamic(b.clone())
643        }
644    }
645}
646
647impl<I: Integer, const N: usize> From<&Bvf<I, N>> for Bv {
648    fn from(b: &Bvf<I, N>) -> Self {
649        if Bvf::<I, N>::capacity() <= Bvp::capacity() {
650            Bv::Fixed(b.try_into().unwrap())
651        } else {
652            Bv::Dynamic(b.into())
653        }
654    }
655}
656
657impl<I: Integer, const N: usize> From<Bvf<I, N>> for Bv {
658    fn from(b: Bvf<I, N>) -> Self {
659        Bv::from(&b)
660    }
661}
662
663macro_rules! impl_tryfrom { ($($type:ty),+) => {
664    $(
665        impl From<$type> for Bv {
666            fn from(int: $type) -> Self {
667                // Branch should be optimized at compile time
668                if std::mem::size_of::<$type>() * 8 <= Bvp::capacity() {
669                    Bv::Fixed(Bvp::try_from(int).unwrap())
670                }
671                else {
672                    Bv::Dynamic(Bvd::from(int))
673                }
674            }
675        }
676
677        impl From<&$type> for Bv {
678            fn from(int: &$type) -> Self {
679                Self::from(*int)
680            }
681        }
682
683        impl TryFrom<&Bv> for $type
684        {
685            type Error = ConvertionError;
686            fn try_from(bv: &Bv) -> Result<Self, Self::Error> {
687                match bv {
688                    Bv::Fixed(b) => Ok(b.try_into()?),
689                    Bv::Dynamic(b) => Ok(b.try_into()?),
690                }
691            }
692        }
693
694        impl TryFrom<Bv> for $type
695        {
696            type Error = ConvertionError;
697            fn try_from(bv: Bv) -> Result<Self, Self::Error> {
698                Self::try_from(&bv)
699            }
700        }
701    )+
702}}
703
704impl_tryfrom!(u8, u16, u32, u64, u128, usize);
705
706impl<I: Integer> From<&[I]> for Bv
707where
708    u64: StaticCast<I>,
709{
710    fn from(slice: &[I]) -> Self {
711        let mut bv = Bv::zeros(slice.len() * I::BITS);
712        for (i, v) in slice.iter().enumerate() {
713            bv.set_int(i, *v);
714        }
715        bv
716    }
717}
718
719// ------------------------------------------------------------------------------------------------
720// Bv - Unary operator & shifts
721// ------------------------------------------------------------------------------------------------
722
723impl Not for Bv {
724    type Output = Bv;
725
726    fn not(self) -> Self::Output {
727        match self {
728            Bv::Fixed(b) => Bv::Fixed(b.not()),
729            Bv::Dynamic(b) => Bv::Dynamic(b.not()),
730        }
731    }
732}
733
734impl Not for &'_ Bv {
735    type Output = Bv;
736
737    fn not(self) -> Self::Output {
738        match self {
739            Bv::Fixed(b) => Bv::Fixed(b.not()),
740            Bv::Dynamic(b) => Bv::Dynamic(b.not()),
741        }
742    }
743}
744
745macro_rules! impl_shift_assign {($trait:ident, $method:ident, {$($rhs:ty),+}) => {
746    $(
747        impl $trait<$rhs> for Bv {
748            fn $method(&mut self, rhs: $rhs) {
749                match self {
750                    Bv::Fixed(b) => b.$method(rhs),
751                    Bv::Dynamic(b) => b.$method(rhs)
752                }
753            }
754        }
755
756        impl $trait<&'_ $rhs> for Bv {
757            fn $method(&mut self, rhs: &'_ $rhs) {
758                match self {
759                    Bv::Fixed(b) => b.$method(rhs),
760                    Bv::Dynamic(b) => b.$method(rhs)
761                }
762            }
763        }
764    )+
765}}
766
767impl_shift_assign!(ShlAssign, shl_assign, {u8, u16, u32, u64, u128, usize});
768impl_shift_assign!(ShrAssign, shr_assign, {u8, u16, u32, u64, u128, usize});
769
770macro_rules! impl_shift {($trait:ident, $method:ident, {$($rhs:ty),+}) => {
771    $(
772        impl $trait<$rhs> for Bv {
773            type Output = Bv;
774            fn $method(self, rhs: $rhs) -> Bv {
775                match self {
776                    Bv::Fixed(b) => Bv::Fixed(b.$method(rhs)),
777                    Bv::Dynamic(b) => Bv::Dynamic(b.$method(rhs))
778                }
779            }
780        }
781
782        impl $trait<&'_ $rhs> for Bv {
783            type Output = Bv;
784            fn $method(self, rhs: &'_ $rhs) -> Bv {
785                match self {
786                    Bv::Fixed(b) => Bv::Fixed(b.$method(rhs)),
787                    Bv::Dynamic(b) => Bv::Dynamic(b.$method(rhs))
788                }
789            }
790        }
791
792        impl $trait<$rhs> for &'_ Bv {
793            type Output = Bv;
794            fn $method(self, rhs: $rhs) -> Bv {
795                self.clone().$method(rhs)
796            }
797        }
798
799        impl $trait<&'_ $rhs> for &'_ Bv {
800            type Output = Bv;
801            fn $method(self, rhs: &'_ $rhs) -> Bv {
802                self.clone().$method(rhs)
803            }
804        }
805    )+
806}}
807
808impl_shift!(Shl, shl, {u8, u16, u32, u64, u128, usize});
809impl_shift!(Shr, shr, {u8, u16, u32, u64, u128, usize});
810
811// ------------------------------------------------------------------------------------------------
812// Uint helper macro
813// ------------------------------------------------------------------------------------------------
814
815macro_rules! impl_op_uint {
816    ($trait:ident, $method:ident, {$($uint:ty),+}) => {
817        $(
818            impl $trait<&$uint> for &Bv
819            {
820                type Output = Bv;
821                fn $method(self, rhs: &$uint) -> Self::Output {
822                    match self {
823                        Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
824                        Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
825                    }
826                }
827            }
828
829            impl $trait<$uint> for &Bv
830            {
831                type Output = Bv;
832                fn $method(self, rhs: $uint) -> Self::Output {
833                    match self {
834                        Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
835                        Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
836                    }
837                }
838            }
839
840            impl $trait<&$uint> for Bv
841            {
842                type Output = Bv;
843                fn $method(self, rhs: &$uint) -> Self::Output {
844                    match self {
845                        Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
846                        Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
847                    }
848                }
849            }
850
851            impl $trait<$uint> for Bv
852            {
853                type Output = Bv;
854                fn $method(self, rhs: $uint) -> Self::Output {
855                    match self {
856                        Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
857                        Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
858                    }
859                }
860            }
861        )+
862    };
863}
864
865macro_rules! impl_op_assign_uint {
866    ($trait:ident, $method:ident, {$($uint:ty),+}) => {
867        $(
868            impl $trait<$uint> for Bv
869            {
870                fn $method(&mut self, rhs: $uint) {
871                    match self {
872                        Bv::Fixed(bvf) => bvf.$method(rhs),
873                        Bv::Dynamic(bvd) => bvd.$method(rhs),
874                    }
875                }
876            }
877
878            impl $trait<&$uint> for Bv
879            {
880                fn $method(&mut self, rhs: &$uint) {
881                    match self {
882                        Bv::Fixed(bvf) => bvf.$method(rhs),
883                        Bv::Dynamic(bvd) => bvd.$method(rhs),
884                    }
885                }
886            }
887        )+
888    };
889}
890
891// ------------------------------------------------------------------------------------------------
892// Bv - Arithmetic operators (assignment kind)
893// ------------------------------------------------------------------------------------------------
894
895macro_rules! impl_op_assign {
896    ($trait:ident, $method:ident, {$($uint:ty),+}) => {
897        impl $trait<&Bv> for Bv {
898            fn $method(&mut self, bv: &Bv) {
899                match bv {
900                    Bv::Fixed(b) => self.$method(b),
901                    Bv::Dynamic(b) => self.$method(b),
902                }
903            }
904        }
905
906        impl $trait<Bv> for Bv {
907            fn $method(&mut self, bv: Bv) {
908                match bv {
909                    Bv::Fixed(b) => self.$method(b),
910                    Bv::Dynamic(b) => self.$method(b),
911                }
912            }
913        }
914
915        impl<I: Integer, const N: usize> $trait<&Bvf<I, N>> for Bv
916        where
917            u64: StaticCast<I>,
918        {
919            fn $method(&mut self, bvf: &Bvf<I, N>) {
920                match self {
921                    Bv::Fixed(b) => b.$method(bvf),
922                    Bv::Dynamic(b) => b.$method(bvf),
923                }
924            }
925        }
926
927        impl<I: Integer, const N: usize> $trait<Bvf<I, N>> for Bv
928        where
929            u64: StaticCast<I>,
930        {
931            fn $method(&mut self, bvf: Bvf<I, N>) {
932                match self {
933                    Bv::Fixed(b) => b.$method(bvf),
934                    Bv::Dynamic(b) => b.$method(bvf),
935                }
936            }
937        }
938
939        impl $trait<Bvd> for Bv {
940            fn $method(&mut self, bvd: Bvd) {
941                match self {
942                    Bv::Fixed(b) => b.$method(bvd),
943                    Bv::Dynamic(b) => b.$method(bvd),
944                }
945            }
946        }
947
948        impl $trait<&Bvd> for Bv {
949            fn $method(&mut self, bvd: &Bvd) {
950                match self {
951                    Bv::Fixed(b) => b.$method(bvd),
952                    Bv::Dynamic(b) => b.$method(bvd),
953                }
954            }
955        }
956
957        impl_op_assign_uint!($trait, $method, {$($uint),+});
958    };
959}
960
961impl_op_assign!(BitAndAssign, bitand_assign, {u8, u16, u32, u64, usize, u128});
962impl_op_assign!(BitOrAssign, bitor_assign, {u8, u16, u32, u64, usize, u128});
963impl_op_assign!(BitXorAssign, bitxor_assign, {u8, u16, u32, u64, usize, u128});
964impl_op_assign!(AddAssign, add_assign, {u8, u16, u32, u64, usize, u128});
965impl_op_assign!(SubAssign, sub_assign, {u8, u16, u32, u64, usize, u128});
966impl_op_assign!(MulAssign, mul_assign, {u8, u16, u32, u64, usize, u128});
967impl_op_assign!(DivAssign, div_assign, {u8, u16, u32, u64, usize, u128});
968impl_op_assign!(RemAssign, rem_assign, {u8, u16, u32, u64, usize, u128});
969
970macro_rules! impl_op {
971    ($trait:ident, $method:ident, {$($uint:ty),+}) => {
972        impl $trait<&Bv> for &Bv {
973            type Output = Bv;
974            fn $method(self, rhs: &Bv) -> Bv {
975                match self {
976                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
977                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
978                }
979            }
980        }
981
982        impl $trait<Bv> for &Bv {
983            type Output = Bv;
984            fn $method(self, rhs: Bv) -> Bv {
985                match self {
986                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
987                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
988                }
989            }
990        }
991
992        impl $trait<&Bv> for Bv {
993            type Output = Bv;
994            fn $method(self, rhs: &Bv) -> Bv {
995                match self {
996                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
997                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
998                }
999            }
1000        }
1001
1002        impl $trait<Bv> for Bv {
1003            type Output = Bv;
1004            fn $method(self, rhs: Bv) -> Bv {
1005                match self {
1006                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1007                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1008                }
1009            }
1010        }
1011
1012        impl<I: Integer, const N: usize> $trait<&Bvf<I, N>> for &Bv
1013        where
1014            u64: StaticCast<I>
1015        {
1016            type Output = Bv;
1017            fn $method(self, rhs: &Bvf<I, N>) -> Bv {
1018                match self {
1019                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1020                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1021                }
1022            }
1023        }
1024
1025        impl<I: Integer, const N: usize> $trait<Bvf<I, N>> for &Bv
1026        where
1027            u64: StaticCast<I>
1028        {
1029            type Output = Bv;
1030            fn $method(self, rhs: Bvf<I, N>) -> Bv {
1031                match self {
1032                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1033                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1034                }
1035            }
1036        }
1037
1038        impl<I: Integer, const N: usize> $trait<&Bvf<I, N>> for Bv
1039        where
1040            u64: StaticCast<I>
1041        {
1042            type Output = Bv;
1043            fn $method(self, rhs: &Bvf<I, N>) -> Bv {
1044                match self {
1045                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1046                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1047                }
1048            }
1049        }
1050
1051        impl<I: Integer, const N: usize> $trait<Bvf<I, N>> for Bv
1052        where
1053            u64: StaticCast<I>
1054        {
1055            type Output = Bv;
1056            fn $method(self, rhs: Bvf<I, N>) -> Bv {
1057                match self {
1058                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1059                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1060                }
1061            }
1062        }
1063
1064        impl $trait<&Bvd> for &Bv
1065        {
1066            type Output = Bv;
1067            fn $method(self, rhs: &Bvd) -> Bv {
1068                match self {
1069                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1070                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1071                }
1072            }
1073        }
1074
1075        impl $trait<Bvd> for &Bv
1076        {
1077            type Output = Bv;
1078            fn $method(self, rhs: Bvd) -> Bv {
1079                match self {
1080                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1081                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1082                }
1083            }
1084        }
1085
1086        impl $trait<&Bvd> for Bv
1087        {
1088            type Output = Bv;
1089            fn $method(self, rhs: &Bvd) -> Bv {
1090                match self {
1091                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1092                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1093                }
1094            }
1095        }
1096
1097        impl $trait<Bvd> for Bv
1098        {
1099            type Output = Bv;
1100            fn $method(self, rhs: Bvd) -> Bv {
1101                match self {
1102                    Bv::Fixed(bvf) => Bv::Fixed(bvf.$method(rhs)),
1103                    Bv::Dynamic(bvd) => Bv::Dynamic(bvd.$method(rhs)),
1104                }
1105            }
1106        }
1107
1108        impl_op_uint!($trait, $method, {$($uint),+});
1109    };
1110}
1111
1112impl_op!(BitAnd, bitand, {u8, u16, u32, u64, usize, u128});
1113impl_op!(BitOr, bitor, {u8, u16, u32, u64, usize, u128});
1114impl_op!(BitXor, bitxor, {u8, u16, u32, u64, usize, u128});
1115impl_op!(Add, add, {u8, u16, u32, u64, usize, u128});
1116impl_op!(Sub, sub, {u8, u16, u32, u64, usize, u128});
1117impl_op!(Mul, mul, {u8, u16, u32, u64, usize, u128});
1118impl_op!(Div, div, {u8, u16, u32, u64, usize, u128});
1119impl_op!(Rem, rem, {u8, u16, u32, u64, usize, u128});