teo_runtime/value/
file.rs1use std::collections::HashSet;
2use std::fmt::{Display, Formatter};
3use itertools::Itertools;
4use maplit::hashset;
5use serde::Serialize;
6use serde_json::{Value as JsonValue};
7use teo_result::Error;
8
9#[derive(Debug, Clone, PartialEq, Serialize)]
10pub struct File {
11 pub filepath: String,
12 #[serde(rename(serialize = "contentType"))]
13 pub content_type: Option<String>,
14 pub filename: String,
15 #[serde(rename(serialize = "filenameExt"))]
16 pub filename_ext: Option<String>,
17}
18
19impl File {
20
21 pub fn filepath(&self) -> &str {
22 self.filepath.as_str()
23 }
24
25 pub fn content_type(&self) -> Option<&str> {
26 self.content_type.as_deref()
27 }
28
29 pub fn filename(&self) -> &str {
30 self.filename.as_str()
31 }
32
33 pub fn filename_ext(&self) -> Option<&str> {
34 self.filename_ext.as_deref()
35 }
36}
37
38impl Display for File {
39
40 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
41 f.write_str("File(\"")?;
42 f.write_str(&self.filepath.as_str().replace("\"", "\\\""))?;
43 f.write_str("\")")
44 }
45}
46
47impl TryFrom<&JsonValue> for File {
48
49 type Error = Error;
50
51 fn try_from(value: &JsonValue) -> Result<Self, Self::Error> {
52 if let Some(object) = value.as_object() {
53 let keys_set: HashSet<&str> = object.keys().map(|k| k.as_str()).collect();
54 let difference: HashSet<&str> = keys_set.difference(&hashset!{"filepath", "contentType", "filename", "filenameExt"}).map(|s| *s).collect();
55 if !difference.is_empty() {
56 return Err(Error::new(format!("Connot convert json value to file, unexpected key {}", difference.iter().map(|k| format!("`{}`", *k)).join(", "))));
57 }
58 Ok(Self {
59 filepath: if let Some(filepath) = object.get("filepath") {
60 if let Some(filepath) = filepath.as_str() {
61 filepath.to_owned()
62 } else {
63 Err(Error::new(format!("Cannot convert json value to file, invalid value at `filepath`, expect string")))?
64 }
65 } else {
66 Err(Error::new(format!("Cannot convert json value to file, missing key `filepath`")))?
67 },
68 content_type: if let Some(content_type) = object.get("contentType") {
69 if let Some(content_type) = content_type.as_str() {
70 Some(content_type.to_owned())
71 } else if content_type.is_null() {
72 None
73 } else {
74 Err(Error::new(format!("Cannot convert json value to file, invalid value at `contentType`, expect string")))?
75 }
76 } else {
77 None
78 },
79 filename: if let Some(filename) = object.get("filename") {
80 if let Some(filename) = filename.as_str() {
81 filename.to_owned()
82 } else {
83 Err(Error::new(format!("Cannot convert json value to file, invalid value at `filename`, expect string")))?
84 }
85 } else {
86 Err(Error::new(format!("Cannot convert json value to file, missing key `filename`")))?
87 },
88 filename_ext: if let Some(filename_ext) = object.get("filenameExt") {
89 if let Some(filename_ext) = filename_ext.as_str() {
90 Some(filename_ext.to_owned())
91 } else if filename_ext.is_null() {
92 None
93 } else {
94 Err(Error::new(format!("Cannot convert json value to file, invalid value at `filenameExt`, expect string")))?
95 }
96 } else {
97 None
98 },
99 })
100 } else {
101 Err(Error::new(format!("Cannot convert json value to file, value `{}` is not object", value)))
102 }
103 }
104}