use std::path::PathBuf;
use serde::Serialize;
use utoipa::openapi::OpenApi;
#[derive(Debug, Clone)]
pub struct Fragment<T: Serialize> {
pub path: PathBuf,
pub content: T,
}
impl<T: Serialize> Fragment<T> {
pub fn new(path: impl Into<PathBuf>, content: T) -> Self {
Self {
path: path.into(),
content,
}
}
#[cfg(feature = "yaml")]
#[cfg_attr(docsrs, doc(cfg(feature = "yaml")))]
pub fn to_yaml(&self) -> Result<String, crate::YamlError> {
crate::ToYaml::to_yaml(&self.content)
}
}
#[derive(Debug, Clone)]
pub struct SplitResult<T: Serialize> {
pub main: OpenApi,
pub fragments: Vec<Fragment<T>>,
}
impl<T: Serialize> SplitResult<T> {
pub fn new(main: OpenApi) -> Self {
Self {
main,
fragments: Vec::new(),
}
}
pub fn add_fragment(&mut self, fragment: Fragment<T>) {
self.fragments.push(fragment);
}
pub fn is_unsplit(&self) -> bool {
self.fragments.is_empty()
}
pub fn fragment_count(&self) -> usize {
self.fragments.len()
}
#[cfg(feature = "yaml")]
#[cfg_attr(docsrs, doc(cfg(feature = "yaml")))]
pub fn main_to_yaml(&self) -> Result<String, crate::YamlError> {
crate::ToYaml::to_yaml(&self.main)
}
}
#[cfg(test)]
mod tests {
use super::*;
use utoipa::openapi::{Components, OpenApiBuilder};
#[test]
fn should_create_fragment() {
let components = Components::new();
let fragment = Fragment::new("schemas/common.yaml", components);
assert_eq!(fragment.path, PathBuf::from("schemas/common.yaml"));
}
#[test]
fn should_create_split_result() {
let spec = OpenApiBuilder::new().build();
let result: SplitResult<Components> = SplitResult::new(spec);
assert!(result.is_unsplit());
assert_eq!(result.fragment_count(), 0);
}
#[test]
fn should_add_fragments() {
let spec = OpenApiBuilder::new().build();
let mut result: SplitResult<Components> = SplitResult::new(spec);
result.add_fragment(Fragment::new("common.yaml", Components::new()));
result.add_fragment(Fragment::new("errors.yaml", Components::new()));
assert!(!result.is_unsplit());
assert_eq!(result.fragment_count(), 2);
}
}
#[cfg(all(test, feature = "yaml"))]
mod yaml_tests {
use super::*;
use utoipa::openapi::{Components, InfoBuilder, OpenApiBuilder};
#[test]
fn should_serialize_fragment_to_yaml() {
let components = Components::new();
let fragment = Fragment::new("schemas/common.yaml", components);
let yaml = fragment.to_yaml().expect("should serialize to YAML");
assert!(yaml.trim().is_empty() || yaml.trim() == "{}");
}
#[test]
fn should_serialize_main_spec_to_yaml() {
let spec = OpenApiBuilder::new()
.info(
InfoBuilder::new()
.title("Test API")
.version("1.0.0")
.build(),
)
.build();
let result: SplitResult<Components> = SplitResult::new(spec);
let yaml = result.main_to_yaml().expect("should serialize to YAML");
assert!(yaml.contains("openapi: 3.1.0"));
assert!(yaml.contains("title: Test API"));
assert!(yaml.contains("version: 1.0.0"));
assert!(yaml.contains("paths"));
}
#[test]
fn should_serialize_split_result_with_fragments() {
let spec = OpenApiBuilder::new()
.info(
InfoBuilder::new()
.title("Split API")
.version("2.0.0")
.build(),
)
.build();
let mut result: SplitResult<Components> = SplitResult::new(spec);
result.add_fragment(Fragment::new("common.yaml", Components::new()));
let main_yaml = result
.main_to_yaml()
.expect("should serialize main to YAML");
let fragment_yaml = result.fragments[0]
.to_yaml()
.expect("should serialize fragment to YAML");
assert!(main_yaml.contains("openapi: 3.1.0"));
assert!(main_yaml.contains("title: Split API"));
assert!(main_yaml.contains("version: 2.0.0"));
assert!(main_yaml.contains("paths"));
assert!(fragment_yaml.trim().is_empty() || fragment_yaml.trim() == "{}");
}
}