sw4rm_rs/shared/
schema.rs1use std::collections::HashMap;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5use crate::{
6 Spec,
7 reference::*,
8 shared::{
9 ExternalDocumentation,
10 StringOrDiscriminator,
11 XML,
12 },
13};
14
15#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)]
24#[serde(default, rename_all = "camelCase")]
25pub struct Schema {
26 #[serde(skip_serializing_if = "Option::is_none")]
29 pub format: Option<String>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub title: Option<String>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub description: Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub default: Option<Value>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub multiple_of: Option<u64>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub maximum: Option<i64>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub exclusive_maximum: Option<i64>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub minimum: Option<i64>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub exclusive_minimum: Option<i64>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub max_length: Option<u64>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub min_length: Option<u64>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub pattern: Option<String>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 pub max_items: Option<u64>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub min_items: Option<u64>,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub unique_items: Option<bool>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub max_properties: Option<u64>,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub min_properties: Option<u64>,
62 #[serde(skip_serializing_if = "Vec::is_empty")]
63 pub required: Vec<String>,
64 #[serde(rename = "enum", skip_serializing_if = "Vec::is_empty")]
65 pub enum_values: Vec<Value>,
66 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
67 pub schema_type: Option<SchemaType>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub items: Option<RefOr<Box<Self>>>,
70 #[serde(skip_serializing_if = "Vec::is_empty")]
71 pub all_of: Vec<RefOr<Box<Self>>>,
72 #[serde(skip_serializing_if = "HashMap::is_empty")]
73 pub properties: HashMap<String, RefOr<Box<Self>>>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub additional_properties: Option<RefOr<Box<Self>>>,
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub discriminator: Option<StringOrDiscriminator>,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub read_only: Option<bool>,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub xml: Option<XML>,
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub external_docs: Option<ExternalDocumentation>,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub example: Option<Value>,
86
87 #[serde(flatten, skip_serializing_if = "HashMap::is_empty")]
91 pub x_fields: HashMap<String, Value>,
92
93 #[serde(skip_serializing_if = "Vec::is_empty")]
96 pub one_of: Vec<RefOr<Box<Self>>>,
97 #[serde(skip_serializing_if = "Vec::is_empty")]
98 pub any_of: Vec<RefOr<Box<Self>>>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub not: Option<RefOr<Box<Self>>>,
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub nullable: Option<bool>,
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub write_only: Option<bool>,
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub deprecated: Option<bool>,
107}
108
109impl Resolvable for Schema {
110 fn resolve(spec: &Spec, path: &String) -> Result<Self, ResolveError> {
111 let path = path.clone();
112 let reference: Reference = path.clone().try_into().unwrap();
113
114 match reference.kind {
115 ReferenceType::Schema | ReferenceType::Definitions => {
116 if spec.semver_check("=2") {
117 spec.definitions.get(&reference.name)
118 .ok_or_else(|| ResolveError::UnknownPathError(path))
119 .and_then(|t| t.resolve(spec))
120 } else {
121 spec.components
122 .as_ref()
123 .ok_or_else(|| ResolveError::UnknownPathError(path.clone()))
124 .and_then(|c| c.schemas.get(&reference.name).ok_or_else(|| ResolveError::UnknownPathError(path)))
125 .and_then(|p| p.resolve(spec))
126 }
127 },
128 _ => Err(ResolveError::UnknownPathError(path)),
129 }
130 }
131}
132
133#[derive(Debug, Serialize, Deserialize, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
134#[serde(rename_all = "camelCase")]
135pub enum SchemaType {
136 Array,
137 Boolean,
138 File,
139 Integer,
140 Number,
141 Object,
142 String,
143}
144impl Default for SchemaType {
145 fn default() -> Self { Self::Object }
146}