use crate::Nesting;
#[allow(unused_imports)]
use crate::{Awaiting, FieldKind};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Facet<'a> {
pub name: &'a str,
pub mode: Selecting,
pub values: &'a [FacetValue<'a>],
}
impl<'a> Facet<'a> {
#[must_use]
pub const fn new(name: &'a str, mode: Selecting, values: &'a [FacetValue<'a>]) -> Self {
Self { name, mode, values }
}
#[must_use]
pub fn engaged(&self) -> bool {
self.values.iter().any(|value| value.standing.is_picked())
}
#[must_use]
pub fn reach(&self) -> u8 {
self.values
.iter()
.map(|value| value.depth.level)
.max()
.unwrap_or(0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Selecting {
OneOf,
AnyOf,
Range,
Text,
Subtree,
}
impl Selecting {
#[must_use]
pub const fn offers_values(self) -> bool {
matches!(self, Self::OneOf | Self::AnyOf | Self::Subtree)
}
#[must_use]
pub const fn prunes(self) -> bool {
matches!(self, Self::Subtree)
}
#[must_use]
pub const fn accumulates(self) -> bool {
matches!(self, Self::AnyOf | Self::Subtree)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct FacetValue<'a> {
pub value: &'a str,
pub label: &'a str,
pub count: Option<u64>,
pub standing: Standing,
pub depth: Nesting,
pub branching: bool,
pub pickable: bool,
pub open: Option<bool>,
pub join: Option<Join>,
pub gain: bool,
pub rank: Option<GroupRank>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum Join {
#[default]
Any,
All,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub struct GroupRank {
pub in_use: bool,
pub live: bool,
pub cut: u8,
pub start: bool,
}
impl GroupRank {
#[must_use]
pub const fn cutting(cut: u8) -> Self {
Self {
in_use: false,
live: true,
cut: if cut > 100 { 100 } else { cut },
start: false,
}
}
#[must_use]
pub const fn in_use() -> Self {
Self {
in_use: true,
live: true,
cut: 0,
start: false,
}
}
#[must_use]
pub const fn dead() -> Self {
Self {
in_use: false,
live: false,
cut: 0,
start: false,
}
}
#[must_use]
pub const fn starting(mut self) -> Self {
self.start = true;
self
}
}
impl<'a> FacetValue<'a> {
#[must_use]
pub const fn new(value: &'a str, label: &'a str) -> Self {
Self {
value,
label,
count: None,
standing: Standing::Open,
depth: Nesting::top(),
branching: false,
pickable: true,
open: None,
join: None,
gain: false,
rank: None,
}
}
#[must_use]
pub const fn of(value: &'a str) -> Self {
Self::new(value, value)
}
#[must_use]
pub const fn counted(mut self, count: u64) -> Self {
self.count = Some(count);
self
}
#[must_use]
pub const fn standing(mut self, standing: Standing) -> Self {
self.standing = standing;
self
}
#[must_use]
pub const fn at(mut self, depth: Nesting, branching: bool) -> Self {
self.depth = depth;
self.branching = branching;
self
}
#[must_use]
pub const fn heading(mut self) -> Self {
self.pickable = false;
self
}
#[must_use]
pub const fn opened(mut self, open: bool) -> Self {
self.open = Some(open);
self
}
#[must_use]
pub const fn joined(mut self, join: Join) -> Self {
self.join = Some(join);
self
}
#[must_use]
pub const fn gained(mut self) -> Self {
self.gain = true;
self
}
#[must_use]
pub const fn ranked(mut self, rank: GroupRank) -> Self {
self.rank = Some(rank);
self
}
#[must_use]
pub const fn is_open(&self) -> bool {
match self.open {
Some(open) => open,
None => self.standing.in_force(),
}
}
#[must_use]
pub const fn is_link(&self) -> bool {
!self.pickable && !self.branching
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum Standing {
#[default]
Open,
Taken,
Inherited,
Pruned,
PrunedAbove,
}
impl Standing {
#[must_use]
pub const fn is_picked(self) -> bool {
matches!(self, Self::Taken | Self::Pruned)
}
#[must_use]
pub const fn in_force(self) -> bool {
matches!(self, Self::Taken | Self::Inherited)
}
#[must_use]
pub const fn intent(self) -> &'static str {
match self {
Self::Taken | Self::Inherited | Self::Open => "content",
Self::Pruned | Self::PrunedAbove => "content-secondary",
}
}
#[must_use]
pub const fn pruned_out(self) -> bool {
matches!(self, Self::Pruned | Self::PrunedAbove)
}
}