icu4x
icu4x copied to clipboard
Databake: allow a static result
I've created a few helpers to bake from a heap type into a static type.
Struct to bake:
#[derive(Bake)]
#[databake(path = crate::stories)]
pub struct Chapter {
pub name: AsStaticStr<String>,
pub paragraphs: VecAsRefSlice<AsStaticStr<String>>,
}
Struct generated:
pub struct Chapter {
pub name: &'static str,
pub paragraphs: &'static [&'static str],
}
Cow<'_, str> and other collections are also supported (at least in theory, I've not tested it).
It's created by the code below. If interested I can create a PR.
#[repr(transparent)]
pub struct AsStaticStr<T>(pub T);
impl<T> Bake for AsStaticStr<T>
where
T: AsRef<str>,
{
fn bake(&self, _ctx: &CrateEnv) -> TokenStream {
let value = self.0.as_ref();
quote!(#value)
}
}
#[repr(transparent)]
pub struct AsRefSlice<I, T>(pub I, pub PhantomData<T>);
impl<I, T> AsRefSlice<I, T> {
pub fn new(i: I) -> Self {
AsRefSlice(i, PhantomData)
}
}
impl<I, T> Bake for AsRefSlice<I, T>
where
for<'a> &'a I: IntoIterator<Item = &'a T>,
T: Bake,
{
fn bake(&self, ctx: &CrateEnv) -> TokenStream {
bake_iter(self.0.into_iter(), ctx)
}
}
#[repr(transparent)]
pub struct VecAsRefSlice<T>(pub Vec<T>);
impl<T> Bake for VecAsRefSlice<T>
where
T: Bake,
{
fn bake(&self, ctx: &CrateEnv) -> TokenStream {
bake_iter(self.0.iter(), ctx)
}
}
fn bake_iter<'a, I, T>(iter: I, ctx: &CrateEnv) -> TokenStream
where
I: Iterator<Item = &'a T>,
T: Bake + 'a,
{
let mut inner = TokenStream::new();
for e in iter {
let e = e.bake(ctx);
inner.extend(quote! {#e,});
}
quote! {&[#inner]}
}
possible type alises:
type StringAsStaticStr = AsStaticStr<String>;
type CowAsStaticStr<'a> = AsStaticStr<Cow<'a, str>>;
// use this instead of the explicit type above: new or PhantomData must be used, has 2. field with it
type VecAsRefSlice<T> = AsRefSlice<Vec<T>, T>;
Also the names could probably be shorter and "better", I'm open for suggestions.