baobao_codegen/builder/
renderable.rs1#[derive(Debug, Clone, PartialEq)]
11pub enum CodeFragment {
12 Line(String),
14 Blank,
16 Raw(String),
18 Block {
20 header: String,
21 body: Vec<CodeFragment>,
22 close: Option<String>,
23 },
24 Indent(Vec<CodeFragment>),
26 Sequence(Vec<CodeFragment>),
28 JsDoc(String),
30 RustDoc(String),
32}
33
34impl CodeFragment {
35 pub fn line(s: impl Into<String>) -> Self {
37 Self::Line(s.into())
38 }
39
40 pub fn blank() -> Self {
42 Self::Blank
43 }
44
45 pub fn raw(s: impl Into<String>) -> Self {
47 Self::Raw(s.into())
48 }
49
50 pub fn block(
52 header: impl Into<String>,
53 body: Vec<CodeFragment>,
54 close: Option<String>,
55 ) -> Self {
56 Self::Block {
57 header: header.into(),
58 body,
59 close,
60 }
61 }
62
63 pub fn indent(fragments: Vec<CodeFragment>) -> Self {
65 Self::Indent(fragments)
66 }
67
68 pub fn sequence(fragments: Vec<CodeFragment>) -> Self {
70 Self::Sequence(fragments)
71 }
72
73 pub fn jsdoc(s: impl Into<String>) -> Self {
75 Self::JsDoc(s.into())
76 }
77
78 pub fn rust_doc(s: impl Into<String>) -> Self {
80 Self::RustDoc(s.into())
81 }
82}
83
84pub trait Renderable {
89 fn to_fragments(&self) -> Vec<CodeFragment>;
91}
92
93impl<T: Renderable + ?Sized> Renderable for &T {
95 fn to_fragments(&self) -> Vec<CodeFragment> {
96 (*self).to_fragments()
97 }
98}
99
100impl<T: Renderable + ?Sized> Renderable for Box<T> {
102 fn to_fragments(&self) -> Vec<CodeFragment> {
103 self.as_ref().to_fragments()
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_code_fragment_constructors() {
113 assert_eq!(
114 CodeFragment::line("test"),
115 CodeFragment::Line("test".to_string())
116 );
117 assert_eq!(CodeFragment::blank(), CodeFragment::Blank);
118 assert_eq!(
119 CodeFragment::raw("raw"),
120 CodeFragment::Raw("raw".to_string())
121 );
122 }
123
124 #[test]
125 fn test_block_fragment() {
126 let block = CodeFragment::block(
127 "if (true) {",
128 vec![CodeFragment::line("return 1;")],
129 Some("}".to_string()),
130 );
131 match block {
132 CodeFragment::Block {
133 header,
134 body,
135 close,
136 } => {
137 assert_eq!(header, "if (true) {");
138 assert_eq!(body.len(), 1);
139 assert_eq!(close, Some("}".to_string()));
140 }
141 _ => panic!("Expected Block variant"),
142 }
143 }
144}