1use std::fmt::Debug;
2
3use crate::Generator;
4use crate::Indentation;
5
6pub struct Body {
7 pub factory: Option<Box<dyn Fn(Indentation, usize) -> String>>,
8 pub semicolon_for_empty: bool,
9}
10
11impl Body {
12 pub fn new() -> Self {
13 Self {
14 factory: None,
15 semicolon_for_empty: true,
16 }
17 }
18
19 pub fn with_factory<T: Fn(Indentation, usize) -> String + 'static>(factory: T) -> Self {
20 Self {
21 factory: Some(Box::new(factory)),
22 semicolon_for_empty: true,
23 }
24 }
25
26 pub fn with_semicolon_for_empty(mut self, semicolon_for_empty: bool) -> Self {
27 self.semicolon_for_empty = semicolon_for_empty;
28
29 self
30 }
31}
32
33impl Debug for Body {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 f.debug_struct("Body")
36 .field("factory:is-some", &self.factory.is_some())
37 .field("semicolon_for_empty", &self.semicolon_for_empty)
38 .finish()
39 }
40}
41
42impl Generator for Body {
43 fn generate(&self, indentation: Indentation, level: usize) -> String {
44 match self.factory {
45 Some(ref factory) => {
46 let mut code = String::new();
47
48 code.push_str(" {");
49 code.push('\n');
50 code.push_str(&factory(indentation, level + 1));
51 code.push('\n');
52 code.push_str(&indentation.indent("}", level));
53 code.push('\n');
54
55 code
56 }
57 None => {
58 let mut code = String::new();
59
60 if self.semicolon_for_empty {
61 code.push(';');
62 } else {
63 code.push_str(" {}");
64 }
65
66 code.push('\n');
67
68 code
69 }
70 }
71 }
72}
73
74impl<T: ToString> From<Vec<T>> for Body {
75 fn from(body: Vec<T>) -> Self {
76 let body = body
77 .iter()
78 .map(|line| line.to_string())
79 .collect::<Vec<String>>();
80
81 Self {
82 factory: Some(Box::new(move |indentation, level| {
83 let body = body.clone();
84
85 body.iter()
86 .map(|line| indentation.indent(line.to_string(), level))
87 .collect::<Vec<String>>()
88 .join("\n")
89 })),
90 semicolon_for_empty: true,
91 }
92 }
93}
94
95impl From<String> for Body {
96 fn from(body: String) -> Self {
97 Self {
98 factory: Some(Box::new(move |indentation, level| {
99 let body = body.clone();
100
101 indentation.indent(body, level)
102 })),
103 semicolon_for_empty: true,
104 }
105 }
106}
107
108impl From<&str> for Body {
109 fn from(body: &str) -> Self {
110 body.to_string().into()
111 }
112}
113
114impl<T: Fn(Indentation, usize) -> String + 'static> From<T> for Body {
115 fn from(factory: T) -> Self {
116 Self {
117 factory: Some(Box::new(factory)),
118 semicolon_for_empty: true,
119 }
120 }
121}
122
123impl From<Option<Box<dyn Fn(Indentation, usize) -> String>>> for Body {
124 fn from(factory: Option<Box<dyn Fn(Indentation, usize) -> String>>) -> Self {
125 Self {
126 factory,
127 semicolon_for_empty: true,
128 }
129 }
130}
131
132impl From<Option<String>> for Body {
133 fn from(body: Option<String>) -> Self {
134 match body {
135 Some(body) => body.into(),
136 None => Self {
137 factory: None,
138 semicolon_for_empty: true,
139 },
140 }
141 }
142}
143
144impl Default for Body {
145 fn default() -> Self {
146 Self {
147 factory: None,
148 semicolon_for_empty: true,
149 }
150 }
151}