cg2 0.2.1

Rust code generator.
Documentation
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
);