use crate::node::{
CoreConstructible, DisconnectConstructible, JetConstructible, WitnessConstructible,
};
use crate::types::{Context, Error};
use crate::{Cmr, FailEntropy, HasCmr, Word};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Hiding<'brand, N> {
result: HidingResult<N>,
ctx: Context<'brand>,
}
type HidingResult<N> = Result<N, Cmr>;
impl<'brand, N> Hiding<'brand, N> {
pub const fn hidden(cmr: Cmr, ctx: Context<'brand>) -> Self {
Self {
result: Err(cmr),
ctx,
}
}
fn hidden_cloned_ctx(&self, cmr: Cmr) -> Self {
Self {
result: Err(cmr),
ctx: self.ctx.shallow_clone(),
}
}
pub fn as_node(&self) -> Option<&N> {
self.result.as_ref().ok()
}
pub fn get_node(self) -> Option<N> {
self.result.ok()
}
}
impl<N: HasCmr> Hiding<'_, N> {
pub fn hide(self) -> Self {
match self.result {
Ok(node) => Self::hidden(node.cmr(), self.ctx),
Err(..) => self,
}
}
}
impl<N: HasCmr> HasCmr for Hiding<'_, N> {
fn cmr(&self) -> Cmr {
match &self.result {
Ok(node) => node.cmr(),
Err(cmr) => *cmr,
}
}
}
impl<'brand, N: CoreConstructible<'brand>> From<N> for Hiding<'brand, N> {
fn from(node: N) -> Self {
Self {
ctx: node.inference_context().shallow_clone(),
result: Ok(node),
}
}
}
impl<'brand, N: CoreConstructible<'brand> + HasCmr> CoreConstructible<'brand>
for Hiding<'brand, N>
{
fn iden(inference_context: &Context<'brand>) -> Self {
N::iden(inference_context).into()
}
fn unit(inference_context: &Context<'brand>) -> Self {
N::unit(inference_context).into()
}
fn injl(child: &Self) -> Self {
match &child.result {
Ok(child) => N::injl(child).into(),
Err(cmr) => child.hidden_cloned_ctx(Cmr::injl(*cmr)),
}
}
fn injr(child: &Self) -> Self {
match &child.result {
Ok(child) => N::injr(child).into(),
Err(cmr) => child.hidden_cloned_ctx(Cmr::injr(*cmr)),
}
}
fn take(child: &Self) -> Self {
match &child.result {
Ok(child) => N::take(child).into(),
Err(cmr) => child.hidden_cloned_ctx(Cmr::take(*cmr)),
}
}
fn drop_(child: &Self) -> Self {
match &child.result {
Ok(child) => N::drop_(child).into(),
Err(cmr) => child.hidden_cloned_ctx(Cmr::drop(*cmr)),
}
}
fn comp(left: &Self, right: &Self) -> Result<Self, Error> {
match (&left.result, &right.result) {
(Ok(left), Ok(right)) => N::comp(left, right).map(Self::from),
_ => Ok(left.hidden_cloned_ctx(Cmr::comp(left.cmr(), right.cmr()))),
}
}
fn case(left: &Self, right: &Self) -> Result<Self, Error> {
match (&left.result, &right.result) {
(Ok(left), Ok(right)) => N::case(left, right).map(Self::from),
(Err(left), Ok(right)) => N::assertr(*left, right).map(Self::from),
(Ok(left), Err(right)) => N::assertl(left, *right).map(Self::from),
_ => Ok(left.hidden_cloned_ctx(Cmr::case(left.cmr(), right.cmr()))),
}
}
fn assertl(left: &Self, right: Cmr) -> Result<Self, Error> {
match &left.result {
Ok(left) => N::assertl(left, right).map(Self::from),
_ => Ok(left.hidden_cloned_ctx(Cmr::case(left.cmr(), right))),
}
}
fn assertr(left: Cmr, right: &Self) -> Result<Self, Error> {
match &right.result {
Ok(right) => N::assertr(left, right).map(Self::from),
_ => Ok(right.hidden_cloned_ctx(Cmr::case(left, right.cmr()))),
}
}
fn pair(left: &Self, right: &Self) -> Result<Self, Error> {
match (&left.result, &right.result) {
(Ok(left), Ok(right)) => N::pair(left, right).map(Self::from),
_ => Ok(left.hidden_cloned_ctx(Cmr::pair(left.cmr(), right.cmr()))),
}
}
fn fail(inference_context: &Context<'brand>, entropy: FailEntropy) -> Self {
N::fail(inference_context, entropy).into()
}
fn const_word(inference_context: &Context<'brand>, word: Word) -> Self {
N::const_word(inference_context, word).into()
}
fn inference_context(&self) -> &Context<'brand> {
&self.ctx
}
}
impl<'brand, J, N> JetConstructible<'brand, J> for Hiding<'brand, N>
where
N: JetConstructible<'brand, J> + CoreConstructible<'brand>,
{
fn jet(inference_context: &Context<'brand>, jet: J) -> Self {
N::jet(inference_context, jet).into()
}
}
impl<'brand, X, N> DisconnectConstructible<'brand, Option<X>> for Hiding<'brand, N>
where
N: DisconnectConstructible<'brand, Option<X>> + CoreConstructible<'brand> + HasCmr,
{
fn disconnect(left: &Self, right: &Option<X>) -> Result<Self, Error> {
match &left.result {
Ok(left) => N::disconnect(left, right).map(Self::from),
Err(..) => Ok(left.hidden_cloned_ctx(Cmr::disconnect(left.cmr()))),
}
}
}
impl<'brand, W, N> WitnessConstructible<'brand, W> for Hiding<'brand, N>
where
N: WitnessConstructible<'brand, W> + CoreConstructible<'brand>,
{
fn witness(inference_context: &Context<'brand>, witness: W) -> Self {
N::witness(inference_context, witness).into()
}
}