mod sealed {
pub trait Sealed {}
}
pub trait Connectivity: sealed::Sealed + Copy {
const NEIGHBOURS: usize;
const OFFSETS: &'static [(i32, i32)];
}
#[derive(Clone, Copy, Debug)]
pub struct Connectivity4;
#[derive(Clone, Copy, Debug)]
pub struct Connectivity8;
impl sealed::Sealed for Connectivity4 {}
impl sealed::Sealed for Connectivity8 {}
impl Connectivity for Connectivity4 {
const NEIGHBOURS: usize = 2;
const OFFSETS: &'static [(i32, i32)] = &[(-1, 0), (0, -1)];
}
impl Connectivity for Connectivity8 {
const NEIGHBOURS: usize = 4;
const OFFSETS: &'static [(i32, i32)] = &[(-1, -1), (0, -1), (1, -1), (-1, 0)];
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn connectivity4_offsets_are_w_n_only() {
assert_eq!(Connectivity4::NEIGHBOURS, 2);
assert_eq!(Connectivity4::OFFSETS, &[(-1, 0), (0, -1)]);
}
#[test]
fn connectivity8_offsets_are_nw_n_ne_w() {
assert_eq!(Connectivity8::NEIGHBOURS, 4);
assert_eq!(
Connectivity8::OFFSETS,
&[(-1, -1), (0, -1), (1, -1), (-1, 0)]
);
}
#[test]
fn all_offsets_are_raster_preceding() {
for offsets in [Connectivity4::OFFSETS, Connectivity8::OFFSETS] {
for &(dx, dy) in offsets {
assert!(
dy < 0 || (dy == 0 && dx < 0),
"offset ({}, {}) is not raster-scan-preceding",
dx,
dy
);
}
}
}
#[test]
fn neighbours_matches_offsets_length() {
assert_eq!(Connectivity4::NEIGHBOURS, Connectivity4::OFFSETS.len());
assert_eq!(Connectivity8::NEIGHBOURS, Connectivity8::OFFSETS.len());
}
}