Skip to content

Commit

Permalink
Simplify task definition removing generics
Browse files Browse the repository at this point in the history
  • Loading branch information
pipex committed Jan 22, 2025
1 parent 70eb653 commit f7e0693
Show file tree
Hide file tree
Showing 18 changed files with 318 additions and 423 deletions.
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum Error {
TaskConditionFailed(#[from] super::task::ConditionFailed),

#[error("plan could not be found: ${0}")]
PlanNotFound(#[from] super::worker::PlanSearchError),
PlanSearchFailed(#[from] super::worker::PlanSearchError),

#[error(transparent)]
Other(#[from] Box<dyn std::error::Error>),
Expand Down
18 changes: 9 additions & 9 deletions src/extract/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ impl IntoError for PathDeserializationError {
#[derive(Debug)]
pub struct Path<T>(pub T);

impl<S, T: DeserializeOwned + Send> FromSystem<S> for Path<T> {
impl<T: DeserializeOwned + Send> FromSystem for Path<T> {
type Error = PathDeserializationError;

fn from_system(_: &System, context: &Context<S>) -> Result<Self, Self::Error> {
fn from_system(_: &System, context: &Context) -> Result<Self, Self::Error> {
let args = &context.args;
T::deserialize(de::PathDeserializer::new(args)).map(Path)
}
Expand Down Expand Up @@ -60,7 +60,7 @@ mod tests {
let system = System::from(state);

let Path(name): Path<String> =
Path::from_system(&system, &Context::<State>::new().arg("name", "one")).unwrap();
Path::from_system(&system, &Context::new().with_arg("name", "one")).unwrap();

assert_eq!(name, "one");
}
Expand All @@ -77,9 +77,9 @@ mod tests {

let Path((first, second)): Path<(String, String)> = Path::from_system(
&system,
&Context::<State>::new()
.arg("first", "one")
.arg("second", "two"),
&Context::new()
.with_arg("first", "one")
.with_arg("second", "two"),
)
.unwrap();

Expand All @@ -99,9 +99,9 @@ mod tests {

let Path(map): Path<HashMap<String, String>> = Path::from_system(
&system,
&Context::<State>::new()
.arg("first", "one")
.arg("second", "two"),
&Context::new()
.with_arg("first", "one")
.with_arg("second", "two"),
)
.unwrap();

Expand Down
49 changes: 7 additions & 42 deletions src/extract/target.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::fmt::{self, Display};
use std::marker::PhantomData;
use std::ops::Deref;

use crate::error::{self, IntoError};
Expand All @@ -10,28 +8,15 @@ use crate::task::Context;

#[derive(Debug)]
pub enum TargetExtractError {
Undefined,
SerializationFailed(serde_json::error::Error),
DeserializationFailed(serde_json::error::Error),
CannotResolvePath {
path: String,
reason: jsonptr::resolve::ResolveError,
},
}

impl std::error::Error for TargetExtractError {}

impl Display for TargetExtractError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TargetExtractError::SerializationFailed(err) => err.fmt(f)?,
TargetExtractError::DeserializationFailed(err) => err.fmt(f)?,
TargetExtractError::Undefined => {
write!(f, "no target has been defined for the context")?;
}
TargetExtractError::CannotResolvePath { path, reason } => {
write!(f, "cannot resolve state path `{}`: {}", path, reason)?;
}
};
Ok(())
}
Expand All @@ -43,46 +28,26 @@ impl IntoError for TargetExtractError {
}
}

pub struct Target<S: Clone, T = S> {
target: T,
_system: PhantomData<S>,
}
pub struct Target<T>(pub T);

impl<S: Serialize + Clone, T: DeserializeOwned> FromSystem<S> for Target<S, T> {
impl<T: DeserializeOwned> FromSystem for Target<T> {
type Error = TargetExtractError;

fn from_system(_: &System, context: &Context<S>) -> Result<Self, Self::Error> {
if context.target.is_none() {
return Err(TargetExtractError::Undefined);
}

let tgt = serde_json::to_value(context.target.clone())
.map_err(TargetExtractError::SerializationFailed)?;

// Return an error if the context path does not exist in the target object
let pointer = context.path.as_ref();
let value = pointer
.resolve(&tgt)
.map_err(|e| TargetExtractError::CannotResolvePath {
path: context.path.to_string(),
reason: e,
})?;
fn from_system(_: &System, context: &Context) -> Result<Self, Self::Error> {
let value = &context.target;

// This will fail if the value cannot be deserialized into the target type
let target = serde_json::from_value::<T>(value.clone())
.map_err(TargetExtractError::DeserializationFailed)?;

Ok(Target {
target,
_system: PhantomData::<S>,
})
Ok(Target(target))
}
}

impl<S: Clone, T> Deref for Target<S, T> {
impl<T> Deref for Target<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.target
&self.0
}
}
Loading

0 comments on commit f7e0693

Please sign in to comment.