blob: 71f68b147a8988e0761fb76bbf6e7c29eec4ef44 [file] [log] [blame]
use {Path, PathSegment, QSelf, Ty};
use aster::ident::ToIdent;
use aster::invoke::{Invoke, Identity};
use aster::path::{PathBuilder, PathSegmentBuilder};
use aster::ty::TyBuilder;
// ////////////////////////////////////////////////////////////////////////////
pub struct QPathBuilder<F = Identity> {
callback: F,
}
impl QPathBuilder {
pub fn new() -> Self {
QPathBuilder::with_callback(Identity)
}
}
impl<F> QPathBuilder<F>
where F: Invoke<(QSelf, Path)>
{
/// Construct a `QPathBuilder` that will call the `callback` with a constructed `QSelf`
/// and `Path`.
pub fn with_callback(callback: F) -> Self {
QPathBuilder { callback: callback }
}
/// Build a qualified path first by starting with a type builder.
pub fn with_ty(self, ty: Ty) -> QPathTyBuilder<F> {
QPathTyBuilder {
builder: self,
ty: ty,
}
}
/// Build a qualified path first by starting with a type builder.
pub fn ty(self) -> TyBuilder<Self> {
TyBuilder::with_callback(self)
}
/// Build a qualified path with a concrete type and path.
pub fn build(self, qself: QSelf, path: Path) -> F::Result {
self.callback.invoke((qself, path))
}
}
impl<F> Invoke<Ty> for QPathBuilder<F>
where F: Invoke<(QSelf, Path)>
{
type Result = QPathTyBuilder<F>;
fn invoke(self, ty: Ty) -> QPathTyBuilder<F> {
self.with_ty(ty)
}
}
// ////////////////////////////////////////////////////////////////////////////
pub struct QPathTyBuilder<F> {
builder: QPathBuilder<F>,
ty: Ty,
}
impl<F> QPathTyBuilder<F>
where F: Invoke<(QSelf, Path)>
{
/// Build a qualified path with a path builder.
pub fn as_(self) -> PathBuilder<Self> {
PathBuilder::with_callback(self)
}
pub fn id<T>(self, id: T) -> F::Result
where T: ToIdent
{
let path = Path {
global: false,
segments: vec![],
};
self.as_().build(path).id(id)
}
pub fn segment<T>(self, id: T) -> PathSegmentBuilder<QPathQSelfBuilder<F>>
where T: ToIdent
{
let path = Path {
global: false,
segments: vec![],
};
self.as_().build(path).segment(id)
}
}
impl<F> Invoke<Path> for QPathTyBuilder<F>
where F: Invoke<(QSelf, Path)>
{
type Result = QPathQSelfBuilder<F>;
fn invoke(self, path: Path) -> QPathQSelfBuilder<F> {
QPathQSelfBuilder {
builder: self.builder,
qself: QSelf {
ty: Box::new(self.ty),
position: path.segments.len(),
},
path: path,
}
}
}
// ////////////////////////////////////////////////////////////////////////////
pub struct QPathQSelfBuilder<F> {
builder: QPathBuilder<F>,
qself: QSelf,
path: Path,
}
impl<F> QPathQSelfBuilder<F>
where F: Invoke<(QSelf, Path)>
{
pub fn id<T>(self, id: T) -> F::Result
where T: ToIdent
{
self.segment(id).build()
}
pub fn segment<T>(self, id: T) -> PathSegmentBuilder<QPathQSelfBuilder<F>>
where T: ToIdent
{
PathSegmentBuilder::with_callback(id, self)
}
}
impl<F> Invoke<PathSegment> for QPathQSelfBuilder<F>
where F: Invoke<(QSelf, Path)>
{
type Result = F::Result;
fn invoke(mut self, segment: PathSegment) -> F::Result {
self.path.segments.push(segment);
self.builder.build(self.qself, self.path)
}
}