Diffstat (limited to 'src/build.rs')
| -rw-r--r-- | src/build.rs | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/build.rs b/src/build.rs index efadc25..0d103ce 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,7 +1,10 @@ // pub mod builders; // pub mod protocols; -use crate::protocol::Visitor; +use crate::{ + protocol::{SyncEffect, Visitor}, + Walker, +}; /// A buildable type. pub trait Build<'ctx>: Sized { @@ -32,7 +35,7 @@ pub trait Builder<'ctx>: Default { /// Get the builder as a visitor that a walker can use. /// /// This is expected to just be `self`. - fn as_visitor(&mut self) -> Visitor<'_, 'ctx>; + fn as_visitor(&mut self) -> &mut Visitor<'ctx>; /// Finish the value. /// @@ -40,3 +43,37 @@ pub trait Builder<'ctx>: Default { /// it will be reported here. fn build(self) -> Result<Self::Value, Self::Error>; } + +#[derive(Debug)] +pub enum BuildError<B, W> { + Builder(B), + Walker(W), +} + +pub fn build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( + walker: W, +) -> Result<B::Value, BuildError<B::Error, W::Error>> { + let mut builder = B::default(); + + if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { + return Err(BuildError::Walker(err)); + } + + builder.build().map_err(BuildError::Builder) +} + +#[cfg(feature = "alloc")] +use crate::protocol::AsyncEffect; + +#[cfg(feature = "alloc")] +pub async fn async_build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = AsyncEffect>>( + walker: W, +) -> Result<B::Value, BuildError<B::Error, W::Error>> { + let mut builder = B::default(); + + if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()).await { + return Err(BuildError::Walker(err)); + } + + builder.build().map_err(BuildError::Builder) +} |