use super::Command;
#[derive(Clone, Debug)]
pub struct Layout {
batch: usize,
commands: Vec<Command>,
contours: Vec<Range>,
}
#[derive(Clone, Debug)]
pub struct Range {
start: usize,
end: usize,
}
impl Layout {
pub fn new(batch: usize, commands: Vec<Command>, contours: Vec<Range>) -> Self {
assert!(
contours.iter().all(|range| range.end() <= commands.len()),
"contour ranges must be in bounds for the command sequence"
);
Self {
batch,
commands,
contours,
}
}
pub const fn batch(&self) -> usize {
self.batch
}
pub fn commands(&self, range: &Range) -> &[Command] {
&self.commands[range.start()..range.end()]
}
pub fn contours(&self) -> &[Range] {
&self.contours
}
}
impl Range {
pub const fn new(start: usize, end: usize) -> Self {
assert!(start <= end, "range start must not exceed range end");
Self { start, end }
}
pub const fn end(&self) -> usize {
self.end
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
pub const fn len(&self) -> usize {
self.end - self.start
}
pub const fn start(&self) -> usize {
self.start
}
}
#[cfg(test)]
mod tests {
use super::{Command, Layout, Range};
#[test]
#[should_panic]
fn layout_rejects_out_of_bounds_commands() {
let _ = Layout::new(0, vec![Command::Quadratic], vec![Range::new(0, 2)]);
}
#[test]
fn layout_returns_contour_commands() {
let layout = Layout::new(
0,
vec![Command::Linear, Command::Quadratic, Command::Linear],
vec![Range::new(1, 3)],
);
assert_eq!(
layout.commands(&Range::new(1, 3)),
&[Command::Quadratic, Command::Linear]
);
}
#[test]
#[should_panic]
fn range_rejects_reversed_bounds() {
let _ = Range::new(5, 2);
}
#[test]
fn range_returns_length() {
assert_eq!(Range::new(2, 5).len(), 3);
}
}