1use super::{Disconnectable, FailEntropy};
4use crate::dag::Dag;
5use crate::Cmr;
6
7use crate::value::Word;
8use std::fmt;
9use std::sync::Arc;
10
11#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
16pub enum Inner<C, J, X, W> {
17 Iden,
19 Unit,
21 InjL(C),
23 InjR(C),
25 Take(C),
27 Drop(C),
29 Comp(C, C),
31 Case(C, C),
33 AssertL(C, Cmr),
35 AssertR(Cmr, C),
37 Pair(C, C),
39 Disconnect(C, X),
41 Witness(W),
43 Fail(FailEntropy),
45 Jet(J),
47 Word(Word),
49}
50
51impl<C, J: Clone, X, W> Inner<C, J, X, W> {
52 pub fn map<D, F: FnMut(C) -> D>(self, mut f: F) -> Inner<D, J, X, W> {
54 match self {
55 Inner::Iden => Inner::Iden,
56 Inner::Unit => Inner::Unit,
57 Inner::InjL(c) => Inner::InjL(f(c)),
58 Inner::InjR(c) => Inner::InjR(f(c)),
59 Inner::Take(c) => Inner::Take(f(c)),
60 Inner::Drop(c) => Inner::Drop(f(c)),
61 Inner::Comp(cl, cr) => Inner::Comp(f(cl), f(cr)),
62 Inner::Case(cl, cr) => Inner::Case(f(cl), f(cr)),
63 Inner::AssertL(c, cmr) => Inner::AssertL(f(c), cmr),
64 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, f(c)),
65 Inner::Pair(cl, cr) => Inner::Pair(f(cl), f(cr)),
66 Inner::Disconnect(cl, cr) => Inner::Disconnect(f(cl), cr),
67 Inner::Witness(w) => Inner::Witness(w),
68 Inner::Fail(entropy) => Inner::Fail(entropy),
69 Inner::Jet(j) => Inner::Jet(j),
70 Inner::Word(w) => Inner::Word(w),
71 }
72 }
73
74 pub fn map_result<D, E, F: FnMut(C) -> Result<D, E>>(
76 self,
77 mut f: F,
78 ) -> Result<Inner<D, J, X, W>, E> {
79 Ok(match self {
80 Inner::Iden => Inner::Iden,
81 Inner::Unit => Inner::Unit,
82 Inner::InjL(c) => Inner::InjL(f(c)?),
83 Inner::InjR(c) => Inner::InjR(f(c)?),
84 Inner::Take(c) => Inner::Take(f(c)?),
85 Inner::Drop(c) => Inner::Drop(f(c)?),
86 Inner::Comp(cl, cr) => Inner::Comp(f(cl)?, f(cr)?),
87 Inner::Case(cl, cr) => Inner::Case(f(cl)?, f(cr)?),
88 Inner::AssertL(c, cmr) => Inner::AssertL(f(c)?, cmr),
89 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, f(c)?),
90 Inner::Pair(cl, cr) => Inner::Pair(f(cl)?, f(cr)?),
91 Inner::Disconnect(cl, cr) => Inner::Disconnect(f(cl)?, cr),
92 Inner::Witness(w) => Inner::Witness(w),
93 Inner::Fail(entropy) => Inner::Fail(entropy),
94 Inner::Jet(j) => Inner::Jet(j),
95 Inner::Word(w) => Inner::Word(w),
96 })
97 }
98
99 pub fn map_left_right<D, FL, FR>(self, fl: FL, fr: FR) -> Inner<D, J, X, W>
106 where
107 FL: FnOnce(C) -> D,
108 FR: FnOnce(C) -> D,
109 {
110 match self {
111 Inner::Iden => Inner::Iden,
112 Inner::Unit => Inner::Unit,
113 Inner::InjL(c) => Inner::InjL(fl(c)),
114 Inner::InjR(c) => Inner::InjR(fl(c)),
115 Inner::Take(c) => Inner::Take(fl(c)),
116 Inner::Drop(c) => Inner::Drop(fl(c)),
117 Inner::Comp(cl, cr) => Inner::Comp(fl(cl), fr(cr)),
118 Inner::Case(cl, cr) => Inner::Case(fl(cl), fr(cr)),
119 Inner::AssertL(c, cmr) => Inner::AssertL(fl(c), cmr),
120 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, fl(c)),
121 Inner::Pair(cl, cr) => Inner::Pair(fl(cl), fr(cr)),
122 Inner::Disconnect(cl, cr) => Inner::Disconnect(fl(cl), cr),
123 Inner::Witness(w) => Inner::Witness(w),
124 Inner::Fail(entropy) => Inner::Fail(entropy),
125 Inner::Jet(j) => Inner::Jet(j),
126 Inner::Word(w) => Inner::Word(w),
127 }
128 }
129
130 pub fn as_ref(&self) -> Inner<&C, J, &X, &W> {
132 match self {
133 Inner::Iden => Inner::Iden,
134 Inner::Unit => Inner::Unit,
135 Inner::InjL(c) => Inner::InjL(c),
136 Inner::InjR(c) => Inner::InjR(c),
137 Inner::Take(c) => Inner::Take(c),
138 Inner::Drop(c) => Inner::Drop(c),
139 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
140 Inner::Case(cl, cr) => Inner::Case(cl, cr),
141 Inner::AssertL(c, cmr) => Inner::AssertL(c, *cmr),
142 Inner::AssertR(cmr, c) => Inner::AssertR(*cmr, c),
143 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
144 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl, cr),
145 Inner::Witness(w) => Inner::Witness(w),
146 Inner::Fail(entropy) => Inner::Fail(*entropy),
147 Inner::Jet(j) => Inner::Jet(j.clone()),
148 Inner::Word(w) => Inner::Word(w.shallow_clone()),
149 }
150 }
151
152 pub fn disconnect_as_ref(&self) -> Inner<C, J, &X, W>
154 where
155 J: Copy,
156 C: Copy,
157 W: Copy,
158 {
159 match *self {
160 Inner::Iden => Inner::Iden,
161 Inner::Unit => Inner::Unit,
162 Inner::InjL(c) => Inner::InjL(c),
163 Inner::InjR(c) => Inner::InjR(c),
164 Inner::Take(c) => Inner::Take(c),
165 Inner::Drop(c) => Inner::Drop(c),
166 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
167 Inner::Case(cl, cr) => Inner::Case(cl, cr),
168 Inner::AssertL(c, cmr) => Inner::AssertL(c, cmr),
169 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c),
170 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
171 Inner::Disconnect(cl, ref cr) => Inner::Disconnect(cl, cr),
172 Inner::Witness(w) => Inner::Witness(w),
173 Inner::Fail(entropy) => Inner::Fail(entropy),
174 Inner::Jet(j) => Inner::Jet(j),
175 Inner::Word(ref w) => Inner::Word(w.shallow_clone()),
176 }
177 }
178
179 pub fn map_disconnect<Y, F: FnOnce(X) -> Y>(self, f: F) -> Inner<C, J, Y, W> {
180 match self {
181 Inner::Iden => Inner::Iden,
182 Inner::Unit => Inner::Unit,
183 Inner::InjL(c) => Inner::InjL(c),
184 Inner::InjR(c) => Inner::InjR(c),
185 Inner::Take(c) => Inner::Take(c),
186 Inner::Drop(c) => Inner::Drop(c),
187 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
188 Inner::Case(cl, cr) => Inner::Case(cl, cr),
189 Inner::AssertL(c, cmr) => Inner::AssertL(c, cmr),
190 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c),
191 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
192 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl, f(cr)),
193 Inner::Witness(w) => Inner::Witness(w),
194 Inner::Fail(entropy) => Inner::Fail(entropy),
195 Inner::Jet(j) => Inner::Jet(j),
196 Inner::Word(w) => Inner::Word(w),
197 }
198 }
199
200 pub fn map_disconnect_result<Y, E, F: FnOnce(X) -> Result<Y, E>>(
202 self,
203 f: F,
204 ) -> Result<Inner<C, J, Y, W>, E> {
205 Ok(match self {
206 Inner::Iden => Inner::Iden,
207 Inner::Unit => Inner::Unit,
208 Inner::InjL(c) => Inner::InjL(c),
209 Inner::InjR(c) => Inner::InjR(c),
210 Inner::Take(c) => Inner::Take(c),
211 Inner::Drop(c) => Inner::Drop(c),
212 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
213 Inner::Case(cl, cr) => Inner::Case(cl, cr),
214 Inner::AssertL(c, cmr) => Inner::AssertL(c, cmr),
215 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c),
216 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
217 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl, f(cr)?),
218 Inner::Witness(w) => Inner::Witness(w),
219 Inner::Fail(entropy) => Inner::Fail(entropy),
220 Inner::Jet(j) => Inner::Jet(j),
221 Inner::Word(w) => Inner::Word(w),
222 })
223 }
224
225 pub fn map_witness<V, F: FnOnce(W) -> V>(self, f: F) -> Inner<C, J, X, V> {
227 match self {
228 Inner::Iden => Inner::Iden,
229 Inner::Unit => Inner::Unit,
230 Inner::InjL(c) => Inner::InjL(c),
231 Inner::InjR(c) => Inner::InjR(c),
232 Inner::Take(c) => Inner::Take(c),
233 Inner::Drop(c) => Inner::Drop(c),
234 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
235 Inner::Case(cl, cr) => Inner::Case(cl, cr),
236 Inner::AssertL(c, cmr) => Inner::AssertL(c, cmr),
237 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c),
238 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
239 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl, cr),
240 Inner::Witness(w) => Inner::Witness(f(w)),
241 Inner::Fail(entropy) => Inner::Fail(entropy),
242 Inner::Jet(j) => Inner::Jet(j),
243 Inner::Word(w) => Inner::Word(w),
244 }
245 }
246
247 pub fn map_witness_result<V, E, F: FnOnce(W) -> Result<V, E>>(
249 self,
250 f: F,
251 ) -> Result<Inner<C, J, X, V>, E> {
252 Ok(match self {
253 Inner::Iden => Inner::Iden,
254 Inner::Unit => Inner::Unit,
255 Inner::InjL(c) => Inner::InjL(c),
256 Inner::InjR(c) => Inner::InjR(c),
257 Inner::Take(c) => Inner::Take(c),
258 Inner::Drop(c) => Inner::Drop(c),
259 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
260 Inner::Case(cl, cr) => Inner::Case(cl, cr),
261 Inner::AssertL(c, cmr) => Inner::AssertL(c, cmr),
262 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c),
263 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
264 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl, cr),
265 Inner::Witness(w) => Inner::Witness(f(w)?),
266 Inner::Fail(entropy) => Inner::Fail(entropy),
267 Inner::Jet(j) => Inner::Jet(j),
268 Inner::Word(w) => Inner::Word(w),
269 })
270 }
271}
272
273impl<C, J, X: Disconnectable<C>, W> Inner<Arc<C>, J, X, W> {
274 pub fn as_dag(&self) -> Dag<&C> {
276 match self {
277 Inner::Iden
278 | Inner::Unit
279 | Inner::Witness(_)
280 | Inner::Fail(_)
281 | Inner::Jet(_)
282 | Inner::Word(_) => Dag::Nullary,
283 Inner::InjL(c)
284 | Inner::InjR(c)
285 | Inner::Take(c)
286 | Inner::Drop(c)
287 | Inner::AssertL(c, _)
288 | Inner::AssertR(_, c) => Dag::Unary(c),
289 Inner::Comp(cl, cr) | Inner::Case(cl, cr) | Inner::Pair(cl, cr) => Dag::Binary(cl, cr),
290 Inner::Disconnect(cl, cr) => cr.disconnect_dag_ref(cl),
291 }
292 }
293}
294
295impl<C, J, X, W> Inner<Option<C>, J, X, W> {
296 pub fn transpose(self) -> Option<Inner<C, J, X, W>> {
298 Some(match self {
299 Inner::Iden => Inner::Iden,
300 Inner::Unit => Inner::Unit,
301 Inner::InjL(c) => Inner::InjL(c?),
302 Inner::InjR(c) => Inner::InjR(c?),
303 Inner::Take(c) => Inner::Take(c?),
304 Inner::Drop(c) => Inner::Drop(c?),
305 Inner::Comp(cl, cr) => Inner::Comp(cl?, cr?),
306 Inner::Case(cl, cr) => Inner::Case(cl?, cr?),
307 Inner::AssertL(c, cmr) => Inner::AssertL(c?, cmr),
308 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c?),
309 Inner::Pair(cl, cr) => Inner::Pair(cl?, cr?),
310 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl?, cr),
311 Inner::Witness(w) => Inner::Witness(w),
312 Inner::Fail(entropy) => Inner::Fail(entropy),
313 Inner::Jet(j) => Inner::Jet(j),
314 Inner::Word(w) => Inner::Word(w),
315 })
316 }
317}
318
319impl<C, J, X, W> Inner<C, J, Option<X>, W> {
320 pub fn transpose_disconnect(self) -> Option<Inner<C, J, X, W>> {
322 Some(match self {
323 Inner::Iden => Inner::Iden,
324 Inner::Unit => Inner::Unit,
325 Inner::InjL(c) => Inner::InjL(c),
326 Inner::InjR(c) => Inner::InjR(c),
327 Inner::Take(c) => Inner::Take(c),
328 Inner::Drop(c) => Inner::Drop(c),
329 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
330 Inner::Case(cl, cr) => Inner::Case(cl, cr),
331 Inner::AssertL(c, cmr) => Inner::AssertL(c, cmr),
332 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c),
333 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
334 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl, cr?),
335 Inner::Witness(w) => Inner::Witness(w),
336 Inner::Fail(entropy) => Inner::Fail(entropy),
337 Inner::Jet(j) => Inner::Jet(j),
338 Inner::Word(w) => Inner::Word(w),
339 })
340 }
341}
342
343impl<C, J, X, W> Inner<C, J, X, Option<W>> {
344 pub fn transpose_witness(self) -> Option<Inner<C, J, X, W>> {
346 Some(match self {
347 Inner::Iden => Inner::Iden,
348 Inner::Unit => Inner::Unit,
349 Inner::InjL(c) => Inner::InjL(c),
350 Inner::InjR(c) => Inner::InjR(c),
351 Inner::Take(c) => Inner::Take(c),
352 Inner::Drop(c) => Inner::Drop(c),
353 Inner::Comp(cl, cr) => Inner::Comp(cl, cr),
354 Inner::Case(cl, cr) => Inner::Case(cl, cr),
355 Inner::AssertL(c, cmr) => Inner::AssertL(c, cmr),
356 Inner::AssertR(cmr, c) => Inner::AssertR(cmr, c),
357 Inner::Pair(cl, cr) => Inner::Pair(cl, cr),
358 Inner::Disconnect(cl, cr) => Inner::Disconnect(cl, cr),
359 Inner::Witness(w) => Inner::Witness(w?),
360 Inner::Fail(entropy) => Inner::Fail(entropy),
361 Inner::Jet(j) => Inner::Jet(j),
362 Inner::Word(w) => Inner::Word(w),
363 })
364 }
365}
366
367impl<C, J: Clone, X, W: Copy> Inner<C, J, X, &W> {
368 pub fn copy_witness(self) -> Inner<C, J, X, W> {
373 self.map_witness(W::clone)
374 }
375}
376
377impl<C, J: Clone, X: Copy, W> Inner<C, J, &X, W> {
378 pub fn copy_disconnect(self) -> Inner<C, J, X, W> {
383 self.map_disconnect(X::clone)
384 }
385}
386
387impl<C, J: fmt::Display, X, W> fmt::Display for Inner<C, J, X, W> {
388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389 match self {
390 Inner::Iden => f.write_str("iden"),
391 Inner::Unit => f.write_str("unit"),
392 Inner::InjL(_) => f.write_str("injl"),
393 Inner::InjR(_) => f.write_str("injr"),
394 Inner::Take(_) => f.write_str("take"),
395 Inner::Drop(_) => f.write_str("drop"),
396 Inner::Comp(_, _) => f.write_str("comp"),
397 Inner::Case(_, _) => f.write_str("case"),
398 Inner::AssertL(_, _) => f.write_str("assertl"),
399 Inner::AssertR(_, _) => f.write_str("assertr"),
400 Inner::Pair(_, _) => f.write_str("pair"),
401 Inner::Disconnect(_, _) => f.write_str("disconnect"),
402 Inner::Witness(..) => f.write_str("witness"),
403 Inner::Fail(..) => f.write_str("fail"),
404 Inner::Jet(jet) => write!(f, "jet({})", jet),
405 Inner::Word(w) => write!(f, "word({})", w),
406 }
407 }
408}