use crate::ast::*;
use crate::gen_rs::rust::RustCodegen;
use anyhow::Result;
impl RustCodegen {
pub(crate) fn generate_generics(&mut self, generics: &Generics) -> Result<()> {
if generics.params.is_empty() && generics.where_clause.predicates.is_empty() {
return Ok(());
}
if !generics.params.is_empty() {
self.write("<");
for (i, param) in generics.params.iter().enumerate() {
if i > 0 {
self.write(", ");
}
self.generate_generic_param(param)?;
}
self.write(">");
}
Ok(())
}
fn generate_generic_param(&mut self, param: &GenericParam) -> Result<()> {
match ¶m.kind {
GenericParamKind::Lifetime(lifetime_param) => {
self.generate_lifetime_param(lifetime_param)?;
}
GenericParamKind::Type(type_param) => {
self.generate_type_param(type_param)?;
}
GenericParamKind::Const(const_param) => {
self.generate_const_param(const_param)?;
}
}
Ok(())
}
fn generate_lifetime_param(&mut self, param: &LifetimeParam) -> Result<()> {
self.write("'");
self.write(¶m.ident.name);
if !param.bounds.is_empty() {
self.write(": ");
for (i, bound) in param.bounds.iter().enumerate() {
if i > 0 {
self.write(" + ");
}
self.generate_lifetime(bound)?;
}
}
Ok(())
}
fn generate_type_param(&mut self, param: &TypeParam) -> Result<()> {
self.write(¶m.ident.name);
if !param.bounds.is_empty() {
self.write(": ");
for (i, bound) in param.bounds.iter().enumerate() {
if i > 0 {
self.write(" + ");
}
self.generate_generic_bound(bound)?;
}
}
if let Some(default) = ¶m.default {
self.write(" = ");
self.generate_ty(default)?;
}
Ok(())
}
fn generate_const_param(&mut self, param: &ConstParam) -> Result<()> {
self.write("const ");
self.write(¶m.ident.name);
self.write(": ");
self.generate_ty(¶m.ty)?;
if let Some(default) = ¶m.default {
self.write(" = ");
self.generate_expr(default)?;
}
Ok(())
}
pub(crate) fn generate_where_clause(&mut self, where_clause: &WhereClause) -> Result<()> {
if !where_clause.has_where_token || where_clause.predicates.is_empty() {
return Ok(());
}
self.write("\nwhere\n");
self.indent();
for (i, predicate) in where_clause.predicates.iter().enumerate() {
if i > 0 {
self.write(",\n");
}
self.write_indent();
self.generate_where_predicate(predicate)?;
}
self.dedent();
Ok(())
}
fn generate_where_predicate(&mut self, predicate: &WherePredicate) -> Result<()> {
match predicate {
WherePredicate::BoundPredicate(bound) => {
self.generate_where_bound_predicate(bound)?;
}
WherePredicate::RegionPredicate(region) => {
self.generate_where_region_predicate(region)?;
}
WherePredicate::EqPredicate(eq) => {
self.generate_where_eq_predicate(eq)?;
}
}
Ok(())
}
fn generate_where_bound_predicate(&mut self, predicate: &WhereBoundPredicate) -> Result<()> {
if !predicate.bound_lifetimes.is_empty() {
self.write("for<");
for (i, lifetime_param) in predicate.bound_lifetimes.iter().enumerate() {
if i > 0 {
self.write(", ");
}
self.write(&lifetime_param.ident.name);
}
self.write("> ");
}
self.generate_ty(&predicate.bounded_ty)?;
self.write(": ");
for (i, bound) in predicate.bounds.iter().enumerate() {
if i > 0 {
self.write(" + ");
}
self.generate_generic_bound(bound)?;
}
Ok(())
}
fn generate_where_region_predicate(&mut self, predicate: &WhereRegionPredicate) -> Result<()> {
self.generate_lifetime(&predicate.lifetime)?;
self.write(": ");
for (i, bound) in predicate.bounds.iter().enumerate() {
if i > 0 {
self.write(" + ");
}
self.generate_lifetime(bound)?;
}
Ok(())
}
fn generate_where_eq_predicate(&mut self, predicate: &WhereEqPredicate) -> Result<()> {
self.generate_ty(&predicate.lhs_ty)?;
self.write(" = ");
self.generate_ty(&predicate.rhs_ty)?;
Ok(())
}
}