protobuf_dbml/generator/
mod.rs

1#[derive(Debug, PartialEq, Clone)]
2pub struct Codegen {
3  root_block: Block,
4}
5
6impl Codegen {
7  pub fn new() -> Self {
8    let codegen = Self {
9      root_block: Block::root(),
10    };
11
12    codegen
13  }
14
15  pub fn line(mut self, line_content: impl ToString) -> Self {
16    self.root_block = self.root_block.line(line_content);
17
18    self
19  }
20
21  pub fn line_cond(mut self, cond: bool, line_content: impl ToString) -> Self {
22    self.root_block = self.root_block.line_cond(cond, line_content);
23
24    self
25  }
26
27  pub fn line_skip(mut self, line_count: usize) -> Self {
28    self.root_block = self.root_block.line_skip(line_count);
29
30    self
31  }
32
33  pub fn block(mut self, block: Block) -> Self {
34    self.root_block = self.root_block.block(block);
35
36    self
37  }
38
39  pub fn block_vec(mut self, block_vec: Vec<Block>) -> Self {
40    self.root_block = self.root_block.block_vec(block_vec);
41
42    self
43  }
44}
45
46impl ToString for Codegen {
47  fn to_string(&self) -> String {
48    self.root_block.to_string()
49  }
50}
51
52#[derive(Debug, PartialEq, Clone, Default)]
53pub struct Block {
54  /// level of the block. 0 is the root block.
55  level: usize,
56  /// content before the block
57  content_before_block: Option<String>,
58  /// content inside the block
59  content: String,
60}
61
62impl Block {
63  fn root() -> Self {
64    Self {
65      level: 0,
66      content_before_block: None,
67      content: String::new(),
68    }
69  }
70
71  pub fn new(level: usize, before_block_content: Option<impl ToString>) -> Self {
72    let content = if let Some(impl_string) = before_block_content {
73      Some(impl_string.to_string())
74    } else {
75      None
76    };
77
78    Self {
79      level,
80      content_before_block: content,
81      content: String::new(),
82    }
83  }
84
85  /// Inserts a single line with the given text content.
86  pub fn line(mut self, line_content: impl ToString) -> Self {
87    let indent = "\t".repeat(self.level);
88
89    let new_content = format!("{}{}", indent, line_content.to_string());
90
91    self.content = format!("{}{}\n", self.content, new_content);
92
93    self
94  }
95
96  /// Inserts a single line when the condition is `true`.
97  pub fn line_cond(mut self, cond: bool, line_content: impl ToString) -> Self {
98    if !cond {
99      return self;
100    }
101
102    let indent = "\t".repeat(self.level);
103
104    let new_content = format!("{}{}", indent, line_content.to_string());
105
106    self.content = format!("{}{}\n", self.content, new_content);
107
108    self
109  }
110
111  /// Inserts empty lines for the given count.
112  pub fn line_skip(mut self, line_count: usize) -> Self {
113    let line_string = "\n".repeat(line_count);
114
115    self.content = format!("{}{}", self.content, line_string);
116
117    self
118  }
119
120  /// Inserts a block to the scope.
121  pub fn block(mut self, block: Block) -> Self {
122    self.content = format!("{}{}\n", self.content, block.to_string());
123
124    self
125  }
126
127  /// Inserts a vector of blocks to the scope.
128  pub fn block_vec(mut self, block_vec: Vec<Block>) -> Self {
129    for block in block_vec.into_iter() {
130      self.content = format!("{}\n{}\n", self.content, block.to_string());
131    }
132
133    self
134  }
135}
136
137impl ToString for Block {
138  fn to_string(&self) -> String {
139    let out = if self.level == 0 {
140      format!("{}", self.content.clone())
141    } else {
142      let block_indent = if self.level == 1 {
143        String::new()
144      } else {
145        "\t".repeat(self.level - 1)
146      };
147
148      let upper_block = if let Some(content_before_block) = self.content_before_block.clone() {
149        format!("{}{} {}", block_indent, content_before_block, "{")
150      } else {
151        format!("{}{}", block_indent, "{")
152      };
153
154      if self.content.is_empty() {
155        format!("{}{}", upper_block, "}")
156      } else {
157        let lower_block = format!("{}{}", block_indent, "}");
158
159        format!("{}\n{}{}", upper_block, self.content.clone(), lower_block)
160      }
161    };
162
163    out
164  }
165}