#![no_std]
use core::{array, fmt, iter, ops};
use either::Either;
#[macro_use]
pub mod layouts;
pub use layouts::*;
pub trait BitFieldLayout: Layout {
type Value: Copy + IntoBits + FromBits;
fn get(&self) -> Self::Value;
fn set(&mut self, new: Self::Value);
fn replace(&mut self, new: Self::Value) -> Self::Value {
let v = self.get();
self.set(new);
v
}
fn swap(&mut self, other: &mut Self) {
let (a, b) = (self.get(), other.get());
self.set(b);
other.set(a);
}
fn update<F>(&mut self, f: F) -> Self::Value
where
F: FnOnce(Self::Value) -> Self::Value,
{
let v = f(self.get());
self.set(v);
self.get()
}
fn insert_flag(&mut self, position: usize, b: bool) -> bool {
let mut result = false;
let bits = self.get()
.into_bits()
.enumerate()
.map(|(n, is_set)| {
if n == position {
result = is_set;
b
} else {
is_set
}
});
self.set(Self::Value::from_bits(bits));
result
}
fn toggle_flag(&mut self, position: usize) {
let bits = self.get()
.into_bits()
.enumerate()
.map(|(n, is_set)| {
if n == position {
!is_set
} else {
is_set
}
});
self.set(Self::Value::from_bits(bits));
}
fn bits(&self) -> Bits<<Self::Value as IntoBits>::Bytes> {
self.get().into_bits()
}
fn flags(&self) -> Flags<Self::Layout, Bits<<Self::Value as IntoBits>::Bytes>> {
Flags::new(Self::layout(), self.bits())
}
fn diff(&self, other: Self) -> Diff<Self::Layout, Bits<<Self::Value as IntoBits>::Bytes>>
where
Self: Sized,
{
Diff::new(self.flags(), other.flags())
}
fn find_state<P>(&self, predicate: P) -> Option<bool>
where
P: Fn(<<Self as Layout>::Layout as Iterator>::Item) -> bool,
{
for f in self.flags() {
if predicate(f.value) {
return Some(f.is_set)
}
}
None
}
}
pub trait Layout {
type Layout: Iterator;
fn layout() -> Self::Layout;
}
pub trait IntoBits {
type Bytes: Iterator<Item = u8>;
fn into_bits(self) -> Bits<Self::Bytes>;
}
impl IntoBits for u8 {
type Bytes = array::IntoIter<u8, 1>;
fn into_bits(self) -> Bits<Self::Bytes> {
self.to_ne_bytes().into_bits()
}
}
impl IntoBits for u16 {
type Bytes = array::IntoIter<u8, 2>;
fn into_bits(self) -> Bits<Self::Bytes> {
self.to_ne_bytes().into_bits()
}
}
impl IntoBits for u32 {
type Bytes = array::IntoIter<u8, 4>;
fn into_bits(self) -> Bits<Self::Bytes> {
self.to_ne_bytes().into_bits()
}
}
impl IntoBits for u64 {
type Bytes = array::IntoIter<u8, 8>;
fn into_bits(self) -> Bits<Self::Bytes> {
self.to_ne_bytes().into_bits()
}
}
impl IntoBits for u128 {
type Bytes = array::IntoIter<u8, 16>;
fn into_bits(self) -> Bits<Self::Bytes> {
self.to_ne_bytes().into_bits()
}
}
impl<const N: usize> IntoBits for [u8; N] {
type Bytes = array::IntoIter<u8, N>;
fn into_bits(self) -> Bits<Self::Bytes> {
Bits::new(array::IntoIter::new(self))
}
}
impl<const N: usize> IntoBits for [u16; N] {
type Bytes = iter::Flatten<array::IntoIter<array::IntoIter<u8, N>, 2>>;
fn into_bits(self) -> Bits<Self::Bytes> {
let mut result = [
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
];
let mut buf = [0u8; N];
let bytes = self.iter()
.map(|d| array::IntoIter::new(d.to_ne_bytes()))
.flatten();
for (n, byte) in bytes.enumerate() {
let i = n % N;
buf[i] = byte;
if i == N - 1 {
result[n / N] = array::IntoIter::new(buf);
}
}
Bits::new(array::IntoIter::new(result).flatten())
}
}
impl<const N: usize> IntoBits for [u32; N] {
type Bytes = iter::Flatten<array::IntoIter<array::IntoIter<u8, N>, 4>>;
fn into_bits(self) -> Bits<Self::Bytes> {
let mut result = [
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
];
let mut buf = [0u8; N];
let bytes = self.iter()
.map(|d| array::IntoIter::new(d.to_ne_bytes()))
.flatten();
for (n, byte) in bytes.enumerate() {
let i = n % N;
buf[i] = byte;
if i == N - 1 {
result[n / N] = array::IntoIter::new(buf);
}
}
Bits::new(array::IntoIter::new(result).flatten())
}
}
impl<const N: usize> IntoBits for [u64; N] {
type Bytes = iter::Flatten<array::IntoIter<array::IntoIter<u8, N>, 8>>;
fn into_bits(self) -> Bits<Self::Bytes> {
let mut result = [
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
];
let mut buf = [0u8; N];
let bytes = self.iter()
.map(|d| array::IntoIter::new(d.to_ne_bytes()))
.flatten();
for (n, byte) in bytes.enumerate() {
let i = n % N;
buf[i] = byte;
if i == N - 1 {
result[n / N] = array::IntoIter::new(buf);
}
}
Bits::new(array::IntoIter::new(result).flatten())
}
}
impl<const N: usize> IntoBits for [u128; N] {
type Bytes = iter::Flatten<array::IntoIter<array::IntoIter<u8, N>, 16>>;
fn into_bits(self) -> Bits<Self::Bytes> {
let mut result = [
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
array::IntoIter::new([0u8; N]),
];
let mut buf = [0u8; N];
let bytes = self.iter()
.map(|d| array::IntoIter::new(d.to_ne_bytes()))
.flatten();
for (n, byte) in bytes.enumerate() {
let i = n % N;
buf[i] = byte;
if i == N - 1 {
result[n / N] = array::IntoIter::new(buf);
}
}
Bits::new(array::IntoIter::new(result).flatten())
}
}
pub trait FromBits {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self;
}
impl FromBits for u8 {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
u8::from_ne_bytes(<[u8; 1]>::from_bits(bits))
}
}
impl FromBits for u16 {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
u16::from_ne_bytes(<[u8; 2]>::from_bits(bits))
}
}
impl FromBits for u32 {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
u32::from_ne_bytes(<[u8; 4]>::from_bits(bits))
}
}
impl FromBits for u64 {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
u64::from_ne_bytes(<[u8; 8]>::from_bits(bits))
}
}
impl FromBits for u128 {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
u128::from_ne_bytes(<[u8; 16]>::from_bits(bits))
}
}
impl<const N: usize> FromBits for [u8; N] {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
let mut result = [0u8; N];
for (i, is_set) in bits.enumerate().take(N * 8) {
if is_set {
result[i / 8] |= 1 << (i % 8)
}
}
result
}
}
impl<const N: usize> FromBits for [u16; N] {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
<[[u8; 2]; N]>::from_bits(bits).iter()
.map(|arr| u16::from_ne_bytes(*arr))
.enumerate()
.fold([0; N], |mut result, (n, v)| { result[n] = v; result })
}
}
impl<const N: usize> FromBits for [u32; N] {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
<[[u8; 4]; N]>::from_bits(bits).iter()
.map(|arr| u32::from_ne_bytes(*arr))
.enumerate()
.fold([0; N], |mut result, (n, v)| { result[n] = v; result })
}
}
impl<const N: usize> FromBits for [u64; N] {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
<[[u8; 8]; N]>::from_bits(bits).iter()
.map(|arr| u64::from_ne_bytes(*arr))
.enumerate()
.fold([0; N], |mut result, (n, v)| { result[n] = v; result })
}
}
impl<const N: usize> FromBits for [u128; N] {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
<[[u8; 16]; N]>::from_bits(bits).iter()
.map(|arr| u128::from_ne_bytes(*arr))
.enumerate()
.fold([0; N], |mut result, (n, v)| { result[n] = v; result })
}
}
impl<const N: usize, const M: usize> FromBits for [[u8; N]; M] {
fn from_bits<I: Iterator<Item = bool>>(bits: I) -> Self {
let mut result = [[0u8; N]; M];
for (i, is_set) in bits.enumerate().take(N * M * 8) {
if is_set {
let m = (i / 8) % M;
let n = (i / 8) % N;
result[m][n] |= 1 << (i % 8)
}
}
result
}
}
#[derive(Debug, Clone, Copy)]
pub struct Bits<I> {
iter: I,
byte: u8,
position: usize
}
impl<I: Iterator<Item = u8>> Bits<I> {
pub fn new(iter: I) -> Self {
Self { iter, byte: 0, position: 0 }
}
}
impl<I: Iterator<Item = u8>> Iterator for Bits<I> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if self.position == 0 {
self.byte = self.iter.next()?;
}
let position = self.position;
self.position = (self.position + 1) % 8;
Some(self.byte & (1 << position) != 0)
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct Flag<T> {
pub position: usize,
pub is_set: bool,
pub value: T,
}
impl<T> fmt::Display for Flag<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}#{}", if self.is_set { "+" } else { "-" }, self.position)
}
}
#[derive(Debug, Clone)]
pub struct Flags<L, B>
where
L: Iterator,
B: Iterator<Item = bool>
{
position: usize,
layout: L,
bits: B,
}
impl<L, B> Flags<L, B>
where
L: Iterator,
B: Iterator<Item = bool>
{
pub fn new(layout: L, bits: B) -> Self {
Self { position: 0, layout, bits, }
}
}
impl<L, B> Iterator for Flags<L, B>
where
L: Iterator,
B: Iterator<Item = bool>
{
type Item = Flag<L::Item>;
fn next(&mut self) -> Option<Self::Item> {
let value = self.layout.next()?;
let is_set = self.bits.next()?;
let position = self.position;
self.position += 1;
Some(Flag { position, is_set, value })
}
}
#[derive(Debug, Clone)]
pub struct Diff<L, B>
where
L: Iterator,
B: Iterator<Item = bool>
{
left: Flags<L, B>,
right: Flags<L, B>,
position: usize,
}
impl<L, B> Diff<L, B>
where
L: Iterator,
B: Iterator<Item = bool>
{
fn new(left: Flags<L, B>, right: Flags<L, B>) -> Self {
Self { left, right, position: 0 }
}
}
impl<L, T, B> Iterator for Diff<L, B>
where
L: Iterator<Item = T>,
B: Iterator<Item = bool>
{
type Item = Either<(usize, T), (usize, T)>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let left = self.left.next()?;
let right = self.right.next()?;
let position = self.position;
self.position += 1;
match (left.is_set, right.is_set) {
(true, false) =>
return Some(Either::Left((position, left.value))),
(false, true) =>
return Some(Either::Right((position, right.value))),
_ => continue,
}
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct BitField<M, T> {
_marker: core::marker::PhantomData<M>,
pub value: T,
}
impl<M, T> BitField<M, T> {
pub fn new(value: T) -> Self {
Self {
_marker: core::marker::PhantomData,
value
}
}
}
impl<M: Layout, T> Layout for BitField<M, T> {
type Layout = M::Layout;
fn layout() -> Self::Layout { M::layout() }
}
impl<M: Layout, T: Copy + IntoBits + FromBits> BitFieldLayout for BitField<M, T> {
type Value = T;
fn get(&self) -> Self::Value { self.value }
fn set(&mut self, new: Self::Value) { self.value = new; }
}
impl<M, T> ops::BitAnd for BitField<M, T>
where
M: Layout,
T: Copy + IntoBits + FromBits + ops::BitAnd<Output = T>,
{
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Self::new(self.get() & rhs.get())
}
}
impl<M, T> ops::BitAndAssign for BitField<M, T>
where
M: Layout,
T: Copy + IntoBits + FromBits + ops::BitAnd<Output = T>,
{
fn bitand_assign(&mut self, rhs: Self) {
*self = Self::new(self.get() & rhs.get())
}
}
impl<M, T> ops::BitOr for BitField<M, T>
where
M: Layout,
T: Copy + IntoBits + FromBits + ops::BitOr<Output = T>,
{
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self::new(self.get() | rhs.get())
}
}
impl<M, T> ops::BitOrAssign for BitField<M, T>
where
M: Layout,
T: Copy + IntoBits + FromBits + ops::BitOr<Output = T>,
{
fn bitor_assign(&mut self, rhs: Self) {
*self = Self::new(self.get() | rhs.get())
}
}
impl<M, T> ops::BitXor for BitField<M, T>
where
M: Layout,
T: Copy + IntoBits + FromBits + ops::BitXor<Output = T>,
{
type Output = Self;
fn bitxor(self, rhs: Self) -> Self::Output {
Self::new(self.get() ^ rhs.get())
}
}
impl<M, T> ops::BitXorAssign for BitField<M, T>
where
M: Layout,
T: Copy + IntoBits + FromBits + ops::BitXor<Output = T>,
{
fn bitxor_assign(&mut self, rhs: Self) {
*self = Self::new(self.get() ^ rhs.get())
}
}
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
mod tests {
use std::prelude::v1::*;
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn bits() {
let bits = Bits::new([13,42].iter().cloned());
let sample = vec![
true, false, true, true, false, false, false, false,
false, true, false, true, false, true, false, false,
];
let result = bits.collect::<Vec<_>>();
assert_eq!(sample, result, "Bits");
}
#[test]
fn into_bits() {
assert_eq!(vec![false,true,false,true], 42u8.into_bits().take(4).collect::<Vec<_>>(), "u8");
assert_eq!(vec![false,true,false,true], 42u16.into_bits().take(4).collect::<Vec<_>>(), "u16");
assert_eq!(vec![false,true,false,true], 42u32.into_bits().take(4).collect::<Vec<_>>(), "u32");
assert_eq!(vec![false,true,false,true], 42u64.into_bits().take(4).collect::<Vec<_>>(), "u64");
assert_eq!(vec![false,true,false,true], 42u128.into_bits().take(4).collect::<Vec<_>>(), "u128");
assert_eq!(vec![false,true,false,true], [42u8,1,2].into_bits().take(4).collect::<Vec<_>>(), "[u8;3]");
assert_eq!(vec![false,true,false,true], [42u16,1,2].into_bits().take(4).collect::<Vec<_>>(), "[u16;3]");
assert_eq!(vec![false,true,false,true], [42u32,1,2].into_bits().take(4).collect::<Vec<_>>(), "[u32;3]");
assert_eq!(vec![false,true,false,true], [42u64,1,2].into_bits().take(4).collect::<Vec<_>>(), "[u64;3]");
assert_eq!(vec![false,true,false,true], [42u128,1,2].into_bits().take(4).collect::<Vec<_>>(), "[u128;3]");
}
#[test]
fn from_bits() {
assert_eq!(42, u8::from_bits(42u8.into_bits()), "u8");
assert_eq!(42, u16::from_bits(42u16.into_bits()), "u16");
assert_eq!(42, u32::from_bits(42u32.into_bits()), "u32");
assert_eq!(42, u64::from_bits(42u64.into_bits()), "u64");
assert_eq!(42, u128::from_bits(42u128.into_bits()), "u128");
assert_eq!([42;3], <[u8;3]>::from_bits([42u8;3].into_bits()), "[u8;3]");
assert_eq!([42;3], <[u16;3]>::from_bits([42u16;3].into_bits()), "[u16;3]");
assert_eq!([42;3], <[u32;3]>::from_bits([42u32;3].into_bits()), "[u32;3]");
assert_eq!([42;3], <[u64;3]>::from_bits([42u64;3].into_bits()), "[u64;3]");
assert_eq!([42;3], <[u128;3]>::from_bits([42u128;3].into_bits()), "[u128;3]");
}
#[test]
fn flags() {
let flags = Flags::new(
["Flag 1","Flag 2","Flag 3","Flag 4","Flag 5","Flag 6","Flag 7","Flag 8",]
.iter(),
[ false, true, false, true, true, false, false, false, ]
.iter().cloned(),
);
let sample = vec!["Flag 2","Flag 4","Flag 5",];
let result = flags.filter_map(|f| Some(*f.value).filter(|_| f.is_set)).collect::<Vec<_>>();
assert_eq!(sample, result, "Flags");
}
#[test]
fn diff() {
let layout = ["Flag 1","Flag 2","Flag 3","Flag 4","Flag 5","Flag 6","Flag 7","Flag 8",];
let flags0 = Flags::new(
layout.iter(),
[ false, true, false, true, true, false, false, false, ]
.iter().cloned(),
);
let flags1 = Flags::new(
layout.iter(),
[ false, true, false, false, true, false, true, false, ]
.iter().cloned(),
);
let sample = vec![
Either::Left((3, &"Flag 4")),
Either::Right((6, &"Flag 7"))
];
let result = Diff::new(flags0, flags1).collect::<Vec<_>>();
assert_eq!(sample, result, "Diff");
}
#[test]
fn bitfield_bitwise() {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
struct Simple;
impl Layout for Simple {
type Layout = core::iter::Empty<()>;
fn layout() -> Self::Layout { std::iter::empty() }
}
let bitand_result: BitField<Simple, u8> = BitField::new(42) & BitField::new(0b1111);
assert_eq!(BitField::<Simple, u8>::new(0b1010), bitand_result, "BitAnd");
let mut bitand_assign_result: BitField<Simple, u8> = BitField::new(42);
bitand_assign_result &= BitField::new(0b1111);
assert_eq!(BitField::<Simple, u8>::new(0b1010), bitand_assign_result, "BitAndAssign");
let bitor_result: BitField<Simple, u8> = BitField::new(42) | BitField::new(0b1111);
assert_eq!(BitField::<Simple, u8>::new(0b101111), bitor_result, "BitOr");
let mut bitor_assign_result: BitField<Simple, u8> = BitField::new(42);
bitor_assign_result |= BitField::new(0b1111);
assert_eq!(BitField::<Simple, u8>::new(0b101111), bitor_assign_result, "BitOrAssign");
let bitxor_result: BitField<Simple, u8> = BitField::new(42) ^ BitField::new(0b1111);
assert_eq!(BitField::<Simple, u8>::new(0b100101), bitxor_result, "BitXor");
let mut bitxor_assign_result: BitField<Simple, u8> = BitField::new(42);
bitxor_assign_result ^= BitField::new(0b1111);
assert_eq!(BitField::<Simple, u8>::new(0b100101), bitxor_assign_result, "BitXorAssign");
}
}