mod gen_enum;
mod gen_struct;
mod generate_item;
mod generate_mod;
mod generator;
mod r#impl;
mod impl_for;
mod stream_builder;
use crate::parse::GenericConstraints;
use crate::parse::Generics;
use crate::parse::Visibility;
use crate::prelude::Delimiter;
use crate::prelude::Ident;
use crate::prelude::TokenStream;
use std::fmt;
use std::marker::PhantomData;
pub use self::gen_enum::GenEnum;
pub use self::gen_struct::GenStruct;
pub use self::generate_item::FnBuilder;
pub use self::generate_item::FnSelfArg;
pub use self::generate_item::GenConst;
pub use self::generate_mod::GenerateMod;
pub use self::generator::Generator;
pub use self::r#impl::Impl;
pub use self::impl_for::ImplFor;
pub use self::stream_builder::PushParseError;
pub use self::stream_builder::StreamBuilder;
#[allow(missing_docs)]
pub trait Parent {
fn append(
&mut self,
builder: StreamBuilder,
);
fn name(&self) -> &Ident;
fn generics(&self) -> Option<&Generics>;
fn generic_constraints(&self) -> Option<&GenericConstraints>;
}
#[allow(missing_docs)]
pub enum StringOrIdent {
String(String),
Ident(Ident),
}
impl fmt::Display for StringOrIdent {
fn fmt(
&self,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match self {
| Self::String(s) => s.fmt(f),
| Self::Ident(i) => i.fmt(f),
}
}
}
impl From<String> for StringOrIdent {
fn from(s: String) -> Self {
Self::String(s)
}
}
impl From<Ident> for StringOrIdent {
fn from(i: Ident) -> Self {
Self::Ident(i)
}
}
impl<'a> From<&'a str> for StringOrIdent {
fn from(s: &'a str) -> Self {
Self::String(s.to_owned())
}
}
pub struct Path(Vec<StringOrIdent>);
impl From<String> for Path {
fn from(s: String) -> Self {
StringOrIdent::from(s).into()
}
}
impl From<Ident> for Path {
fn from(i: Ident) -> Self {
StringOrIdent::from(i).into()
}
}
impl From<&str> for Path {
fn from(s: &str) -> Self {
StringOrIdent::from(s).into()
}
}
impl From<StringOrIdent> for Path {
fn from(value: StringOrIdent) -> Self {
Self(vec![value])
}
}
impl FromIterator<String> for Path {
fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
iter.into_iter().map(StringOrIdent::from).collect()
}
}
impl FromIterator<Ident> for Path {
fn from_iter<T: IntoIterator<Item = Ident>>(iter: T) -> Self {
iter.into_iter().map(StringOrIdent::from).collect()
}
}
impl<'a> FromIterator<&'a str> for Path {
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
iter.into_iter().map(StringOrIdent::from).collect()
}
}
impl FromIterator<StringOrIdent> for Path {
fn from_iter<T: IntoIterator<Item = StringOrIdent>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
impl IntoIterator for Path {
type IntoIter = std::vec::IntoIter<StringOrIdent>;
type Item = StringOrIdent;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
struct Field {
name: String,
vis: Visibility,
ty: String,
attributes: Vec<StreamBuilder>,
}
impl Field {
fn new(
name: impl Into<String>,
vis: Visibility,
ty: impl Into<String>,
) -> Self {
Self {
name: name.into(),
vis,
ty: ty.into(),
attributes: Vec::new(),
}
}
}
pub struct FieldBuilder<'a, P> {
fields: &'a mut Vec<Field>,
_parent: PhantomData<P>, }
impl<P> FieldBuilder<'_, P> {
pub fn with_attribute(
&mut self,
name: impl AsRef<str>,
value: impl FnOnce(&mut StreamBuilder) -> crate::Result,
) -> crate::Result<&mut Self> {
self.current().with_attribute(name, value)?;
Ok(self)
}
pub fn with_parsed_attribute(
&mut self,
attribute: impl AsRef<str>,
) -> crate::Result<&mut Self> {
self.current().with_parsed_attribute(attribute)?;
Ok(self)
}
pub fn with_attribute_stream(
&mut self,
attribute: impl Into<TokenStream>,
) -> &mut Self {
self.current().with_attribute_stream(attribute);
self
}
pub fn add_field(
&mut self,
name: impl Into<String>,
ty: impl Into<String>,
) -> &mut Self {
self.fields.push(Field::new(name, Visibility::Default, ty));
self
}
}
impl<P: Parent> FieldBuilder<'_, GenStruct<'_, P>> {
pub fn make_pub(&mut self) -> &mut Self {
self.current().vis = Visibility::Pub;
self
}
}
impl<'a, P> From<&'a mut Vec<Field>> for FieldBuilder<'a, P> {
fn from(fields: &'a mut Vec<Field>) -> Self {
Self {
fields,
_parent: PhantomData,
}
}
}
impl<P> FieldBuilder<'_, P> {
fn current(&mut self) -> &mut Field {
self.fields.last_mut().unwrap()
}
}
trait AttributeContainer {
fn derives(&mut self) -> &mut Vec<Path>;
fn attributes(&mut self) -> &mut Vec<StreamBuilder>;
fn with_derive(
&mut self,
derive: impl Into<Path>,
) -> &mut Self {
self.derives().push(derive.into());
self
}
fn with_derives<T: Into<Path>>(
&mut self,
derives: impl IntoIterator<Item = T>,
) -> &mut Self {
self.derives().extend(derives.into_iter().map(Into::into));
self
}
fn with_attribute(
&mut self,
name: impl AsRef<str>,
value: impl FnOnce(&mut StreamBuilder) -> crate::Result,
) -> crate::Result<&mut Self> {
let mut stream = StreamBuilder::new();
value(stream.ident_str(name))?;
self.attributes().push(stream);
Ok(self)
}
fn with_parsed_attribute(
&mut self,
attribute: impl AsRef<str>,
) -> crate::Result<&mut Self> {
let mut stream = StreamBuilder::new();
stream.push_parsed(attribute)?;
self.attributes().push(stream);
Ok(self)
}
fn with_attribute_stream(
&mut self,
attribute: impl Into<TokenStream>,
) -> &mut Self {
let stream = StreamBuilder {
stream: attribute.into(),
};
self.attributes().push(stream);
self
}
fn build_derives(
&mut self,
b: &mut StreamBuilder,
) -> &mut Self {
let derives = std::mem::take(self.derives());
if !derives.is_empty() {
build_attribute(b, |b| {
b.ident_str("derive").group(Delimiter::Parenthesis, |b| {
for (idx, derive) in derives.into_iter().enumerate() {
if idx > 0 {
b.punct(',');
}
for (idx, component) in derive.into_iter().enumerate() {
if idx > 0 {
b.puncts("::");
}
match component {
| StringOrIdent::String(s) => b.ident_str(s),
| StringOrIdent::Ident(i) => b.ident(i),
};
}
}
Ok(())
})
})
.expect("could not build derives");
}
self
}
fn build_attributes(
&mut self,
b: &mut StreamBuilder,
) -> &mut Self {
for attr in std::mem::take(self.attributes()) {
build_attribute(b, |b| Ok(b.extend(attr.stream))).expect("could not build attribute");
}
self
}
}
impl AttributeContainer for Field {
fn derives(&mut self) -> &mut Vec<Path> {
unreachable!("fields cannot have derives")
}
fn attributes(&mut self) -> &mut Vec<StreamBuilder> {
&mut self.attributes
}
}
fn build_attribute<T>(
b: &mut StreamBuilder,
build: T,
) -> crate::Result
where
T: FnOnce(&mut StreamBuilder) -> crate::Result<&mut StreamBuilder>,
{
b.punct('#').group(Delimiter::Bracket, |b| {
build(b)?;
Ok(())
})?;
Ok(())
}