1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use super::*;

#[derive(Debug, Default)]
pub struct Merge {
    pub config: MergeConfig,
    pub merged: OpenAPI,
    pub merge_time: time::Duration,
    pub save_time: time::Duration,
}

impl Merge {
    pub fn merge(mut self) -> io::Result<Self> {
        let now = time::Instant::now();
        let mut inputs = self.config.inputs.drain(..);
        // Use first element is a base for merging
        let base = inputs
            .next()
            .ok_or(io::Error::other("At least one input required"))?;
        let merged = inputs.fold(base, merge_into_base).openapi;
        let merge_time = now.elapsed();

        Ok(Self {
            merged,
            merge_time,
            ..self
        })
    }

    pub fn save(self) -> io::Result<Self> {
        let now = time::Instant::now();
        let path = self.config.output();
        save_json_file(&path, &self.merged)?;
        let save_time = now.elapsed();

        Ok(Self { save_time, ..self })
    }
}

impl From<MergeConfig> for Merge {
    fn from(config: MergeConfig) -> Self {
        Self {
            config,
            ..default()
        }
    }
}

fn merge_into_base(base: Input, mut other: Input) -> Input {
    tracing::info!(other = %other.source, "Processing");

    let mut openapi = base.openapi;
    openapi.merge_components(other.components());
    openapi.merge_security(other.security());
    openapi.merge_tags(other.tags());
    openapi.merge_extensions(other.extensions());

    for (path, method, operation) in other.operations() {
        openapi.merge_operation(path, method, operation);
    }

    Input { openapi, ..base }
}