Skip to content

Commit

Permalink
feat(links): add ControlFlow to result to indicate early exit
Browse files Browse the repository at this point in the history
This allows `Links` to signal, they have received everything they needed
and let the `Data` stop providing `Link`s
  • Loading branch information
SebastianSpeitel committed Jan 24, 2024
1 parent 72fd7e8 commit a930e1b
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 37 deletions.
16 changes: 9 additions & 7 deletions src/data/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use std::borrow::Cow;

use crate::data::{format, BoxedData, Data};
use crate::links::{LinkError, Links};
use crate::links::{LinkError, Links, Result};
use crate::query::Query;

pub trait DataExt: Data {
Expand Down Expand Up @@ -156,25 +156,27 @@ pub trait DataExt: Data {
#[inline]
#[cfg(feature = "std")]
fn as_list(&self) -> Result<Vec<BoxedData>, LinkError> {
use crate::links::CONTINUE;

#[derive(Default)]
struct ListLinks(Vec<BoxedData>);

impl Links for ListLinks {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result<(), LinkError> {
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
if key.is_none() {
self.0.push(target);
}
Ok(())
CONTINUE
}
#[inline]
fn push_unkeyed(&mut self, target: BoxedData) -> Result<(), LinkError> {
fn push_unkeyed(&mut self, target: BoxedData) -> Result {
self.0.push(target);
Ok(())
CONTINUE
}
#[inline]
fn push_keyed(&mut self, _target: BoxedData, _key: BoxedData) -> Result<(), LinkError> {
Ok(())
fn push_keyed(&mut self, _target: BoxedData, _key: BoxedData) -> Result {
CONTINUE
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/data/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
};

use crate::data::{BoxedData, Data};
use crate::links::{LinkError, Links};
use crate::links::{Links, Result, CONTINUE};
use crate::value::ValueBuiler;

#[derive(Default, Debug)]
Expand Down Expand Up @@ -282,7 +282,7 @@ mod recursive {
}

impl<F: DataFormatter> Links for RecursiveLinks<'_, '_, F> {
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result<(), LinkError> {
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
let link = FormattableLink::<F, _, _> {
key,
target,
Expand All @@ -291,7 +291,7 @@ mod recursive {
};
self.fmt_set.entry(&link);

Ok(())
CONTINUE
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/data/impls/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ impl Data for Val {
impl Data for Map<String, Val> {
#[inline]
fn provide_links(&self, links: &mut dyn Links) -> Result<(), LinkError> {
links.extend(self.iter().map(|(k, v)| (k.to_owned(), v.to_owned())))
links
.extend(self.iter().map(|(k, v)| (k.to_owned(), v.to_owned())))
.map(|_| ())
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/data/impls/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ where
{
#[inline]
fn provide_links(&self, links: &mut dyn Links) -> Result<(), LinkError> {
links.extend(self.iter().map(|(k, t)| (k.to_owned(), t.to_owned())))
links
.extend(self.iter().map(|(k, t)| (k.to_owned(), t.to_owned())))
.map(|_| ())
}
}

Expand All @@ -262,7 +264,9 @@ where
{
#[inline]
fn provide_links(&self, links: &mut dyn Links) -> Result<(), LinkError> {
links.extend(self.iter().map(::std::borrow::ToOwned::to_owned))
links
.extend(self.iter().map(::std::borrow::ToOwned::to_owned))
.map(|_| ())
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/data/impls/toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ impl Data for Val {
impl Data for Table {
#[inline]
fn provide_links(&self, links: &mut dyn Links) -> Result<(), LinkError> {
links.extend(self.iter().map(|(k, v)| (k.to_owned(), v.to_owned())))
links
.extend(self.iter().map(|(k, v)| (k.to_owned(), v.to_owned())))
.map(|_| ())
}
}
14 changes: 11 additions & 3 deletions src/links.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ops::ControlFlow;

use crate::data::{BoxedData, Data};

pub mod impls;
Expand All @@ -8,9 +10,13 @@ pub mod prelude {
pub use super::Links;
pub use super::LinksExt;
pub use super::Result;
pub use super::BREAK;
pub use super::CONTINUE;
}

pub type Result<T = (), E = LinkError> = core::result::Result<T, E>;
pub type Result<T = ControlFlow<()>, E = LinkError> = core::result::Result<T, E>;
pub const CONTINUE: Result = Ok(ControlFlow::Continue(()));
pub const BREAK: Result = Ok(ControlFlow::Break(()));

#[derive(Debug, thiserror::Error)]
pub enum LinkError {
Expand Down Expand Up @@ -60,9 +66,11 @@ pub trait LinksExt: Links {
#[inline]
fn extend(&mut self, links: impl IntoIterator<Item = impl Link>) -> Result {
for link in links {
link.build_into(self)?;
if link.build_into(self)?.is_break() {
return BREAK;
}
}
Ok(())
CONTINUE
}
}

Expand Down
40 changes: 20 additions & 20 deletions src/links/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
hash::BuildHasher,
};

use super::{Links, Result};
use super::{Links, Result, BREAK, CONTINUE};
use crate::data::{
unique::{Fixed, MaybeUnique},
BoxedData,
Expand All @@ -13,7 +13,7 @@ impl Links for Vec<(Option<BoxedData>, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
self.push((key, target));
Ok(())
CONTINUE
}
}

Expand All @@ -23,73 +23,73 @@ impl Links for Vec<(BoxedData, BoxedData)> {
if let Some(key) = key {
self.push((key, target));
}
Ok(())
CONTINUE
}

#[inline]
fn push_unkeyed(&mut self, _target: BoxedData) -> Result {
Ok(())
CONTINUE
}

#[inline]
fn push_keyed(&mut self, target: BoxedData, key: BoxedData) -> Result {
self.push((key, target));
Ok(())
CONTINUE
}
}

impl Links for Vec<BoxedData> {
#[inline]
fn push(&mut self, target: BoxedData, _key: Option<BoxedData>) -> Result {
self.push(target);
Ok(())
CONTINUE
}

#[inline]
fn push_unkeyed(&mut self, target: BoxedData) -> Result {
self.push(target);
Ok(())
CONTINUE
}

#[inline]
fn push_keyed(&mut self, target: BoxedData, _key: BoxedData) -> Result {
self.push(target);
Ok(())
CONTINUE
}
}

impl Links for Option<(BoxedData, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
if self.is_some() {
return Ok(());
return BREAK;
}
if let Some(key) = key {
self.replace((key, target));
}
Ok(())
BREAK
}
}

impl Links for Option<(Option<BoxedData>, BoxedData)> {
#[inline]
fn push(&mut self, target: BoxedData, key: Option<BoxedData>) -> Result {
if self.is_some() {
return Ok(());
return BREAK;
}
self.replace((key, target));
Ok(())
BREAK
}
}

impl Links for Option<BoxedData> {
#[inline]
fn push(&mut self, target: BoxedData, _key: Option<BoxedData>) -> Result {
if self.is_some() {
return Ok(());
return BREAK;
}
self.replace(target);
Ok(())
BREAK
}
}

Expand All @@ -101,18 +101,18 @@ impl<S: BuildHasher> Links for HashMap<Fixed<BoxedData>, BoxedData, S> {
self.insert(key, target);
}
}
Ok(())
CONTINUE
}
#[inline]
fn push_unkeyed(&mut self, _target: BoxedData) -> Result {
Ok(())
CONTINUE
}
#[inline]
fn push_keyed(&mut self, target: BoxedData, key: BoxedData) -> Result {
if let Ok(key) = key.try_into_unique() {
self.insert(key, target);
}
Ok(())
CONTINUE
}
}

Expand All @@ -122,20 +122,20 @@ impl<S: BuildHasher> Links for HashSet<Fixed<BoxedData>, S> {
if let Ok(target) = target.try_into_unique() {
self.insert(target);
}
Ok(())
CONTINUE
}
#[inline]
fn push_unkeyed(&mut self, target: BoxedData) -> Result {
if let Ok(target) = target.try_into_unique() {
self.insert(target);
}
Ok(())
CONTINUE
}
#[inline]
fn push_keyed(&mut self, target: BoxedData, _key: BoxedData) -> Result {
if let Ok(target) = target.try_into_unique() {
self.insert(target);
}
Ok(())
CONTINUE
}
}

0 comments on commit a930e1b

Please sign in to comment.