1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10pub struct CodeBase {
11 pub enums: Vec<EnumInfo>,
13 pub structs: Vec<StructInfo>,
15 pub files: Vec<FileInfo>,
17}
18
19impl CodeBase {
20 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn merge(&mut self, other: CodeBase) {
27 self.enums.extend(other.enums);
28 self.structs.extend(other.structs);
29 self.files.extend(other.files);
30 }
31
32 pub fn total_elements(&self) -> usize {
34 self.enums.len() + self.structs.len()
35 }
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct FileInfo {
41 pub path: String,
43 pub enum_count: usize,
45 pub struct_count: usize,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct EnumInfo {
52 pub name: String,
54 pub doc_comment: Option<String>,
56 pub file_path: String,
58 pub line_number: usize,
60 pub visibility: Visibility,
62 pub generics: Vec<String>,
64 pub derives: Vec<String>,
66 pub attributes: Vec<String>,
68 pub variants: Vec<EnumVariant>,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct EnumVariant {
75 pub name: String,
77 pub doc_comment: Option<String>,
79 pub fields: Vec<FieldInfo>,
81 pub discriminant: Option<String>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct StructInfo {
88 pub name: String,
90 pub doc_comment: Option<String>,
92 pub file_path: String,
94 pub line_number: usize,
96 pub visibility: Visibility,
98 pub generics: Vec<String>,
100 pub derives: Vec<String>,
102 pub attributes: Vec<String>,
104 pub fields: Vec<FieldInfo>,
106 pub methods: Vec<MethodInfo>,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct FieldInfo {
113 pub name: Option<String>,
115 pub ty: String,
117 pub doc_comment: Option<String>,
119 pub visibility: Visibility,
121 pub attributes: Vec<String>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct MethodInfo {
128 pub name: String,
130 pub doc_comment: Option<String>,
132 pub file_path: String,
134 pub line_number: usize,
136 pub visibility: Visibility,
138 pub is_async: bool,
140 pub is_const: bool,
142 pub is_unsafe: bool,
144 pub generics: Vec<String>,
146 pub parameters: Vec<ParameterInfo>,
148 pub return_type: Option<String>,
150 pub receiver: Option<Receiver>,
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct ParameterInfo {
157 pub name: String,
159 pub ty: String,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
165pub enum Receiver {
166 Value,
168 Ref,
170 RefMut,
172 Explicit(String),
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
178pub enum Visibility {
179 Private,
181 Public,
183 Crate,
185 Super,
187 Restricted(String),
189}
190
191impl Default for Visibility {
192 fn default() -> Self {
193 Visibility::Private
194 }
195}
196
197impl std::fmt::Display for Visibility {
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 match self {
200 Visibility::Private => write!(f, ""),
201 Visibility::Public => write!(f, "pub"),
202 Visibility::Crate => write!(f, "pub(crate)"),
203 Visibility::Super => write!(f, "pub(super)"),
204 Visibility::Restricted(path) => write!(f, "pub(in {})", path),
205 }
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
214 fn test_codebase_new() {
215 let codebase = CodeBase::new();
216 assert!(codebase.enums.is_empty());
217 assert!(codebase.structs.is_empty());
218 assert!(codebase.files.is_empty());
219 }
220
221 #[test]
222 fn test_codebase_merge() {
223 let mut codebase1 = CodeBase::new();
224 codebase1.enums.push(EnumInfo {
225 name: "TestEnum".to_string(),
226 doc_comment: None,
227 file_path: "test.rs".to_string(),
228 line_number: 1,
229 visibility: Visibility::Public,
230 generics: vec![],
231 derives: vec![],
232 attributes: vec![],
233 variants: vec![],
234 });
235
236 let mut codebase2 = CodeBase::new();
237 codebase2.structs.push(StructInfo {
238 name: "TestStruct".to_string(),
239 doc_comment: None,
240 file_path: "test.rs".to_string(),
241 line_number: 10,
242 visibility: Visibility::Public,
243 generics: vec![],
244 derives: vec![],
245 attributes: vec![],
246 fields: vec![],
247 methods: vec![],
248 });
249
250 codebase1.merge(codebase2);
251 assert_eq!(codebase1.enums.len(), 1);
252 assert_eq!(codebase1.structs.len(), 1);
253 }
254
255 #[test]
256 fn test_visibility_display() {
257 assert_eq!(Visibility::Private.to_string(), "");
258 assert_eq!(Visibility::Public.to_string(), "pub");
259 assert_eq!(Visibility::Crate.to_string(), "pub(crate)");
260 assert_eq!(Visibility::Super.to_string(), "pub(super)");
261 assert_eq!(
262 Visibility::Restricted("crate::module".to_string()).to_string(),
263 "pub(in crate::module)"
264 );
265 }
266}