Diffstat (limited to 'src/build.rs')
-rw-r--r--src/build.rs41
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)
+}