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};
7
8#[derive(Debug, Default)]
10pub struct CodeGenMetadata {
11 pub messages: HashMap<String, MessageInfo>,
12 pub enums: HashMap<String, EnumInfo>,
13 pub services: HashMap<String, ServiceInfo>,
14}
15
16impl CodeGenMetadata {
17 pub fn get_message_fields(&self, type_name: &str) -> Vec<MessageField> {
19 self.messages
20 .get(type_name)
21 .map(|msg| msg.fields.clone())
22 .unwrap_or_default()
23 }
24
25 pub fn resource_from_singular(&self, name: &str) -> Option<&ResourceDescriptor> {
27 self.messages.values().find_map(|info| {
28 info.resource_descriptor
29 .as_ref()
30 .filter(|r| r.singular == name)
31 })
32 }
33
34 pub fn resource_from_plural(&self, name: &str) -> Option<&ResourceDescriptor> {
36 self.messages.values().find_map(|info| {
37 info.resource_descriptor
38 .as_ref()
39 .filter(|r| r.plural == name)
40 })
41 }
42
43 pub fn get_resource_descriptor(&self, type_name: &str) -> Option<&ResourceDescriptor> {
45 if let Some(descriptor) = self
47 .messages
48 .get(type_name)
49 .and_then(|info| info.resource_descriptor.as_ref())
50 {
51 return Some(descriptor);
52 }
53
54 self.messages.iter().find_map(|(key, info)| {
56 let simple = key.rfind('.').map(|i| &key[i + 1..]).unwrap_or(key);
57 if simple == 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 unified_type: UnifiedType,
81 pub documentation: Option<String>,
82 pub oneof_variants: Option<Vec<OneofVariant>>,
84 pub field_behavior: Vec<FieldBehavior>,
86 pub is_sensitive: bool,
89 pub resource_reference: Option<ResourceReference>,
96}
97
98#[derive(Debug, Clone)]
100pub struct OneofVariant {
101 pub field_name: String, pub variant_name: String, pub field_type: UnifiedType, pub documentation: Option<String>,
105}
106
107impl OneofVariant {
108 pub fn is_int32(&self) -> bool {
112 matches!(self.field_type.base_type, BaseType::Int32)
113 }
114}
115
116#[derive(Debug, Clone)]
118pub struct EnumInfo {
119 pub name: String,
120 pub values: Vec<EnumValue>,
121 pub documentation: Option<String>,
122}
123
124#[derive(Debug, Clone)]
126pub struct EnumValue {
127 pub name: String,
128 pub number: i32,
129 pub documentation: Option<String>,
130}
131
132#[derive(Debug, Clone)]
134pub struct ServiceInfo {
135 pub name: String,
136 pub package: String,
138 pub documentation: Option<String>,
139 pub methods: Vec<MethodMetadata>,
140}
141
142#[derive(Debug, Clone)]
144pub struct MethodMetadata {
145 pub service_name: String,
146 pub method_name: String,
147 pub input_type: String,
148 pub output_type: String,
149 pub operation: Option<Operation>,
150 pub http_rule: HttpRule,
151 pub http_pattern: HttpPattern,
153 pub documentation: Option<String>,
154}
155
156impl MethodMetadata {
157 pub fn http_method(&self) -> Option<&str> {
159 use crate::google::api::http_rule::Pattern;
160 self.http_rule.pattern.as_ref().map(|p| match p {
161 Pattern::Get(_) => "GET",
162 Pattern::Post(_) => "POST",
163 Pattern::Put(_) => "PUT",
164 Pattern::Delete(_) => "DELETE",
165 Pattern::Patch(_) => "PATCH",
166 Pattern::Custom(c) => c.kind.as_str(),
167 })
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174
175 #[test]
176 fn test_service_based_method_structure() {
177 let mut codegen_metadata = CodeGenMetadata {
178 messages: HashMap::new(),
179 services: HashMap::new(),
180 enums: HashMap::new(),
181 };
182
183 let mut service_info = ServiceInfo {
185 name: "TestService".to_string(),
186 package: "test.v1".to_string(),
187 documentation: Some("Test service documentation".to_string()),
188 methods: Vec::new(),
189 };
190
191 let http_rule = crate::google::api::HttpRule {
193 pattern: Some(crate::google::api::http_rule::Pattern::Get(
194 "/test".to_string(),
195 )),
196 ..Default::default()
197 };
198
199 let method = MethodMetadata {
200 service_name: "TestService".to_string(),
201 method_name: "TestMethod".to_string(),
202 input_type: ".test.TestRequest".to_string(),
203 output_type: ".test.TestResponse".to_string(),
204 operation: None,
205 http_pattern: crate::parsing::http::HttpPattern::parse("/test"),
206 http_rule,
207 documentation: Some("Test method documentation".to_string()),
208 };
209 service_info.methods.push(method);
210
211 codegen_metadata
212 .services
213 .insert("TestService".to_string(), service_info);
214
215 let service = codegen_metadata.services.get("TestService").unwrap();
217 assert_eq!(service.name, "TestService");
218 assert_eq!(service.methods.len(), 1);
219 assert_eq!(service.methods[0].method_name, "TestMethod");
220 }
221}