use crate::Error;
use crate::N;
use serde::de::Error as DeError;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{Display, Formatter};
use std::ops::{BitAnd, BitOr};
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Default, Hash)]
pub struct Fill(u16);
impl Fill {
#[must_use]
pub const fn all(n: usize) -> Self {
Self(((1u16 << (n + 1)).wrapping_sub(1)) & !1)
}
pub fn new(ns: &[N]) -> Result<Self, Error> {
for &n in ns {
if !(1..=9).contains(&n) {
return Err(Error::InvalidValue(n));
}
}
Ok(Self(ns.iter().fold(0u16, |acc, &v| acc | (1u16 << v))))
}
pub(crate) fn from(ns: &[N]) -> Self {
Self(ns.iter().fold(0u16, |acc, &v| acc | (1u16 << v)))
}
#[must_use]
pub const fn singleton(n: N) -> Self {
Self(1u16 << n)
}
#[must_use]
pub const fn contains(self, value: N) -> bool {
self.0 & (1u16 << value) != 0
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.0 == 0
}
#[must_use]
pub const fn is_singleton(self) -> bool {
self.0.is_power_of_two()
}
#[must_use]
pub const fn len(self) -> usize {
self.0.count_ones() as usize
}
#[must_use]
pub fn values(self) -> Vec<N> {
(1u8..=9).filter(|&v| self.0 & (1u16 << v) != 0).collect()
}
#[must_use]
pub fn min_value(self) -> Option<N> {
(1u8..=9).find(|&v| self.0 & (1u16 << v) != 0)
}
#[must_use]
pub fn max_value(self) -> Option<N> {
(1u8..=9).rev().find(|&v| self.0 & (1u16 << v) != 0)
}
}
impl BitOr for Fill {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl BitAnd for Fill {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
}
impl crate::csp::Domain for Fill {
fn is_empty(&self) -> bool {
Self::is_empty(*self)
}
}
impl Display for Fill {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{{")?;
let mut first = true;
for v in self.values() {
if !first {
write!(f, ", ")?;
}
write!(f, "{v}")?;
first = false;
}
write!(f, "}}")
}
}
impl Serialize for Fill {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.collect_seq(self.values())
}
}
impl<'de> Deserialize<'de> for Fill {
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let ns = Vec::<N>::deserialize(d)?;
Self::new(&ns).map_err(|e| DeError::custom(e.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::{from_str, to_string};
#[test]
fn all_contains_one_through_n() {
let f = Fill::all(4);
assert!(f.contains(1));
assert!(f.contains(4));
assert!(!f.contains(0));
assert!(!f.contains(5));
}
#[test]
fn new_empty_slice_is_empty() {
assert!(Fill::new(&[]).unwrap().is_empty());
}
#[test]
fn new_deduplicates_values() {
assert_eq!(Fill::new(&[2, 2, 3]).unwrap(), Fill::from(&[2, 3]));
}
#[test]
fn new_rejects_zero() {
assert!(matches!(Fill::new(&[0]), Err(Error::InvalidValue(0))));
}
#[test]
fn new_rejects_ten() {
assert!(matches!(Fill::new(&[10]), Err(Error::InvalidValue(10))));
}
#[test]
fn singleton_contains_only_that_value() {
let f = Fill::singleton(3);
assert!(f.contains(3));
assert!(!f.contains(2));
assert!(f.is_singleton());
}
#[test]
fn from_empty_slice_is_empty() {
assert!(Fill::from(&[]).is_empty());
}
#[test]
fn contains_absent_value_is_false() {
assert!(!Fill::from(&[1, 3]).contains(2));
}
#[test]
fn is_empty_false_for_non_empty() {
assert!(!Fill::all(3).is_empty());
}
#[test]
fn is_singleton_true_for_single_value() {
assert!(Fill::new(&[5]).unwrap().is_singleton());
}
#[test]
fn is_singleton_false_for_multiple() {
assert!(!Fill::new(&[1, 2]).unwrap().is_singleton());
}
#[test]
fn is_singleton_false_for_empty() {
assert!(!Fill::default().is_singleton());
}
#[test]
fn len_counts_values() {
assert_eq!(Fill::default().len(), 0);
assert_eq!(Fill::singleton(3).len(), 1);
assert_eq!(Fill::new(&[1, 5, 9]).unwrap().len(), 3);
assert_eq!(Fill::all(9).len(), 9);
}
#[test]
fn default_is_empty() {
assert!(Fill::default().is_empty());
}
#[test]
fn display_empty() {
assert_eq!(Fill::from(&[]).to_string(), "{}");
}
#[test]
fn display_singleton() {
assert_eq!(Fill::from(&[3]).to_string(), "{3}");
}
#[test]
fn display_sorted() {
assert_eq!(Fill::from(&[3, 1, 2]).to_string(), "{1, 2, 3}");
}
#[test]
fn round_trips_through_json() {
let f = Fill::from(&[1, 3]);
assert_eq!(from_str::<Fill>(&to_string(&f).unwrap()).unwrap(), f);
}
#[test]
fn serialize_is_sorted_array() {
assert_eq!(to_string(&Fill::from(&[3, 1])).unwrap(), r"[1,3]");
}
#[test]
fn deserialize_rejects_out_of_range() {
assert!(from_str::<Fill>("[0]").is_err());
assert!(from_str::<Fill>("[10]").is_err());
}
#[test]
fn bitor_union() {
assert_eq!(
Fill::new(&[1, 2]).unwrap() | Fill::new(&[2, 3]).unwrap(),
Fill::new(&[1, 2, 3]).unwrap()
);
}
#[test]
fn bitand_intersection() {
assert_eq!(
Fill::new(&[1, 2, 3]).unwrap() & Fill::new(&[2, 3, 4]).unwrap(),
Fill::new(&[2, 3]).unwrap()
);
}
#[test]
fn values_in_order() {
assert_eq!(Fill::from(&[3, 1, 2]).values(), vec![1, 2, 3]);
}
}