openapi_to_rust/server/
mod.rs1use crate::analysis::{OperationInfo, SchemaAnalysis};
10
11pub mod codegen;
12pub mod edit;
13pub mod list;
14pub mod selector;
15
16pub use selector::{Resolution, Selector, SelectorParseError, SelectorResolveError, resolve};
17
18pub fn resolve_operation_selectors(
21 selectors: &[String],
22 analysis: &SchemaAnalysis,
23) -> Result<Resolution, OperationSelectionError> {
24 let parsed = selectors
25 .iter()
26 .map(|selector| {
27 Selector::parse(selector).map_err(|source| OperationSelectionError::Parse {
28 selector: selector.clone(),
29 source,
30 })
31 })
32 .collect::<Result<Vec<_>, _>>()?;
33 let index = OperationIndex::from_analysis(analysis);
34 resolve(&parsed, &index).map_err(OperationSelectionError::Resolve)
35}
36
37pub fn resolve_operation_id(
43 operation_id: &str,
44 analysis: &SchemaAnalysis,
45) -> Result<Resolution, OperationSelectionError> {
46 let index = OperationIndex::from_analysis(analysis);
47 resolve(&[Selector::OperationId(operation_id.to_string())], &index)
48 .map_err(OperationSelectionError::Resolve)
49}
50
51#[derive(Debug, thiserror::Error)]
52pub enum OperationSelectionError {
53 #[error("invalid operation selector `{selector}`: {source}")]
54 Parse {
55 selector: String,
56 #[source]
57 source: SelectorParseError,
58 },
59 #[error("operation selector did not resolve: {0}")]
60 Resolve(#[source] SelectorResolveError),
61}
62
63#[derive(Debug, Clone)]
66pub struct OperationIndex {
67 operations: Vec<OperationSummary>,
68 operation_id_aliases: std::collections::BTreeMap<String, Vec<String>>,
69}
70
71#[derive(Debug, Clone, serde::Serialize)]
74pub struct OperationSummary {
75 pub operation_id: String,
76 pub method: String,
77 pub path: String,
78 pub tags: Vec<String>,
79 pub supports_streaming: bool,
82}
83
84impl OperationIndex {
85 pub fn from_analysis(analysis: &SchemaAnalysis) -> Self {
87 let operations = analysis
88 .operations
89 .values()
90 .map(OperationSummary::from)
91 .collect();
92 Self {
93 operations,
94 operation_id_aliases: analysis.operation_id_aliases.clone(),
95 }
96 }
97
98 pub fn from_summaries(operations: Vec<OperationSummary>) -> Self {
102 Self {
103 operations,
104 operation_id_aliases: Default::default(),
105 }
106 }
107
108 pub fn operations(&self) -> &[OperationSummary] {
109 &self.operations
110 }
111
112 pub(crate) fn operation_id_aliases(&self, raw_id: &str) -> Option<&[String]> {
113 self.operation_id_aliases.get(raw_id).map(Vec::as_slice)
114 }
115
116 #[cfg(test)]
117 pub(crate) fn with_aliases(
118 mut self,
119 aliases: std::collections::BTreeMap<String, Vec<String>>,
120 ) -> Self {
121 self.operation_id_aliases = aliases;
122 self
123 }
124
125 pub fn tag_count(&self) -> usize {
129 let mut tags: std::collections::BTreeSet<&str> = std::collections::BTreeSet::new();
130 for op in &self.operations {
131 for t in &op.tags {
132 tags.insert(t.as_str());
133 }
134 }
135 tags.len()
136 }
137}
138
139impl From<&OperationInfo> for OperationSummary {
140 fn from(op: &OperationInfo) -> Self {
141 Self {
142 operation_id: op.operation_id.clone(),
143 method: op.method.clone(),
144 path: op.path.clone(),
145 tags: op.tags.clone(),
146 supports_streaming: op.supports_streaming,
147 }
148 }
149}