valico/json_schema/keywords/
content_media.rs

1use base64;
2use base64::Engine;
3use serde_json::Value;
4use std::str;
5
6use super::super::schema;
7use super::super::validators;
8
9#[derive(Debug)]
10pub enum ContentMediaType {
11    ApplicationJson,
12}
13
14impl ContentMediaType {
15    pub fn as_str(&self) -> &str {
16        match self {
17            ContentMediaType::ApplicationJson => "application/json",
18        }
19    }
20
21    pub fn validate(&self, val: &str) -> bool {
22        match self {
23            ContentMediaType::ApplicationJson => serde_json::from_str::<Value>(val),
24        }
25        .is_ok()
26    }
27}
28
29impl str::FromStr for ContentMediaType {
30    type Err = ();
31    fn from_str(s: &str) -> Result<ContentMediaType, ()> {
32        match s {
33            "application/json" => Ok(ContentMediaType::ApplicationJson),
34            _ => Err(()),
35        }
36    }
37}
38
39#[derive(Debug)]
40pub enum ContentEncoding {
41    Base64,
42}
43
44impl ContentEncoding {
45    pub fn as_str(&self) -> &str {
46        match self {
47            ContentEncoding::Base64 => "base64",
48        }
49    }
50
51    pub fn decode_val(&self, val: &str) -> Result<String, String> {
52        match self {
53            ContentEncoding::Base64 => {
54                match base64::engine::general_purpose::STANDARD.decode(val) {
55                    Ok(v) => match str::from_utf8(&v[..]) {
56                        Ok(s) => Ok(s.to_string()),
57                        Err(e) => Err(e.to_string()),
58                    },
59                    Err(e) => Err(e.to_string()),
60                }
61            }
62        }
63    }
64}
65
66impl str::FromStr for ContentEncoding {
67    type Err = ();
68    fn from_str(s: &str) -> Result<ContentEncoding, ()> {
69        match s {
70            "base64" => Ok(ContentEncoding::Base64),
71            _ => Err(()),
72        }
73    }
74}
75
76#[allow(missing_copy_implementations)]
77pub struct ContentMedia;
78impl super::Keyword for ContentMedia {
79    fn compile(&self, def: &Value, ctx: &schema::WalkContext<'_>) -> super::KeywordResult {
80        let maybe_content_media_type = def.get("contentMediaType");
81        let mut type_ = None;
82        if let Some(content_media_type) = maybe_content_media_type {
83            if !content_media_type.is_string() {
84                return Err(schema::SchemaError::Malformed {
85                    path: ctx.fragment.join("/"),
86                    detail: "contentMediaType MUST be a string.".to_string(),
87                });
88            } else {
89                let media_type = content_media_type.as_str().unwrap().parse().ok();
90                if let Some(media_type) = media_type {
91                    type_ = Some(media_type);
92                } else {
93                    return Err(schema::SchemaError::Malformed {
94                        path: ctx.fragment.join("/"),
95                        detail: "contentMediaType MUST be one of [\"application/json\"]"
96                            .to_string(),
97                    });
98                }
99            }
100        }
101
102        let maybe_content_encoding = def.get("contentEncoding");
103        let mut encoding = None;
104        if let Some(content_encoding) = maybe_content_encoding {
105            if !content_encoding.is_string() {
106                return Err(schema::SchemaError::Malformed {
107                    path: ctx.fragment.join("/"),
108                    detail: "contentEncoding MUST be a string.".to_string(),
109                });
110            } else {
111                let encoding_ = content_encoding.as_str().unwrap().parse().ok();
112                if let Some(encoding_) = encoding_ {
113                    encoding = Some(encoding_);
114                } else {
115                    return Err(schema::SchemaError::Malformed {
116                        path: ctx.fragment.join("/"),
117                        detail: "contentEncoding MUST be one of [\"base64\"]".to_string(),
118                    });
119                }
120            }
121        }
122
123        Ok(Some(Box::new(validators::ContentMedia { type_, encoding })))
124    }
125}