#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub struct Part {
pub bytes: bool,
pub bits: u8,
pub desc: bool,
}
pub const MAX_PARTS: usize = 32;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Shape {
pub parts: [Part; MAX_PARTS],
pub n: usize,
}
impl Shape {
const EMPTY: Shape = Shape { parts: [Part { bytes: false, bits: 0, desc: false }; MAX_PARTS], n: 0 };
pub const fn fixed(bits: u8) -> Shape {
let mut s = Shape::EMPTY;
s.parts[0] = Part { bytes: false, bits, desc: false };
s.n = 1;
s
}
pub const fn bytes() -> Shape {
let mut s = Shape::EMPTY;
s.parts[0] = Part { bytes: true, bits: 0, desc: false };
s.n = 1;
s
}
pub const fn concat(a: &Shape, b: &Shape) -> Shape {
let mut s = *a;
let mut i = 0;
while i < b.n && i < MAX_PARTS {
if a.n + i < MAX_PARTS {
s.parts[a.n + i] = b.parts[i];
}
i += 1;
}
let n = a.n + b.n;
s.n = if n > MAX_PARTS { MAX_PARTS + 1 } else { n };
s
}
pub const fn repeat(s: &Shape, count: usize) -> Shape {
let mut out = Shape::EMPTY;
let mut i = 0;
while i < count {
out = Shape::concat(&out, s);
i += 1;
}
out
}
pub const fn reversed(&self) -> Shape {
let mut s = *self;
let mut i = 0;
while i < s.n && i < MAX_PARTS {
s.parts[i].desc = !s.parts[i].desc;
i += 1;
}
s
}
pub const fn is_valid(&self) -> bool {
self.n >= 1 && self.n <= MAX_PARTS
}
pub const fn all_fixed(&self) -> bool {
let mut i = 0;
while i < self.n && i < MAX_PARTS {
if self.parts[i].bytes {
return false;
}
i += 1;
}
true
}
pub const fn has_bytes(&self) -> bool {
!self.all_fixed()
}
pub const fn total_bits(&self) -> u32 {
let mut b = 0u32;
let mut i = 0;
while i < self.n && i < MAX_PARTS {
b += self.parts[i].bits as u32;
i += 1;
}
b
}
pub const fn part(&self, i: usize) -> Part {
self.parts[i]
}
pub const fn kind(&self, i: usize) -> u8 {
let p = self.parts[i];
if !p.bytes {
0
} else if p.desc {
2
} else {
1
}
}
}