use alloc::{string::String, vec::Vec};
use crate::Generator;
pub trait Flexible {
fn call(&self, g: &mut Generator);
}
pub trait FlexibleList {
fn call(&self) -> Vec<String>;
}
impl Flexible for () {
fn call(&self, _g: &mut Generator) {}
}
impl Flexible for char {
fn call(&self, g: &mut Generator) {
g.outc(*self);
}
}
impl Flexible for &str {
fn call(&self, g: &mut Generator) {
g.out(self);
}
}
impl Flexible for String {
fn call(&self, g: &mut Generator) {
g.out(self);
}
}
impl Flexible for &String {
fn call(&self, g: &mut Generator) {
g.out(self);
}
}
impl<F> Flexible for F
where
F: Fn(&mut Generator),
{
fn call(&self, g: &mut Generator) {
self(g);
}
}
impl<I> FlexibleList for I
where
I: Flexible,
{
fn call(&self) -> Vec<String> {
let mut g = Generator::new();
self.call(&mut g);
vec![g.into_code()]
}
}
impl<const N: usize, I> FlexibleList for &[I; N]
where
I: Flexible,
{
fn call(&self) -> Vec<String> {
(*self as &[_]).call()
}
}
impl<I> FlexibleList for &[I]
where
I: Flexible,
{
fn call(&self) -> Vec<String> {
let mut items = vec![];
for i in *self {
let mut g = Generator::new();
i.call(&mut g);
items.push(g.into_code());
}
items
}
}
macro_rules! impl_flexible_list_tuple {
($($item:ident),*) => {
impl_flexible_list_tuple!(@impl [$($item),*]);
};
(@impl []) => {};
(@impl [$first:ident $(, $item:ident)*]) => {
impl_flexible_list_tuple!(@impl $first $(, $item)*);
impl_flexible_list_tuple!(@impl [$($item),*]);
};
(@impl $first:ident $(, $item:ident)*) => {
impl<$first $(, $item)*> FlexibleList for ($first, $($item),*)
where
$first: Flexible,
$($item: Flexible),*
{
fn call(&self) -> Vec<String> {
(&self).call()
}
}
impl<$first $(, $item)*> FlexibleList for &($first, $($item),*)
where
$first: Flexible,
$($item: Flexible),*
{
fn call(&self) -> Vec<String> {
#[expect(non_snake_case)]
let ($first, $($item),*) = self;
let mut items = vec![];
let mut g = Generator::new();
$first.call(&mut g);
items.push(g.code().clone());
$(
g.clear();
$item.call(&mut g);
items.push(g.code().clone());
)*
items
}
}
};
}
#[rustfmt::skip]
impl_flexible_list_tuple!(
I0, I1, I2, I3, I4, I5, I6, I7,
I8, I9, I10, I11, I12, I13, I14, I15,
I16, I17, I18, I19, I20, I21, I22, I23,
I24, I25, I26, I27, I28, I29, I30, I31
);