feat(v2): initial commit
This commit is contained in:
parent
48868983b3
commit
5a84558d89
44 changed files with 20091 additions and 3489 deletions
4
torn-api-codegen/src/openapi/mod.rs
Normal file
4
torn-api-codegen/src/openapi/mod.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
pub mod parameter;
|
||||
pub mod path;
|
||||
pub mod schema;
|
||||
pub mod r#type;
|
||||
40
torn-api-codegen/src/openapi/parameter.rs
Normal file
40
torn-api-codegen/src/openapi/parameter.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ParameterLocation {
|
||||
Query,
|
||||
Path,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum OpenApiParameterDefault<'a> {
|
||||
Int(i32),
|
||||
Str(&'a str),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct OpenApiParameterSchema<'a> {
|
||||
#[serde(rename = "$ref")]
|
||||
pub ref_path: Option<&'a str>,
|
||||
pub r#type: Option<&'a str>,
|
||||
pub r#enum: Option<Vec<&'a str>>,
|
||||
pub format: Option<&'a str>,
|
||||
pub default: Option<OpenApiParameterDefault<'a>>,
|
||||
pub maximum: Option<i32>,
|
||||
pub minimum: Option<i32>,
|
||||
pub items: Option<Box<OpenApiParameterSchema<'a>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct OpenApiParameter<'a> {
|
||||
pub name: &'a str,
|
||||
pub description: Option<Cow<'a, str>>,
|
||||
pub r#in: ParameterLocation,
|
||||
pub required: bool,
|
||||
#[serde(borrow)]
|
||||
pub schema: OpenApiParameterSchema<'a>,
|
||||
}
|
||||
81
torn-api-codegen/src/openapi/path.rs
Normal file
81
torn-api-codegen/src/openapi/path.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
use super::parameter::OpenApiParameter;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum OpenApiPathParameter<'a> {
|
||||
Link {
|
||||
#[serde(rename = "$ref")]
|
||||
ref_path: &'a str,
|
||||
},
|
||||
Inline(OpenApiParameter<'a>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct SchemaLink<'a> {
|
||||
#[serde(rename = "$ref")]
|
||||
pub ref_path: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum OpenApiResponseBody<'a> {
|
||||
Schema(SchemaLink<'a>),
|
||||
Union {
|
||||
#[serde(borrow, rename = "anyOf")]
|
||||
any_of: Vec<SchemaLink<'a>>,
|
||||
},
|
||||
}
|
||||
|
||||
fn deserialize_response_body<'de, D>(deserializer: D) -> Result<OpenApiResponseBody<'de>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Json<'a> {
|
||||
#[serde(borrow)]
|
||||
schema: OpenApiResponseBody<'a>,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct Content<'a> {
|
||||
#[serde(borrow, rename = "application/json")]
|
||||
json: Json<'a>,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct StatusOk<'a> {
|
||||
#[serde(borrow)]
|
||||
content: Content<'a>,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct Responses<'a> {
|
||||
#[serde(borrow, rename = "200")]
|
||||
ok: StatusOk<'a>,
|
||||
}
|
||||
|
||||
let responses = Responses::deserialize(deserializer)?;
|
||||
|
||||
Ok(responses.ok.content.json.schema)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct OpenApiPathBody<'a> {
|
||||
pub summary: Option<Cow<'a, str>>,
|
||||
pub description: Cow<'a, str>,
|
||||
#[serde(borrow, default)]
|
||||
pub parameters: Vec<OpenApiPathParameter<'a>>,
|
||||
#[serde(
|
||||
borrow,
|
||||
rename = "responses",
|
||||
deserialize_with = "deserialize_response_body"
|
||||
)]
|
||||
pub response_content: OpenApiResponseBody<'a>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct OpenApiPath<'a> {
|
||||
#[serde(borrow)]
|
||||
pub get: OpenApiPathBody<'a>,
|
||||
}
|
||||
38
torn-api-codegen/src/openapi/schema.rs
Normal file
38
torn-api-codegen/src/openapi/schema.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
use indexmap::IndexMap;
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::{parameter::OpenApiParameter, path::OpenApiPath, r#type::OpenApiType};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Components<'a> {
|
||||
#[serde(borrow)]
|
||||
pub schemas: IndexMap<&'a str, OpenApiType<'a>>,
|
||||
#[serde(borrow)]
|
||||
pub parameters: IndexMap<&'a str, OpenApiParameter<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct OpenApiSchema<'a> {
|
||||
#[serde(borrow)]
|
||||
pub paths: IndexMap<&'a str, OpenApiPath<'a>>,
|
||||
#[serde(borrow)]
|
||||
pub components: Components<'a>,
|
||||
}
|
||||
|
||||
impl OpenApiSchema<'_> {
|
||||
pub fn read() -> Result<Self, serde_json::Error> {
|
||||
let s = include_str!("../../openapi.json");
|
||||
|
||||
serde_json::from_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn read() {
|
||||
OpenApiSchema::read().unwrap();
|
||||
}
|
||||
}
|
||||
98
torn-api-codegen/src/openapi/type.rs
Normal file
98
torn-api-codegen/src/openapi/type.rs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum OpenApiVariants<'a> {
|
||||
Int(Vec<i32>),
|
||||
#[serde(borrow)]
|
||||
Str(Vec<&'a str>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct OpenApiType<'a> {
|
||||
#[serde(default)]
|
||||
pub deprecated: bool,
|
||||
pub description: Option<Cow<'a, str>>,
|
||||
|
||||
pub r#type: Option<&'a str>,
|
||||
pub format: Option<&'a str>,
|
||||
|
||||
#[serde(rename = "$ref")]
|
||||
pub ref_path: Option<&'a str>,
|
||||
|
||||
pub one_of: Option<Vec<OpenApiType<'a>>>,
|
||||
pub all_of: Option<Vec<OpenApiType<'a>>>,
|
||||
|
||||
pub required: Option<Vec<&'a str>>,
|
||||
#[serde(borrow)]
|
||||
pub properties: Option<IndexMap<&'a str, OpenApiType<'a>>>,
|
||||
|
||||
pub items: Option<Box<OpenApiType<'a>>>,
|
||||
pub r#enum: Option<OpenApiVariants<'a>>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn object() {
|
||||
let json = r##"
|
||||
{
|
||||
"required": [
|
||||
"name",
|
||||
"branches"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"branches": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TornFactionTreeBranch"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
"##;
|
||||
|
||||
let obj: OpenApiType = serde_json::from_str(json).unwrap();
|
||||
|
||||
assert_eq!(obj.r#type, Some("object"));
|
||||
|
||||
let props = obj.properties.unwrap();
|
||||
|
||||
assert!(props.contains_key("name"));
|
||||
|
||||
let branches = props.get("branches").unwrap();
|
||||
assert_eq!(branches.r#type, Some("array"));
|
||||
|
||||
let items = branches.items.as_ref().unwrap();
|
||||
assert!(items.ref_path.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enum_variants() {
|
||||
let int_json = r#"
|
||||
[1, 2, 3, 4]
|
||||
"#;
|
||||
|
||||
let de: OpenApiVariants = serde_json::from_str(int_json).unwrap();
|
||||
|
||||
assert_eq!(de, OpenApiVariants::Int(vec![1, 2, 3, 4]));
|
||||
|
||||
let str_json = r#"
|
||||
["foo", "bar", "baz"]
|
||||
"#;
|
||||
|
||||
let de: OpenApiVariants = serde_json::from_str(str_json).unwrap();
|
||||
|
||||
assert_eq!(de, OpenApiVariants::Str(vec!["foo", "bar", "baz"]));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue