Skip to main content

zai_rs/tool/file_parser_create/
response.rs

1//! File-parser task-creation response.
2
3use serde::{Deserialize, Deserializer, Serialize, de::Error as _};
4
5/// Response returned after creating a parser task.
6#[derive(Debug, Clone, Serialize)]
7pub struct FileParserCreateResponse {
8    /// Whether the provider reports successful task creation.
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub success: Option<bool>,
11    /// Provider message, when present.
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub message: Option<String>,
14    /// Unique parsing-task identifier.
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub task_id: Option<String>,
17}
18
19#[derive(Deserialize)]
20struct FileParserCreateResponseWire {
21    success: Option<bool>,
22    message: Option<String>,
23    task_id: Option<String>,
24}
25
26impl<'de> Deserialize<'de> for FileParserCreateResponse {
27    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
28    where
29        D: Deserializer<'de>,
30    {
31        let wire = FileParserCreateResponseWire::deserialize(deserializer)?;
32        if wire.success.is_none() && wire.message.is_none() && wire.task_id.is_none() {
33            return Err(D::Error::custom(
34                "file-parser response contained no documented non-null fields",
35            ));
36        }
37        Ok(Self {
38            success: wire.success,
39            message: wire.message,
40            task_id: wire.task_id,
41        })
42    }
43}
44
45impl FileParserCreateResponse {
46    /// Return whether the response contains a usable task identifier.
47    pub fn is_success(&self) -> bool {
48        self.success != Some(false)
49            && self
50                .task_id
51                .as_deref()
52                .is_some_and(|task_id| !task_id.trim().is_empty())
53    }
54
55    /// Borrow the task ID when returned.
56    pub fn task_id(&self) -> Option<&str> {
57        self.task_id.as_deref()
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn accepts_optional_schema_fields_but_rejects_empty_success() {
67        assert!(serde_json::from_str::<FileParserCreateResponse>("{}").is_err());
68        assert!(serde_json::from_str::<FileParserCreateResponse>(r#"{"success":null}"#).is_err());
69        let response: FileParserCreateResponse =
70            serde_json::from_str(r#"{"success":true,"task_id":"task-1"}"#).unwrap();
71        assert!(response.is_success());
72        assert_eq!(response.task_id(), Some("task-1"));
73    }
74}