summaryrefslogtreecommitdiffstats
path: root/third_party/rust/warp/src/generic.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/warp/src/generic.rs')
-rw-r--r--third_party/rust/warp/src/generic.rs250
1 files changed, 250 insertions, 0 deletions
diff --git a/third_party/rust/warp/src/generic.rs b/third_party/rust/warp/src/generic.rs
new file mode 100644
index 0000000000..5350d22156
--- /dev/null
+++ b/third_party/rust/warp/src/generic.rs
@@ -0,0 +1,250 @@
+#[derive(Debug)]
+pub struct Product<H, T: HList>(pub(crate) H, pub(crate) T);
+
+pub type One<T> = (T,);
+
+#[inline]
+pub(crate) fn one<T>(val: T) -> One<T> {
+ (val,)
+}
+
+#[derive(Debug)]
+pub enum Either<T, U> {
+ A(T),
+ B(U),
+}
+
+// Converts Product (and ()) into tuples.
+pub trait HList: Sized {
+ type Tuple: Tuple<HList = Self>;
+
+ fn flatten(self) -> Self::Tuple;
+}
+
+// Typeclass that tuples can be converted into a Product (or unit ()).
+pub trait Tuple: Sized {
+ type HList: HList<Tuple = Self>;
+
+ fn hlist(self) -> Self::HList;
+
+ #[inline]
+ fn combine<T>(self, other: T) -> CombinedTuples<Self, T>
+ where
+ Self: Sized,
+ T: Tuple,
+ Self::HList: Combine<T::HList>,
+ {
+ self.hlist().combine(other.hlist()).flatten()
+ }
+}
+
+pub type CombinedTuples<T, U> =
+ <<<T as Tuple>::HList as Combine<<U as Tuple>::HList>>::Output as HList>::Tuple;
+
+// Combines Product together.
+pub trait Combine<T: HList> {
+ type Output: HList;
+
+ fn combine(self, other: T) -> Self::Output;
+}
+
+pub trait Func<Args> {
+ type Output;
+
+ fn call(&self, args: Args) -> Self::Output;
+}
+
+// ===== impl Combine =====
+
+impl<T: HList> Combine<T> for () {
+ type Output = T;
+ #[inline]
+ fn combine(self, other: T) -> Self::Output {
+ other
+ }
+}
+
+impl<H, T: HList, U: HList> Combine<U> for Product<H, T>
+where
+ T: Combine<U>,
+ Product<H, <T as Combine<U>>::Output>: HList,
+{
+ type Output = Product<H, <T as Combine<U>>::Output>;
+
+ #[inline]
+ fn combine(self, other: U) -> Self::Output {
+ Product(self.0, self.1.combine(other))
+ }
+}
+
+impl HList for () {
+ type Tuple = ();
+ #[inline]
+ fn flatten(self) -> Self::Tuple {}
+}
+
+impl Tuple for () {
+ type HList = ();
+
+ #[inline]
+ fn hlist(self) -> Self::HList {}
+}
+
+impl<F, R> Func<()> for F
+where
+ F: Fn() -> R,
+{
+ type Output = R;
+
+ #[inline]
+ fn call(&self, _args: ()) -> Self::Output {
+ (*self)()
+ }
+}
+
+impl<F, R> Func<crate::Rejection> for F
+where
+ F: Fn(crate::Rejection) -> R,
+{
+ type Output = R;
+
+ #[inline]
+ fn call(&self, arg: crate::Rejection) -> Self::Output {
+ (*self)(arg)
+ }
+}
+
+macro_rules! product {
+ ($H:expr) => { Product($H, ()) };
+ ($H:expr, $($T:expr),*) => { Product($H, product!($($T),*)) };
+}
+
+macro_rules! Product {
+ ($H:ty) => { Product<$H, ()> };
+ ($H:ty, $($T:ty),*) => { Product<$H, Product!($($T),*)> };
+}
+
+macro_rules! product_pat {
+ ($H:pat) => { Product($H, ()) };
+ ($H:pat, $($T:pat),*) => { Product($H, product_pat!($($T),*)) };
+}
+
+macro_rules! generics {
+ ($type:ident) => {
+ impl<$type> HList for Product!($type) {
+ type Tuple = ($type,);
+
+ #[inline]
+ fn flatten(self) -> Self::Tuple {
+ (self.0,)
+ }
+ }
+
+ impl<$type> Tuple for ($type,) {
+ type HList = Product!($type);
+ #[inline]
+ fn hlist(self) -> Self::HList {
+ product!(self.0)
+ }
+ }
+
+ impl<F, R, $type> Func<Product!($type)> for F
+ where
+ F: Fn($type) -> R,
+ {
+ type Output = R;
+
+ #[inline]
+ fn call(&self, args: Product!($type)) -> Self::Output {
+ (*self)(args.0)
+ }
+
+ }
+
+ impl<F, R, $type> Func<($type,)> for F
+ where
+ F: Fn($type) -> R,
+ {
+ type Output = R;
+
+ #[inline]
+ fn call(&self, args: ($type,)) -> Self::Output {
+ (*self)(args.0)
+ }
+ }
+
+ };
+
+ ($type1:ident, $( $type:ident ),*) => {
+ generics!($( $type ),*);
+
+ impl<$type1, $( $type ),*> HList for Product!($type1, $($type),*) {
+ type Tuple = ($type1, $( $type ),*);
+
+ #[inline]
+ fn flatten(self) -> Self::Tuple {
+ #[allow(non_snake_case)]
+ let product_pat!($type1, $( $type ),*) = self;
+ ($type1, $( $type ),*)
+ }
+ }
+
+ impl<$type1, $( $type ),*> Tuple for ($type1, $($type),*) {
+ type HList = Product!($type1, $( $type ),*);
+
+ #[inline]
+ fn hlist(self) -> Self::HList {
+ #[allow(non_snake_case)]
+ let ($type1, $( $type ),*) = self;
+ product!($type1, $( $type ),*)
+ }
+ }
+
+ impl<F, R, $type1, $( $type ),*> Func<Product!($type1, $($type),*)> for F
+ where
+ F: Fn($type1, $( $type ),*) -> R,
+ {
+ type Output = R;
+
+ #[inline]
+ fn call(&self, args: Product!($type1, $($type),*)) -> Self::Output {
+ #[allow(non_snake_case)]
+ let product_pat!($type1, $( $type ),*) = args;
+ (*self)($type1, $( $type ),*)
+ }
+ }
+
+ impl<F, R, $type1, $( $type ),*> Func<($type1, $($type),*)> for F
+ where
+ F: Fn($type1, $( $type ),*) -> R,
+ {
+ type Output = R;
+
+ #[inline]
+ fn call(&self, args: ($type1, $($type),*)) -> Self::Output {
+ #[allow(non_snake_case)]
+ let ($type1, $( $type ),*) = args;
+ (*self)($type1, $( $type ),*)
+ }
+ }
+ };
+}
+
+generics! {
+ T1,
+ T2,
+ T3,
+ T4,
+ T5,
+ T6,
+ T7,
+ T8,
+ T9,
+ T10,
+ T11,
+ T12,
+ T13,
+ T14,
+ T15,
+ T16
+}