1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::BTreeMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(tag = "status", rename_all = "snake_case")]
10pub enum SubmitValue<T> {
11 Ok(T),
12 Err(SubmitError),
13 Running,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct SubmitError {
18 pub message: String,
19 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
20 pub field_errors: BTreeMap<String, String>,
21}
22
23impl SubmitError {
24 pub fn new(message: impl Into<String>) -> Self {
25 Self {
26 message: message.into(),
27 field_errors: Default::default(),
28 }
29 }
30
31 pub fn field(mut self, key: impl Into<String>, message: impl Into<String>) -> Self {
32 self.field_errors.insert(key.into(), message.into());
33 self
34 }
35}
36
37pub fn encode_submit_result<T: serde::Serialize>(
39 res: Result<T, SubmitError>,
40) -> crate::core::Result<serde_json::Value> {
41 match res {
42 Ok(v) => serde_json::to_value(v).map_err(|e| {
43 crate::core::ResumaError::Validation(format!(
44 "Could not encode submit result: {e}. If the return value is your own struct or enum, add #[data] above its definition."
45 ))
46 }),
47 Err(e) => Err(crate::core::ResumaError::Other(
48 serde_json::to_string(&e).unwrap_or_else(|_| e.message.clone()),
49 )),
50 }
51}
52
53pub type SubmitFn = fn(Value) -> SubmitDispatch;
55
56pub enum SubmitDispatch {
57 Ok(Value),
58 Err(SubmitError),
59}