use core::ops::RangeBounds;
use core::{fmt, ops::Bound};
#[cfg(feature = "dev")]
use arbitrary::Arbitrary;
use ufotofu::codec_prelude::*;
use order_theory::GreatestElement;
use willow_data_model::prelude as wdm;
use crate::prelude::*;
wrapper! {
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd)]
#[cfg_attr(feature = "dev", derive(Arbitrary))]
Area; wdm::Area<MCL, MCC, MPL, SubspaceId>
}
impl fmt::Debug for Area {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl Grouping for Area {
fn includes<Coord>(&self, coord: &Coord) -> bool
where
Coord: Coordinatelike + ?Sized,
{
wdm::Grouping::wdm_includes(&self.0, coord)
}
fn intersection(
&self,
other: &Self,
) -> Result<Self, willow_data_model::prelude::EmptyGrouping> {
wdm::Grouping::wdm_intersection(&self.0, &other.0).map(Into::into)
}
}
impl RangeBounds<SubspaceId> for Area {
fn start_bound(&self) -> Bound<&SubspaceId> {
match self.subspace() {
None => Bound::Unbounded,
Some(s) => Bound::Included(s),
}
}
fn end_bound(&self) -> Bound<&SubspaceId> {
match self.subspace() {
None => Bound::Unbounded,
Some(s) => Bound::Included(s),
}
}
}
impl RangeBounds<Timestamp> for Area {
fn start_bound(&self) -> Bound<&Timestamp> {
self.times().start_bound()
}
fn end_bound(&self) -> Bound<&Timestamp> {
self.times().end_bound()
}
}
impl Area {
pub fn new(subspace: Option<SubspaceId>, path: Path, times: TimeRange) -> Self {
wdm::Area::new(subspace, path.into(), times).into()
}
pub fn subspace(&self) -> Option<&SubspaceId> {
self.0.subspace()
}
pub fn path(&self) -> &Path {
self.0.path().into()
}
pub fn times(&self) -> &TimeRange {
self.0.times()
}
pub fn set_subspace(&mut self, new_subspace: Option<SubspaceId>) {
self.0.set_subspace(new_subspace);
}
pub fn set_path(&mut self, new_path: Path) {
self.0.set_path(new_path.into());
}
pub fn set_times<TR>(&mut self, new_range: TR)
where
TR: Into<TimeRange>,
{
self.0.set_times(new_range)
}
pub fn new_subspace_area(subspace_id: SubspaceId) -> Self {
wdm::Area::new_subspace_area(subspace_id).into()
}
pub fn admits_pruning_by<Coord>(&self, coord: &Coord) -> bool
where
Coord: Coordinatelike,
{
self.0.admits_pruning_by(coord)
}
pub fn full() -> Self {
wdm::Area::full().into()
}
pub fn is_full(&self) -> bool {
self.0.is_full()
}
}
impl GreatestElement for Area {
fn greatest() -> Self {
wdm::Area::greatest().into()
}
}
impl RelativeEncodable<Area> for Area {
async fn relative_encode<C>(&self, rel: &Area, consumer: &mut C) -> Result<(), C::Error>
where
C: BulkConsumer<Item = u8> + ?Sized,
{
self.0.relative_encode(rel.into(), consumer).await
}
fn can_be_encoded_relative_to(&self, rel: &Area) -> bool {
self.0.can_be_encoded_relative_to(rel.into())
}
}
impl RelativeDecodable<Area> for Area {
type ErrorReason = Blame;
async fn relative_decode<P>(
rel: &Area,
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
wdm::Area::<MCL, MCC, MPL, SubspaceId>::relative_decode(rel.into(), producer)
.await
.map(Into::into)
}
}
impl RelativeDecodableCanonic<Area> for Area {
type ErrorCanonic = Blame;
async fn relative_decode_canonic<P>(
rel: &Area,
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
Self: Sized,
{
wdm::Area::<MCL, MCC, MPL, SubspaceId>::relative_decode_canonic(rel.into(), producer)
.await
.map(Into::into)
}
}
impl RelativeEncodableKnownLength<Area> for Area {
fn len_of_relative_encoding(&self, rel: &Area) -> usize {
self.0.len_of_relative_encoding(rel.into())
}
}
#[cfg(feature = "dev")]
pub fn arbitrary_area_in_area<'a>(
reference: &Area,
u: &mut arbitrary::Unstructured<'a>,
) -> arbitrary::Result<Area> {
willow_data_model::groupings::arbitrary_area_in_area::<MCL, MCC, MPL, SubspaceId>(
reference.into(),
u,
)
.map(Into::into)
}