Compare commits
1 Commits
tuple_expe
...
tuple_atte
| Author | SHA1 | Date | |
|---|---|---|---|
| 14435de6a5 |
@@ -2,8 +2,7 @@ use std::ops::Range;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
primitive::{Axis, Painter, RoundedRectData, UIRegion},
|
primitive::{Axis, Painter, RoundedRectData, UIRegion},
|
||||||
ToId, UIColor, Widget, WidgetArrLike, WidgetFn, WidgetId, WidgetIdLikeTuple, WidgetLike,
|
UIColor, Widget, WidgetArrLike, WidgetFn, WidgetId, WidgetLike,
|
||||||
WidgetLikeTuple,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -50,18 +49,20 @@ impl Widget for Span {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
pub fn proportioned<const LEN: usize>(
|
pub fn proportioned(
|
||||||
axis: Axis,
|
axis: Axis,
|
||||||
ratios: [impl UINum; LEN],
|
elements: impl IntoIterator<Item = (WidgetId, impl UINum)>,
|
||||||
elements: [WidgetId; LEN],
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ratios = ratios.map(|r| r.to_f32());
|
// TODO: update
|
||||||
let total: f32 = ratios.iter().sum();
|
let elements = elements
|
||||||
|
.into_iter()
|
||||||
|
.map(|(w, r)| (w, r.to_f32()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let total: f32 = elements.iter().map(|(_, r)| r).sum();
|
||||||
let mut start = 0.0;
|
let mut start = 0.0;
|
||||||
Self {
|
Self {
|
||||||
elements: elements
|
elements: elements
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(ratios)
|
|
||||||
.map(|(e, r)| {
|
.map(|(e, r)| {
|
||||||
let end = start + r / total;
|
let end = start + r / total;
|
||||||
let res = (start..end, e);
|
let res = (start..end, e);
|
||||||
@@ -118,29 +119,26 @@ impl<T: UINum> From<T> for Padding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WidgetUtil {
|
pub trait WidgetUtil<W> {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Widget = Regioned>;
|
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Widget = Regioned>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: WidgetLike> WidgetUtil for W {
|
impl<W: WidgetLike> WidgetUtil<W::Widget> for W {
|
||||||
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Widget = Regioned> {
|
fn pad(self, padding: impl Into<Padding>) -> impl WidgetLike<Widget = Regioned> {
|
||||||
WidgetFn(|ui| Regioned {
|
WidgetFn(|ui| Regioned {
|
||||||
region: padding.into().region(),
|
region: padding.into().region(),
|
||||||
inner: self.add(ui).erase_type(),
|
inner: self.id(ui).erase_type(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WidgetArrUtil<const LEN: usize> {
|
pub trait WidgetArrUtil<Wa: WidgetArrLike> {
|
||||||
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Widget = Span>;
|
fn span(self, axis: Axis, ratios: [impl UINum; Wa::LEN]) -> impl WidgetLike<Widget = Span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const LEN: usize, Wa: WidgetArrLike<LEN>> WidgetArrUtil<LEN> for Wa
|
impl<Wa: WidgetArrLike> WidgetArrUtil<Wa> for Wa {
|
||||||
where
|
fn span(self, axis: Axis, ratios: [impl UINum; Wa::LEN]) -> impl WidgetLike<Widget = Span> {
|
||||||
<Wa::Ws as WidgetLikeTuple<LEN>>::Wrap<ToId>: WidgetIdLikeTuple<LEN>,
|
WidgetFn(move |ui| Span::proportioned(axis, self.ui(ui).ids().into_iter().zip(ratios)))
|
||||||
{
|
|
||||||
fn span(self, axis: Axis, ratios: [impl UINum; LEN]) -> impl WidgetLike<Widget = Span> {
|
|
||||||
WidgetFn(move |ui| Span::proportioned(axis, ratios, self.ui(ui).erase_types()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ impl From<UI> for UIBuilder {
|
|||||||
|
|
||||||
impl UIBuilder {
|
impl UIBuilder {
|
||||||
pub fn add<W: Widget>(&mut self, w: W) -> WidgetRef<W> {
|
pub fn add<W: Widget>(&mut self, w: W) -> WidgetRef<W> {
|
||||||
WidgetRef::new(self.clone(), (self.push(w),))
|
WidgetRef::new(self.clone(), (self.push(w), ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
||||||
@@ -42,8 +42,8 @@ impl UIBuilder {
|
|||||||
WidgetId::new(id, TypeId::of::<W>())
|
WidgetId::new(id, TypeId::of::<W>())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish<W: WidgetLike>(mut self, base: W) -> UI {
|
pub fn finish<WL: WidgetLike>(mut self, base: WL) -> UI {
|
||||||
let base = base.add(&mut self).erase_type();
|
let base = base.id(&mut self).erase_type();
|
||||||
let mut ui = Rc::into_inner(self.ui).unwrap().into_inner();
|
let mut ui = Rc::into_inner(self.ui).unwrap().into_inner();
|
||||||
ui.base = Some(base);
|
ui.base = Some(base);
|
||||||
ui
|
ui
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
primitive::Painter,
|
primitive::Painter,
|
||||||
util::{impl_tuple, ID},
|
util::{IntoTupleList, TupleList, ID},
|
||||||
UIBuilder,
|
UIBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ pub struct WidgetId<W = ()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: temp
|
// TODO: temp
|
||||||
impl<W: Widget> Clone for WidgetId<W> {
|
impl<W> Clone for WidgetId<W> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ty: self.ty,
|
ty: self.ty,
|
||||||
@@ -59,8 +59,8 @@ impl<W> WidgetId<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait WidgetLike {
|
pub trait WidgetLike {
|
||||||
type Widget: Widget;
|
type Widget;
|
||||||
fn add(self, ui: &mut UIBuilder) -> WidgetId<Self::Widget>;
|
fn id(self, ui: &mut UIBuilder) -> WidgetId<Self::Widget>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// wouldn't be needed if negative trait bounds & disjoint impls existed
|
/// wouldn't be needed if negative trait bounds & disjoint impls existed
|
||||||
@@ -68,7 +68,7 @@ pub struct WidgetFn<F: FnOnce(&mut UIBuilder) -> W, W>(pub F);
|
|||||||
|
|
||||||
impl<W: Widget, F: FnOnce(&mut UIBuilder) -> W> WidgetLike for WidgetFn<F, W> {
|
impl<W: Widget, F: FnOnce(&mut UIBuilder) -> W> WidgetLike for WidgetFn<F, W> {
|
||||||
type Widget = W;
|
type Widget = W;
|
||||||
fn add(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
fn id(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||||
let w = (self.0)(ui);
|
let w = (self.0)(ui);
|
||||||
ui.add(w).to_id()
|
ui.add(w).to_id()
|
||||||
}
|
}
|
||||||
@@ -76,103 +76,111 @@ impl<W: Widget, F: FnOnce(&mut UIBuilder) -> W> WidgetLike for WidgetFn<F, W> {
|
|||||||
|
|
||||||
impl<W: Widget> WidgetLike for W {
|
impl<W: Widget> WidgetLike for W {
|
||||||
type Widget = W;
|
type Widget = W;
|
||||||
fn add(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
fn id(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||||
ui.add(self).to_id()
|
ui.add(self).to_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> WidgetLike for WidgetId<W> {
|
impl<W> WidgetLike for WidgetId<W> {
|
||||||
type Widget = W;
|
type Widget = W;
|
||||||
fn add(self, _: &mut UIBuilder) -> WidgetId<W> {
|
fn id(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Widget> WidgetLike for WidgetArr<1, (W,)> {
|
pub struct WidgetArr<Ws: WidgetList> {
|
||||||
type Widget = W;
|
|
||||||
fn add(self, _: &mut UIBuilder) -> WidgetId<W> {
|
|
||||||
self.arr.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WidgetArr<const LEN: usize, Ws: WidgetLikeTuple<LEN>> {
|
|
||||||
pub ui: UIBuilder,
|
pub ui: UIBuilder,
|
||||||
pub arr: Ws::Wrap<ToId>,
|
pub arr: Ws::Ids,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const LEN: usize, Ws: WidgetLikeTuple<LEN>> WidgetArr<LEN, Ws>
|
impl<Ws: WidgetList> WidgetArr<Ws> {
|
||||||
where
|
pub fn new(ui: UIBuilder, arr: Ws::Ids) -> Self {
|
||||||
Ws::Wrap<ToId>: WidgetIdLikeTuple<LEN>,
|
|
||||||
{
|
|
||||||
pub fn new(ui: UIBuilder, arr: Ws::Wrap<ToId>) -> Self {
|
|
||||||
Self { ui, arr }
|
Self { ui, arr }
|
||||||
}
|
}
|
||||||
pub fn erase_types(self) -> [WidgetId; LEN] {
|
pub fn ids(self) -> Vec<WidgetId> {
|
||||||
self.arr.map::<EraseId>(&mut ())
|
self.arr.all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type WidgetRef<W> = WidgetArr<1, (W,)>;
|
pub type WidgetRef<W> = WidgetArr<(W, ())>;
|
||||||
|
|
||||||
impl<W: WidgetLike> WidgetRef<W> {
|
impl<W> WidgetRef<W> {
|
||||||
pub fn handle(&self) -> WidgetId<W::Widget> {
|
pub fn handle(&self) -> WidgetId<W> {
|
||||||
self.arr.0.clone()
|
self.arr.head().clone()
|
||||||
}
|
}
|
||||||
pub fn to_id(self) -> WidgetId<W::Widget> {
|
pub fn to_id(self) -> WidgetId<W> {
|
||||||
self.arr.0
|
self.arr.into_head()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WidgetArrLike<const LEN: usize> {
|
impl<W> WidgetLike for WidgetRef<W> {
|
||||||
type Ws: WidgetLikeTuple<LEN>;
|
type Widget = W;
|
||||||
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<LEN, Self::Ws>;
|
fn id(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||||
|
self.arr.into_head()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const LEN: usize, Ws: WidgetLikeTuple<LEN>> WidgetArrLike<LEN> for WidgetArr<LEN, Ws> {
|
pub trait WidgetArrLike {
|
||||||
|
const LEN: usize;
|
||||||
|
type Ws: WidgetList;
|
||||||
|
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<Self::Ws>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ws: WidgetList> WidgetArrLike for WidgetArr<Ws> {
|
||||||
|
const LEN: usize = Ws::LEN;
|
||||||
type Ws = Ws;
|
type Ws = Ws;
|
||||||
fn ui(self, _: &mut UIBuilder) -> WidgetArr<LEN, Ws> {
|
fn ui(self, _: &mut UIBuilder) -> WidgetArr<Ws> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_tuple!(Widget);
|
impl<W: WidgetLike> WidgetArrLike for (W, ())
|
||||||
impl_tuple!(WidgetLike);
|
|
||||||
impl_tuple!(WidgetIdLike);
|
|
||||||
|
|
||||||
pub trait WidgetIdLike {
|
|
||||||
fn erase_type(self) -> WidgetId;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W> WidgetIdLike for WidgetId<W> {
|
|
||||||
fn erase_type(self) -> WidgetId {
|
|
||||||
self.erase_type()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ToId;
|
|
||||||
impl WidgetLikeWrapper for ToId {
|
|
||||||
type Wrap<T: WidgetLike> = WidgetId<T::Widget>;
|
|
||||||
type Ctx = UIBuilder;
|
|
||||||
fn wrap<T: WidgetLike>(t: T, ctx: &mut Self::Ctx) -> Self::Wrap<T> {
|
|
||||||
t.add(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EraseId;
|
|
||||||
impl WidgetIdLikeMapper for EraseId {
|
|
||||||
type Map = WidgetId<()>;
|
|
||||||
type Ctx = ();
|
|
||||||
fn map<Id: WidgetIdLike>(t: Id, _: &mut Self::Ctx) -> Self::Map {
|
|
||||||
t.erase_type()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: WidgetLikeTuple<LEN>, const LEN: usize> WidgetArrLike<LEN> for T
|
|
||||||
where
|
where
|
||||||
T::Wrap<ToId>: WidgetIdLikeTuple<LEN>,
|
Self: TupleList,
|
||||||
{
|
{
|
||||||
type Ws = T;
|
const LEN: usize = <Self as TupleList>::LEN;
|
||||||
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<LEN, T> {
|
type Ws = (W::Widget, ());
|
||||||
WidgetArr::new(ui.clone(), self.wrap::<ToId>(ui))
|
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<(W::Widget, ())> {
|
||||||
|
WidgetArr::new(ui.clone(), (self.0.id(ui), ()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<W: WidgetLike, T: WidgetArrLike> WidgetArrLike for (W, T)
|
||||||
|
where
|
||||||
|
Self: TupleList,
|
||||||
|
{
|
||||||
|
const LEN: usize = <Self as TupleList>::LEN;
|
||||||
|
type Ws = (W::Widget, T::Ws);
|
||||||
|
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<(W::Widget, T::Ws)> {
|
||||||
|
WidgetArr::new(ui.clone(), (self.0.id(ui), self.1.ui(ui).arr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WidgetList: TupleList {
|
||||||
|
type Ids: IdList;
|
||||||
|
}
|
||||||
|
impl<H> WidgetList for (H, ()) {
|
||||||
|
type Ids = (WidgetId<H>, ());
|
||||||
|
}
|
||||||
|
impl<H, T: WidgetList> WidgetList for (H, T) {
|
||||||
|
type Ids = (WidgetId<H>, T::Ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait IdList: TupleList {
|
||||||
|
fn iter(self) -> impl Iterator<Item = WidgetId>;
|
||||||
|
fn all(self) -> Vec<WidgetId>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.iter().collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<H> IdList for (WidgetId<H>, ()) {
|
||||||
|
fn iter(self) -> impl Iterator<Item = WidgetId> {
|
||||||
|
core::iter::once(self.0.erase_type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<H, T: IdList> IdList for (WidgetId<H>, T) {
|
||||||
|
fn iter(self) -> impl Iterator<Item = WidgetId> {
|
||||||
|
core::iter::once(self.0.erase_type()).chain(self.1.iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_from)]
|
#![feature(const_from)]
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
|
||||||
mod layout;
|
mod layout;
|
||||||
mod render;
|
mod render;
|
||||||
mod util;
|
pub mod util;
|
||||||
mod base;
|
mod base;
|
||||||
|
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use gui::util::IntoTupleList;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use app::App;
|
use app::App;
|
||||||
@@ -38,15 +39,19 @@ impl Client {
|
|||||||
rect.color(UIColor::ORANGE),
|
rect.color(UIColor::ORANGE),
|
||||||
rect.color(UIColor::LIME).pad(10.0),
|
rect.color(UIColor::LIME).pad(10.0),
|
||||||
)
|
)
|
||||||
.span(Axis::Y, [1, 1]),
|
.into_list()
|
||||||
|
.span(Axis::Y, [1, 1].into()),
|
||||||
rect.color(UIColor::YELLOW),
|
rect.color(UIColor::YELLOW),
|
||||||
)
|
)
|
||||||
|
.into_list()
|
||||||
.span(Axis::X, [2, 2, 1])
|
.span(Axis::X, [2, 2, 1])
|
||||||
.pad(10),
|
.pad(10),
|
||||||
)
|
)
|
||||||
|
.into_list()
|
||||||
.span(Axis::X, [1, 3]),
|
.span(Axis::X, [1, 3]),
|
||||||
rect.color(UIColor::GREEN),
|
rect.color(UIColor::GREEN),
|
||||||
)
|
)
|
||||||
|
.into_list()
|
||||||
.span(Axis::Y, [3, 1])
|
.span(Axis::Y, [3, 1])
|
||||||
.pad(10),
|
.pad(10),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ impl IDTracker {
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use this
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn free(&mut self, id: ID) {
|
pub fn free(&mut self, id: ID) {
|
||||||
self.free.push(id);
|
self.free.push(id);
|
||||||
|
|||||||
@@ -1,54 +1,70 @@
|
|||||||
macro_rules! impl_tuple {
|
pub trait TupleList {
|
||||||
($Tuple:ident $Bound:ident $Wrapper:ident $Mapper:ident $n:expr;$TL:tt $($T:tt)*) => {
|
const LEN: usize;
|
||||||
#[allow(non_snake_case)]
|
type Head;
|
||||||
impl<$($T: $Bound,)* $TL: $Bound> $Tuple<$n> for ($($T,)* $TL,) {
|
type Tail;
|
||||||
type Wrap<W: $Wrapper> = ($(W::Wrap<$T>,)* W::Wrap<$TL>,);
|
fn into_head(self) -> Self::Head;
|
||||||
type Map<M: $Mapper> = [M::Map; $n];
|
fn head(&self) -> &Self::Head;
|
||||||
fn wrap<W: $Wrapper>(self, ctx: &mut W::Ctx) -> ($(W::Wrap<$T>,)* W::Wrap<$TL>,) {
|
fn split(self) -> (Self::Head, Self::Tail);
|
||||||
let ($($T,)* $TL,) = self;
|
}
|
||||||
($(W::wrap($T, ctx),)* W::wrap($TL, ctx),)
|
impl TupleList for () {
|
||||||
}
|
const LEN: usize = 0;
|
||||||
fn map<M: $Mapper>(self, ctx: &mut M::Ctx) -> [M::Map; $n] {
|
type Head = ();
|
||||||
let ($($T,)* $TL,) = self;
|
type Tail = ();
|
||||||
[$(M::map($T, ctx),)* M::map($TL, ctx)]
|
fn head(&self) -> &Self::Head {
|
||||||
}
|
&()
|
||||||
}
|
}
|
||||||
};
|
fn into_head(self) -> Self::Head {}
|
||||||
($Tuple:ident, $Bound:ident, $Wrapper:ident, $Mapper:ident) => {
|
fn split(self) -> (Self::Head, Self::Tail) {
|
||||||
pub trait $Wrapper {
|
((), ())
|
||||||
type Wrap<T: $Bound>;
|
|
||||||
type Ctx;
|
|
||||||
fn wrap<T: $Bound>(t: T, ctx: &mut Self::Ctx) -> Self::Wrap<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait $Mapper {
|
|
||||||
type Map;
|
|
||||||
type Ctx;
|
|
||||||
fn map<T: $Bound>(t: T, ctx: &mut Self::Ctx) -> Self::Map;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait $Tuple<const LEN: usize> {
|
|
||||||
type Wrap<W: $Wrapper>;
|
|
||||||
type Map<M: $Mapper>;
|
|
||||||
fn map<M: $Mapper>(self, ctx: &mut M::Ctx) -> [M::Map; LEN];
|
|
||||||
fn wrap<W: $Wrapper>(self, ctx: &mut W::Ctx) -> Self::Wrap<W>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 1;A);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 2;A B);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 3;A B C);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 4;A B C D);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 5;A B C D E);
|
|
||||||
impl_tuple!($Tuple $Bound $Wrapper $Mapper 6;A B C D E F);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 7;A B C D E F G);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 8;A B C D E F G H);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 9;A B C D E F G H I);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 10;A B C D E F G H I J);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 11;A B C D E F G H I J K);
|
|
||||||
// impl_tuple!($Tuple $Bound $Wrapper $Mapper 12;A B C D E F G H I J K L);
|
|
||||||
};
|
|
||||||
($Bound:ident) => {
|
|
||||||
impl_tuple!(${concat($Bound, Tuple)}, $Bound, ${concat($Bound, Wrapper)}, ${concat($Bound, Mapper)});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) use impl_tuple;
|
impl<T, Rest: TupleList> TupleList for (T, Rest) {
|
||||||
|
const LEN: usize = Rest::LEN + 1;
|
||||||
|
type Head = T;
|
||||||
|
type Tail = Rest;
|
||||||
|
fn head(&self) -> &Self::Head {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
fn into_head(self) -> Self::Head {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
fn split(self) -> (Self::Head, Self::Tail) {
|
||||||
|
(self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait IntoTupleList {
|
||||||
|
type List;
|
||||||
|
fn into_list(self) -> Self::List;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoTupleList for () {
|
||||||
|
type List = ();
|
||||||
|
fn into_list(self) -> Self::List {}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_tuple {
|
||||||
|
($H:tt $($T:tt)*) => {
|
||||||
|
impl<$H, $($T,)*> IntoTupleList for ($H, $($T,)*) {
|
||||||
|
type List = ($H, <($($T,)*) as IntoTupleList>::List);
|
||||||
|
fn into_list(self) -> Self::List {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let ($H, $($T,)*) = self;
|
||||||
|
($H, ($($T,)*).into_list())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_tuple!(A);
|
||||||
|
impl_tuple!(A B);
|
||||||
|
impl_tuple!(A B C);
|
||||||
|
impl_tuple!(A B C D);
|
||||||
|
impl_tuple!(A B C D E);
|
||||||
|
impl_tuple!(A B C D E F);
|
||||||
|
impl_tuple!(A B C D E F G);
|
||||||
|
impl_tuple!(A B C D E F G H);
|
||||||
|
impl_tuple!(A B C D E F G H I);
|
||||||
|
impl_tuple!(A B C D E F G H I J);
|
||||||
|
impl_tuple!(A B C D E F G H I J K);
|
||||||
|
impl_tuple!(A B C D E F G H I J K L);
|
||||||
|
|||||||
Reference in New Issue
Block a user