Skip to main content

mdnt_groups_support/
lib.rs

1#![doc = include_str!("../README.md")]
2//!
3//! Includes some implementations of the [`DecomposeIn<Cell>`] trait for standard
4//! types but is not exhaustive. The implemented types cover the needs of the
5//! circuits crate.
6//!
7//! If other external types are required their implementation should be added to
8//! this crate.
9
10#![deny(rustdoc::broken_intra_doc_links)]
11#![deny(missing_debug_implementations)]
12#![deny(missing_docs)]
13
14/// Implementations of this trait represent complex types that aggregate a
15/// collection of `AssignedCell` values.
16pub trait DecomposeIn<Cell> {
17    /// Returns an iterator of `Cell` instances.
18    fn cells(&self) -> impl IntoIterator<Item = Cell>;
19}
20
21impl<Cell> DecomposeIn<Cell> for u32 {
22    fn cells(&self) -> impl IntoIterator<Item = Cell> {
23        std::iter::empty()
24    }
25}
26
27impl<Cell, T: DecomposeIn<Cell>> DecomposeIn<Cell> for &T {
28    fn cells(&self) -> impl IntoIterator<Item = Cell> {
29        (*self).cells()
30    }
31}
32
33impl<Cell, T: DecomposeIn<Cell>, E> DecomposeIn<Cell> for Result<T, E> {
34    fn cells(&self) -> impl IntoIterator<Item = Cell> {
35        self.iter().flat_map(|t| t.cells())
36    }
37}
38
39impl<Cell, T: DecomposeIn<Cell>> DecomposeIn<Cell> for Option<T> {
40    fn cells(&self) -> impl IntoIterator<Item = Cell> {
41        self.iter().flat_map(|t| t.cells())
42    }
43}
44
45impl<Cell, T: DecomposeIn<Cell>> DecomposeIn<Cell> for &[T] {
46    fn cells(&self) -> impl IntoIterator<Item = Cell> {
47        self.iter().flat_map(|t| t.cells())
48    }
49}
50
51impl<Cell, T: DecomposeIn<Cell>, const N: usize> DecomposeIn<Cell> for [T; N] {
52    fn cells(&self) -> impl IntoIterator<Item = Cell> {
53        self.iter().flat_map(|t| t.cells())
54    }
55}
56
57impl<Cell, T: DecomposeIn<Cell>> DecomposeIn<Cell> for Vec<T> {
58    fn cells(&self) -> impl IntoIterator<Item = Cell> {
59        self.iter().flat_map(|t| t.cells())
60    }
61}
62
63macro_rules! chain {
64    () => {
65        std::iter::empty()
66    };
67    ($h:expr $(,$t:expr)* $(,)?) => {
68        $h.into_iter().chain( chain!($( $t, )*))
69    };
70}
71
72macro_rules! tuple_impl {
73    () => {
74        tuple_impl!(@impl [] [] [A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12] [0 1 2 3 4 5 6 7 8 9 10 11]);
75    };
76
77    (@impl [$($done:ident)*] [$($idxs:tt)*] [$head:ident $($rest:ident)*] [$i:tt $($is:tt)*]) => {
78        //// Implement for tuple ($head, $done...)
79        impl<Cell, $head: DecomposeIn<Cell>, $( $done: DecomposeIn<Cell>, )*> DecomposeIn<Cell> for (
80                $head, $( $done, )*
81            )
82        {
83            fn cells(&self) -> impl IntoIterator<Item = Cell> {
84                chain!($(
85                    self.$idxs.cells(),
86                )*
87                self.$i.cells())
88            }
89        }
90
91        // Recurse
92        tuple_impl!(
93            @impl [$head $($done)*] [$($idxs)* $i] [$($rest)*] [$($is)*]
94        );
95    };
96
97    // Stop when no identifiers remain
98    (@impl [$($done:ident)*] [$($idxs:tt)*] [] $rem:tt) => {
99        // Also emit the 0-tuple base case
100        impl<Cell> DecomposeIn<Cell> for () {
101            fn cells(&self) -> impl IntoIterator<Item = Cell> {
102                std::iter::empty()
103            }
104        }
105    };
106
107}
108
109tuple_impl!();