1use crate::jet::Jet;
2use crate::node::{CoreConstructible, DisconnectConstructible, WitnessConstructible};
3use crate::types::{Arrow, Context, Error};
4use crate::{Cmr, FailEntropy, HasCmr, Word};
5
6#[derive(Clone, Debug)]
7enum HidingInner<'brand, N> {
8 Node(N),
9 Hidden { cmr: Cmr, arrow: Arrow<'brand> },
10}
11
12#[derive(Clone, Debug)]
40pub struct Hiding<'brand, N> {
41 inner: HidingInner<'brand, N>,
42}
43
44impl<'brand, N> Hiding<'brand, N> {
45 pub fn hidden(cmr: Cmr, ctx: &Context<'brand>) -> Self {
50 Self {
51 inner: HidingInner::Hidden {
52 cmr,
53 arrow: Arrow::hidden(ctx),
54 },
55 }
56 }
57
58 #[inline]
61 pub fn map_ref<M>(
62 &self,
63 mapfn: impl FnOnce(&N) -> M,
64 cmrfn: impl FnOnce(Cmr) -> Cmr,
65 ) -> Hiding<'brand, M> {
66 use core::convert::Infallible;
67 match self.map_ref_result::<_, Infallible>(|node| Ok(mapfn(node)), cmrfn) {
68 Ok(res) => res,
69 Err(inf) => match inf {},
70 }
71 }
72
73 #[inline]
76 pub fn map_ref_result<M, Err>(
77 &self,
78 mapfn: impl FnOnce(&N) -> Result<M, Err>,
79 cmrfn: impl FnOnce(Cmr) -> Cmr,
80 ) -> Result<Hiding<'brand, M>, Err> {
81 Ok(Hiding {
82 inner: match self.inner {
83 HidingInner::Node(ref n) => HidingInner::Node(mapfn(n)?),
84 HidingInner::Hidden { cmr, ref arrow } => HidingInner::Hidden {
85 cmr: cmrfn(cmr),
86 arrow: Arrow::hidden(arrow.inference_context()),
87 },
88 },
89 })
90 }
91
92 pub fn as_node(&self) -> Option<&N> {
96 match self.inner {
97 HidingInner::Node(ref n) => Some(n),
98 HidingInner::Hidden { .. } => None,
99 }
100 }
101
102 pub fn into_node(self) -> Option<N> {
106 match self.inner {
107 HidingInner::Node(n) => Some(n),
108 HidingInner::Hidden { .. } => None,
109 }
110 }
111}
112
113impl<'brand, N: HasCmr + CoreConstructible<'brand>> Hiding<'brand, N> {
114 fn zip_ref<M: CoreConstructible<'brand>>(
120 &self,
121 other: &Self,
122 node_zipfn: impl FnOnce(&N, &N) -> Result<M, Error>,
123 cmr_zipfn: impl FnOnce(Cmr, Cmr) -> Cmr,
124 ) -> Result<Hiding<'brand, M>, Error> {
125 Ok(Hiding {
126 inner: match (&self.inner, &other.inner) {
127 (HidingInner::Node(ref left), HidingInner::Node(ref right)) => {
128 node_zipfn(left, right).map(HidingInner::Node)?
129 }
130 _ => {
131 self.inference_context()
132 .check_eq(other.inference_context())?;
133 HidingInner::Hidden {
134 cmr: cmr_zipfn(self.cmr(), other.cmr()),
135 arrow: Arrow::hidden(self.inference_context()),
136 }
137 }
138 },
139 })
140 }
141
142 pub fn hide(self) -> Self {
148 match self.inner {
149 HidingInner::Node(node) => Self {
150 inner: HidingInner::Hidden {
151 cmr: node.cmr(),
152 arrow: Arrow::hidden(node.inference_context()),
153 },
154 },
155 HidingInner::Hidden { .. } => self,
156 }
157 }
158}
159
160impl<N: HasCmr> HasCmr for Hiding<'_, N> {
161 fn cmr(&self) -> Cmr {
162 match self.inner {
163 HidingInner::Node(ref node) => node.cmr(),
164 HidingInner::Hidden { cmr, .. } => cmr,
165 }
166 }
167}
168
169impl<'brand, N> From<N> for Hiding<'brand, N> {
170 fn from(node: N) -> Self {
171 Self {
172 inner: HidingInner::Node(node),
173 }
174 }
175}
176
177impl<'brand, N: HasCmr + CoreConstructible<'brand>> CoreConstructible<'brand>
180 for Hiding<'brand, N>
181{
182 fn iden(inference_context: &Context<'brand>) -> Self {
183 N::iden(inference_context).into()
184 }
185
186 fn unit(inference_context: &Context<'brand>) -> Self {
187 N::unit(inference_context).into()
188 }
189
190 fn injl(child: &Self) -> Self {
191 child.map_ref(N::injl, Cmr::injl)
192 }
193
194 fn injr(child: &Self) -> Self {
195 child.map_ref(N::injr, Cmr::injr)
196 }
197
198 fn take(child: &Self) -> Self {
199 child.map_ref(N::take, Cmr::take)
200 }
201
202 fn drop_(child: &Self) -> Self {
203 child.map_ref(N::drop_, Cmr::drop)
204 }
205
206 fn comp(left: &Self, right: &Self) -> Result<Self, Error> {
207 left.zip_ref(right, N::comp, Cmr::comp)
208 }
209
210 fn case(left: &Self, right: &Self) -> Result<Self, Error> {
211 use HidingInner as I;
212
213 left.inference_context()
214 .check_eq(right.inference_context())?;
215 let inner = match (&left.inner, &right.inner) {
216 (I::Node(left), I::Node(right)) => I::Node(N::case(left, right)?),
217 (I::Hidden { cmr, .. }, I::Node(right)) => I::Node(N::assertr(*cmr, right)?),
218 (I::Node(left), I::Hidden { cmr, .. }) => I::Node(N::assertl(left, *cmr)?),
219 (I::Hidden { cmr: l_cmr, .. }, I::Hidden { cmr: r_cmr, .. }) => I::Hidden {
220 cmr: Cmr::case(*l_cmr, *r_cmr),
221 arrow: Arrow::hidden(left.inference_context()),
222 },
223 };
224
225 Ok(Self { inner })
226 }
227
228 fn assertl(left: &Self, right: Cmr) -> Result<Self, Error> {
229 left.map_ref_result(
230 |left| N::assertl(left, right),
231 |lcmr| Cmr::case(lcmr, right),
232 )
233 }
234
235 fn assertr(left: Cmr, right: &Self) -> Result<Self, Error> {
236 right.map_ref_result(
237 |right| N::assertr(left, right),
238 |rcmr| Cmr::case(left, rcmr),
239 )
240 }
241
242 fn pair(left: &Self, right: &Self) -> Result<Self, Error> {
243 left.zip_ref(right, N::pair, Cmr::pair)
244 }
245
246 fn fail(inference_context: &Context<'brand>, entropy: FailEntropy) -> Self {
247 N::fail(inference_context, entropy).into()
248 }
249
250 fn const_word(inference_context: &Context<'brand>, word: Word) -> Self {
251 N::const_word(inference_context, word).into()
252 }
253
254 fn jet(inference_context: &Context<'brand>, jet: &dyn Jet) -> Self {
255 N::jet(inference_context, jet).into()
256 }
257
258 fn arrow(&self) -> &Arrow<'brand> {
259 match self.inner {
260 HidingInner::Node(ref node) => node.arrow(),
261 HidingInner::Hidden { ref arrow, .. } => arrow,
262 }
263 }
264}
265
266impl<'brand, X, N> DisconnectConstructible<'brand, Option<X>> for Hiding<'brand, N>
267where
268 N: DisconnectConstructible<'brand, Option<X>> + CoreConstructible<'brand> + HasCmr,
269{
270 fn disconnect(left: &Self, right: &Option<X>) -> Result<Self, Error> {
271 left.map_ref_result(|left| N::disconnect(left, right), Cmr::disconnect)
272 }
273}
274
275impl<'brand, W, N> WitnessConstructible<'brand, W> for Hiding<'brand, N>
276where
277 N: WitnessConstructible<'brand, W> + CoreConstructible<'brand>,
278{
279 fn witness(inference_context: &Context<'brand>, witness: W) -> Self {
280 N::witness(inference_context, witness).into()
281 }
282}