olai_codegen/parsing/
models.rs1use std::collections::HashMap;
2
3use crate::gnostic::openapi::v3::Operation;
4use crate::google::api::{FieldBehavior, HttpRule, ResourceDescriptor, ResourceReference};
5use crate::parsing::http::HttpPattern;
6use crate::parsing::types::{BaseType, UnifiedType};
7use crate::utils::last_segment;
8
9#[derive(Debug, Default)]
11pub struct CodeGenMetadata {
12 pub messages: HashMap<String, MessageInfo>,
13 pub enums: HashMap<String, EnumInfo>,
14 pub services: HashMap<String, ServiceInfo>,
15}
16
17impl CodeGenMetadata {
18 pub fn get_message_fields(&self, type_name: &str) -> Vec<MessageField> {
20 self.messages
21 .get(type_name)
22 .map(|msg| msg.fields.clone())
23 .unwrap_or_default()
24 }
25
26 pub fn resource_from_singular(&self, name: &str) -> Option<&ResourceDescriptor> {
28 self.messages.values().find_map(|info| {
29 info.resource_descriptor
30 .as_ref()
31 .filter(|r| r.singular == name)
32 })
33 }
34
35 pub fn resource_from_plural(&self, name: &str) -> Option<&ResourceDescriptor> {
37 self.messages.values().find_map(|info| {
38 info.resource_descriptor
39 .as_ref()
40 .filter(|r| r.plural == name)
41 })
42 }
43
44 pub fn get_resource_descriptor(&self, type_name: &str) -> Option<&ResourceDescriptor> {
46 if let Some(descriptor) = self
48 .messages
49 .get(type_name)
50 .and_then(|info| info.resource_descriptor.as_ref())
51 {
52 return Some(descriptor);
53 }
54
55 self.messages.iter().find_map(|(key, info)| {
57 if last_segment(key) == type_name {
58 info.resource_descriptor.as_ref()
59 } else {
60 None
61 }
62 })
63 }
64}
65
66#[derive(Debug, Clone)]
68pub struct MessageInfo {
69 pub name: String,
70 pub fields: Vec<MessageField>,
71 pub resource_descriptor: Option<ResourceDescriptor>,
72 pub documentation: Option<String>,
73}
74
75#[derive(Debug, Clone)]
77pub struct MessageField {
78 pub name: String,
79 pub json_name: Option<String>,
81 pub unified_type: UnifiedType,
83 pub documentation: Option<String>,
84 pub oneof_variants: Option<Vec<OneofVariant>>,
86 pub field_behavior: Vec<FieldBehavior>,
88 pub is_sensitive: bool,
91 pub resource_reference: Option<ResourceReference>,
98}
99
100#[derive(Debug, Clone)]
102pub struct OneofVariant {
103 pub field_name: String, pub variant_name: String, pub field_type: UnifiedType, pub documentation: Option<String>,
107}
108
109impl OneofVariant {
110 pub fn is_int32(&self) -> bool {
114 matches!(self.field_type.base_type, BaseType::Int32)
115 }
116}
117
118#[derive(Debug, Clone)]
120pub struct EnumInfo {
121 pub name: String,
122 pub values: Vec<EnumValue>,
123 pub documentation: Option<String>,
124}
125
126#[derive(Debug, Clone)]
128pub struct EnumValue {
129 pub name: String,
130 pub number: i32,
131 pub documentation: Option<String>,
132}
133
134#[derive(Debug, Clone)]
136pub struct ServiceInfo {
137 pub name: String,
138 pub package: String,
140 pub documentation: Option<String>,
141 pub methods: Vec<MethodMetadata>,
142}
143
144#[derive(Debug, Clone)]
146pub struct MethodMetadata {
147 pub service_name: String,
148 pub method_name: String,
149 pub input_type: String,
150 pub output_type: String,
151 pub operation: Option<Operation>,
152 pub http_rule: HttpRule,
153 pub http_pattern: HttpPattern,
155 pub documentation: Option<String>,
156}
157
158impl MethodMetadata {
159 pub fn http_method(&self) -> Option<&str> {
161 use crate::google::api::http_rule::Pattern;
162 self.http_rule.pattern.as_ref().map(|p| match p {
163 Pattern::Get(_) => "GET",
164 Pattern::Post(_) => "POST",
165 Pattern::Put(_) => "PUT",
166 Pattern::Delete(_) => "DELETE",
167 Pattern::Patch(_) => "PATCH",
168 Pattern::Custom(c) => c.kind.as_str(),
169 })
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_service_based_method_structure() {
179 let mut codegen_metadata = CodeGenMetadata {
180 messages: HashMap::new(),
181 services: HashMap::new(),
182 enums: HashMap::new(),
183 };
184
185 let mut service_info = ServiceInfo {
187 name: "TestService".to_string(),
188 package: "test.v1".to_string(),
189 documentation: Some("Test service documentation".to_string()),
190 methods: Vec::new(),
191 };
192
193 let http_rule = crate::google::api::HttpRule {
195 pattern: Some(crate::google::api::http_rule::Pattern::Get(
196 "/test".to_string(),
197 )),
198 ..Default::default()
199 };
200
201 let method = MethodMetadata {
202 service_name: "TestService".to_string(),
203 method_name: "TestMethod".to_string(),
204 input_type: ".test.TestRequest".to_string(),
205 output_type: ".test.TestResponse".to_string(),
206 operation: None,
207 http_pattern: crate::parsing::http::HttpPattern::parse("/test"),
208 http_rule,
209 documentation: Some("Test method documentation".to_string()),
210 };
211 service_info.methods.push(method);
212
213 codegen_metadata
214 .services
215 .insert("TestService".to_string(), service_info);
216
217 let service = codegen_metadata.services.get("TestService").unwrap();
219 assert_eq!(service.name, "TestService");
220 assert_eq!(service.methods.len(), 1);
221 assert_eq!(service.methods[0].method_name, "TestMethod");
222 }
223}