blob: d8d13d1d27b7fb63cfadde11b8b7a20ea24848c0 [file] [log] [blame]
use {Ident, LifetimeDef, Path, PolyTraitRef, TraitBoundModifier, Ty, TyParam, TyParamBound};
use aster::invoke::{Invoke, Identity};
use aster::lifetime::{IntoLifetime, IntoLifetimeDef, LifetimeDefBuilder};
use aster::path::{IntoPath, PathBuilder};
use aster::ty::TyBuilder;
// ////////////////////////////////////////////////////////////////////////////
pub struct TyParamBuilder<F = Identity> {
callback: F,
id: Ident,
bounds: Vec<TyParamBound>,
default: Option<Ty>,
}
impl TyParamBuilder {
pub fn new<I>(id: I) -> Self
where I: Into<Ident>
{
TyParamBuilder::with_callback(id, Identity)
}
pub fn from_ty_param(ty_param: TyParam) -> Self {
TyParamBuilder::from_ty_param_with_callback(Identity, ty_param)
}
}
impl<F> TyParamBuilder<F>
where F: Invoke<TyParam>
{
pub fn with_callback<I>(id: I, callback: F) -> Self
where I: Into<Ident>
{
TyParamBuilder {
callback: callback,
id: id.into(),
bounds: Vec::new(),
default: None,
}
}
pub fn from_ty_param_with_callback(callback: F, ty_param: TyParam) -> Self {
TyParamBuilder {
callback: callback,
id: ty_param.ident,
bounds: ty_param.bounds,
default: ty_param.default,
}
}
pub fn with_default(mut self, ty: Ty) -> Self {
self.default = Some(ty);
self
}
pub fn default(self) -> TyBuilder<Self> {
TyBuilder::with_callback(self)
}
pub fn with_bound(mut self, bound: TyParamBound) -> Self {
self.bounds.push(bound);
self
}
pub fn bound(self) -> TyParamBoundBuilder<Self> {
TyParamBoundBuilder::with_callback(self)
}
pub fn with_trait_bound(self, trait_ref: PolyTraitRef) -> Self {
self.bound().build_trait(trait_ref, TraitBoundModifier::None)
}
pub fn trait_bound<P>(self, path: P) -> PolyTraitRefBuilder<Self>
where P: IntoPath
{
PolyTraitRefBuilder::with_callback(path, self)
}
pub fn lifetime_bound<L>(mut self, lifetime: L) -> Self
where L: IntoLifetime
{
let lifetime = lifetime.into_lifetime();
self.bounds.push(TyParamBound::Region(lifetime));
self
}
pub fn build(self) -> F::Result {
self.callback.invoke(TyParam {
attrs: vec![],
ident: self.id,
bounds: self.bounds,
default: self.default,
})
}
}
impl<F> Invoke<Ty> for TyParamBuilder<F>
where F: Invoke<TyParam>
{
type Result = Self;
fn invoke(self, ty: Ty) -> Self {
self.with_default(ty)
}
}
impl<F> Invoke<TyParamBound> for TyParamBuilder<F>
where F: Invoke<TyParam>
{
type Result = Self;
fn invoke(self, bound: TyParamBound) -> Self {
self.with_bound(bound)
}
}
impl<F> Invoke<PolyTraitRef> for TyParamBuilder<F>
where F: Invoke<TyParam>
{
type Result = Self;
fn invoke(self, trait_ref: PolyTraitRef) -> Self {
self.with_trait_bound(trait_ref)
}
}
// ////////////////////////////////////////////////////////////////////////////
pub struct TyParamBoundBuilder<F = Identity> {
callback: F,
}
impl TyParamBoundBuilder {
pub fn new() -> Self {
TyParamBoundBuilder::with_callback(Identity)
}
}
impl<F> TyParamBoundBuilder<F>
where F: Invoke<TyParamBound>
{
pub fn with_callback(callback: F) -> Self {
TyParamBoundBuilder { callback: callback }
}
pub fn build_trait(self, poly_trait: PolyTraitRef, modifier: TraitBoundModifier) -> F::Result {
let bound = TyParamBound::Trait(poly_trait, modifier);
self.callback.invoke(bound)
}
pub fn trait_<P>(self, path: P) -> PolyTraitRefBuilder<TraitTyParamBoundBuilder<F>>
where P: IntoPath
{
let builder = TraitTyParamBoundBuilder {
builder: self,
modifier: TraitBoundModifier::None,
};
PolyTraitRefBuilder::with_callback(path, builder)
}
pub fn maybe_trait<P>(self, path: P) -> PolyTraitRefBuilder<TraitTyParamBoundBuilder<F>>
where P: IntoPath
{
let builder = TraitTyParamBoundBuilder {
builder: self,
modifier: TraitBoundModifier::Maybe,
};
PolyTraitRefBuilder::with_callback(path, builder)
}
pub fn iterator(self, ty: Ty) -> PolyTraitRefBuilder<TraitTyParamBoundBuilder<F>> {
let path = PathBuilder::new()
.global()
.id("std")
.id("iter")
.segment("Iterator")
.binding("Item")
.build(ty)
.build()
.build();
self.trait_(path)
}
pub fn lifetime<L>(self, lifetime: L) -> F::Result
where L: IntoLifetime
{
let lifetime = lifetime.into_lifetime();
self.callback.invoke(TyParamBound::Region(lifetime))
}
}
// ////////////////////////////////////////////////////////////////////////////
pub struct TraitTyParamBoundBuilder<F> {
builder: TyParamBoundBuilder<F>,
modifier: TraitBoundModifier,
}
impl<F> Invoke<PolyTraitRef> for TraitTyParamBoundBuilder<F>
where F: Invoke<TyParamBound>
{
type Result = F::Result;
fn invoke(self, poly_trait: PolyTraitRef) -> Self::Result {
self.builder.build_trait(poly_trait, self.modifier)
}
}
// ////////////////////////////////////////////////////////////////////////////
pub struct PolyTraitRefBuilder<F> {
callback: F,
trait_ref: Path,
lifetimes: Vec<LifetimeDef>,
}
impl<F> PolyTraitRefBuilder<F>
where F: Invoke<PolyTraitRef>
{
pub fn with_callback<P>(path: P, callback: F) -> Self
where P: IntoPath
{
PolyTraitRefBuilder {
callback: callback,
trait_ref: path.into_path(),
lifetimes: Vec::new(),
}
}
pub fn with_lifetime<L>(mut self, lifetime: L) -> Self
where L: IntoLifetimeDef
{
self.lifetimes.push(lifetime.into_lifetime_def());
self
}
pub fn lifetime<N>(self, name: N) -> LifetimeDefBuilder<Self>
where N: Into<Ident>
{
LifetimeDefBuilder::with_callback(name, self)
}
pub fn build(self) -> F::Result {
self.callback.invoke(PolyTraitRef {
bound_lifetimes: self.lifetimes,
trait_ref: self.trait_ref,
})
}
}
impl<F> Invoke<LifetimeDef> for PolyTraitRefBuilder<F>
where F: Invoke<PolyTraitRef>
{
type Result = Self;
fn invoke(self, lifetime: LifetimeDef) -> Self {
self.with_lifetime(lifetime)
}
}