use std::sync::Arc;
use url::Url;
pub(crate) mod document;
pub(crate) mod operation;
pub(crate) mod params;
pub(crate) mod schema;
pub(crate) mod servers;
mod yaml;
use document::Document;
use operation::{Operation, SkippedOperation};
use servers::Servers;
pub(crate) const DEFAULT_MAX_SPEC_BYTES: usize = 64 * 1024 * 1024;
#[derive(Debug, Clone, Copy)]
pub(crate) struct SpecInput<'a> {
pub(crate) name: &'a str,
pub(crate) url: &'a Url,
pub(crate) bytes: &'a [u8],
pub(crate) max_spec_bytes: usize,
}
#[derive(Debug)]
pub(crate) struct OpenApiSpec {
pub(crate) document: Arc<Document>,
pub(crate) servers: Servers,
pub(crate) operations: Vec<Operation>,
pub(crate) skipped: Vec<SkippedOperation>,
}
#[derive(Debug, thiserror::Error)]
pub(crate) enum LoadError {
#[error("OpenAPI spec is {size} bytes, over max_spec_bytes ({limit} bytes)")]
TooLarge { size: usize, limit: usize },
#[error("could not parse OpenAPI spec as JSON: {0}")]
Json(serde_json::Error),
#[error("could not parse OpenAPI spec as YAML: {0}")]
Yaml(serde_yaml_ng::Error),
#[error(
"YAML aliases expand the spec past {limit} units of content, two per byte \
of the spec; its aliases repeat too much"
)]
YamlAliasExpansion { limit: usize },
#[error("Swagger 2.0 specs are not supported; convert the spec to OpenAPI 3")]
Swagger2,
#[error("OpenAPI version {0} is not supported; expected 3.0 or 3.1")]
UnsupportedVersion(String),
#[error("document is not an OpenAPI spec: it has no `openapi` version")]
MissingVersion,
}
impl OpenApiSpec {
pub(crate) fn load(input: SpecInput<'_>) -> Result<Self, LoadError> {
if input.bytes.len() > input.max_spec_bytes {
return Err(LoadError::TooLarge {
size: input.bytes.len(),
limit: input.max_spec_bytes,
});
}
let document = Document::parse(input.bytes)?;
let servers = servers::resolve_spec(document.root(), input.url);
let (operations, skipped) = operation::index(&document, input.name, input.url);
Ok(Self {
document: Arc::new(document),
servers,
operations,
skipped,
})
}
}
#[cfg(test)]
#[path = "openapi_tests.rs"]
mod tests;