use crate::{Bake, BakeSize, CrateEnv};
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use proc_macro2::TokenStream;
use quote::quote;
#[derive(Default, Debug)]
#[repr(transparent)]
#[allow(clippy::exhaustive_structs)] pub struct AsStaticStr<T>(pub T)
where
T: AsRef<str>;
impl<T> AsStaticStr<T>
where
T: AsRef<str>,
{
#[inline]
#[allow(missing_docs)]
pub fn into(self) -> T {
self.0
}
}
impl<T> Bake for AsStaticStr<T>
where
T: AsRef<str>,
{
fn bake(&self, _ctx: &CrateEnv) -> TokenStream {
let value = &self.0.as_ref();
quote!(#value)
}
}
impl<T> BakeSize for AsStaticStr<T>
where
T: AsRef<str>,
{
fn borrows_size(&self) -> usize {
self.0.as_ref().len()
}
}
impl<T> Deref for AsStaticStr<T>
where
T: AsRef<str>,
{
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for AsStaticStr<T>
where
T: AsRef<str>,
{
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> From<T> for AsStaticStr<T>
where
T: AsRef<str>,
{
#[inline]
fn from(value: T) -> Self {
Self(value)
}
}
#[test]
fn as_static_str() {
use std::borrow::Cow;
assert_eq!(
AsStaticStr(Cow::<str>::Owned("hi".to_string()))
.bake(&Default::default())
.to_string(),
r#""hi""#
);
}
pub type StringAsStaticStr = AsStaticStr<String>;
#[derive(Default, Debug)]
#[repr(transparent)]
#[allow(clippy::exhaustive_structs)] pub struct IteratorAsRefSlice<B, T>(pub B, pub PhantomData<T>)
where
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: Bake;
impl<B, T> IteratorAsRefSlice<B, T>
where
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: Bake,
{
#[inline]
#[allow(missing_docs)]
pub fn into(self) -> B {
self.0
}
}
impl<B, T> Bake for IteratorAsRefSlice<B, T>
where
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: Bake,
{
fn bake(&self, ctx: &CrateEnv) -> TokenStream {
let mut inner = TokenStream::new();
for e in self.0.into_iter() {
let e = e.bake(ctx);
inner.extend(quote! {#e,});
}
quote! {&[#inner]}
}
}
impl<B, T> BakeSize for IteratorAsRefSlice<B, T>
where
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: BakeSize,
{
fn borrows_size(&self) -> usize {
self.0.into_iter().map(|x| x.borrows_size()).sum()
}
}
impl<B, T> Deref for IteratorAsRefSlice<B, T>
where
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: Bake,
{
type Target = B;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<B, T> DerefMut for IteratorAsRefSlice<B, T>
where
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: Bake,
{
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<B, T> From<B> for IteratorAsRefSlice<B, T>
where
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: Bake,
{
#[inline]
fn from(value: B) -> Self {
Self(value, PhantomData)
}
}
impl<B, T> FromIterator<T> for IteratorAsRefSlice<B, T>
where
B: FromIterator<T>,
for<'a> &'a B: IntoIterator<Item = &'a T>,
T: Bake,
{
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self(iter.into_iter().collect(), PhantomData)
}
}
#[test]
fn as_ref_slice() {
use std::collections::HashSet;
let mut set = IteratorAsRefSlice::<HashSet<usize>, usize>::default();
set.insert(42);
assert_eq!(
set.bake(&Default::default()).to_string(),
r#"& [42usize ,]"#
)
}
pub type VecAsRefSlice<T> = IteratorAsRefSlice<Vec<T>, T>;
#[test]
fn vec_as_ref_slice() {
assert_eq!(
VecAsRefSlice::from(vec![6u8])
.bake(&Default::default())
.to_string(),
r#"& [6u8 ,]"#
)
}