geop_core_program/
operation.rs1use geop_core_math::geop_error::{GeopError, GeopResult};
2use serde::{Deserialize, Serialize, de::DeserializeOwned};
3
4use crate::part::StepContext;
5
6pub trait Operation: 'static {
9 const KIND: &'static str;
11 type Args: Serialize + DeserializeOwned + 'static;
14
15 fn run(ctx: &mut StepContext, args: &Self::Args) -> GeopResult<()>;
20}
21
22pub trait StepArgs: Serialize {
26 const KIND: &'static str;
28}
29
30pub trait ErasedOperation {
34 fn kind(&self) -> &'static str;
35 fn check_args(&self, args: &serde_json::Value) -> GeopResult<()>;
37 fn run(&self, ctx: &mut StepContext, args: &serde_json::Value) -> GeopResult<()>;
38}
39
40pub fn args<O: Operation>(json: &serde_json::Value) -> GeopResult<O::Args> {
42 O::Args::deserialize(json)
43 .map_err(|e| GeopError::new(format!("arguments of operation `{}`: {e}", O::KIND)))
44}
45
46pub fn saved<O: Operation>(args: &O::Args) -> GeopResult<serde_json::Value> {
48 serde_json::to_value(args)
49 .map_err(|e| GeopError::new(format!("arguments of operation `{}`: {e}", O::KIND)))
50}
51
52impl<O: Operation> ErasedOperation for O {
53 fn kind(&self) -> &'static str {
54 O::KIND
55 }
56
57 fn check_args(&self, args: &serde_json::Value) -> GeopResult<()> {
58 self::args::<O>(args).map(|_| ())
59 }
60
61 fn run(&self, ctx: &mut StepContext, args: &serde_json::Value) -> GeopResult<()> {
62 <O as Operation>::run(ctx, &self::args::<O>(args)?)
63 }
64}