yamlette/
composer.rs

1#[macro_export]
2macro_rules! yamlette_compose {
3    ( ignore ; $ignored:tt ; $expr:tt ) => { $expr };
4
5    ( orchestra ; $orchestra:expr ; $volumes:tt ) => {{ $crate::yamlette_compose! ( volumes ; &$orchestra ; $volumes ; [ ] ; [ ] ) }};
6
7    ( size ; [# $( $style:expr ),* => $( $element:tt ),* ] ) => {{ $crate::yamlette_compose! ( size ; [ $( $element ),* ] ) }};
8
9    ( size ; [ $( $element:tt ),* ] ) => {{
10        let mut _size = 1;
11
12        $(
13            _size += $crate::yamlette_compose! ( size ; $element );
14        )*
15
16        _size
17    }};
18
19    ( size ; {# $( $style:expr ),* => $( $key:tt : $val:tt ),* } ) => {{ $crate::yamlette_compose! ( size ; { $( $key : $val ),* } ) }};
20
21    ( size ; { $( $key:tt : $val:tt ),* } ) => {{
22        let mut _size = 1;
23
24        $(
25            _size += $crate::yamlette_compose! ( size ; $key );
26            _size += $crate::yamlette_compose! ( size ; $val );
27        )*
28
29        _size
30    }};
31
32    ( size ; ( # $( $style:expr ),* => $elem:tt ) ) => {{ $crate::yamlette_compose! ( size ; $elem ) }};
33
34    ( size ; ( # $( $style:expr ),* => $elem:expr ) ) => {{ $crate::yamlette_compose! ( size ; $elem ) }};
35
36    ( size ; ( & $alias:ident $elem:tt ) ) => {{ $crate::yamlette_compose! ( size ; $elem ) }};
37
38    ( size ; ( & $alias:ident $elem:expr ) ) => {{ $crate::yamlette_compose! ( size ; $elem ) }};
39
40    ( size ; ( * $link:ident ) ) => {{ 1 }};
41
42    ( size ; ( $elem:tt ) ) => {{ $crate::yamlette_compose! ( size ; $elem ) }};
43
44    ( size ; ( $elem:expr ) ) => {{ $crate::yamlette_compose! ( size ; $elem ) }};
45
46    ( size ; $element:expr ) => {{
47        use $crate::orchestra::chord::Chord;
48        Chord::chord_size (&$element)
49    }};
50
51
52    ( directives ; $orchestra:expr ; $directives:tt ) => {{
53        let _tags_count = $crate::yamlette_compose! ( directives ; tags count ; $directives );
54
55        if _tags_count > 0 {
56            use std::borrow::Cow;
57
58            let mut _tags: Vec<(Cow<'static, str>, Cow<'static, str>)> = Vec::with_capacity (_tags_count);
59            $crate::yamlette_compose! ( directives ; collect tags ; _tags ; $directives );
60            $orchestra.directive_tags (_tags).ok ().unwrap ();
61        }
62
63        $crate::yamlette_compose! ( directives ; others ; $orchestra ; $directives );
64    }};
65
66    ( directives ; tags count ; [ $( $directive:tt ),* ] ) => {{
67        let mut _size = 0;
68        $( _size += $crate::yamlette_compose! ( directives ; tag count ; $directive ); )*
69        _size
70    }};
71
72    ( directives ; tag count ; (TAG ; $shortcut:expr , $handle:expr ) ) => { 1 };
73    ( directives ; tag count ; $directive:tt ) => { 0 };
74
75    ( directives ; collect tags ; $vec:expr ; [ $( $directive:tt ),* ] ) => { $( $crate::yamlette_compose! ( directive ; collect tags ; $vec ; $directive ); )* };
76    ( directive ; collect tags ; $vec:expr ; (TAG ; $shortcut:expr , $handle:expr ) ) => { $vec.push ( (Cow::from ($shortcut) , Cow::from ($handle)) ); };
77    ( directive ; collect tags ; $vec:expr ; $directive:tt ) => {{ }};
78
79    ( directives ; others ; $orchestra:expr ; [ $( $directive:tt ),* ] ) => {{ $( $crate::yamlette_compose! ( directive ; others ; $orchestra ; $directive ); )* }};
80    ( directive ; others ; $orchestra:expr ; YAML ) => {{ $orchestra.directive_yaml (true).ok ().unwrap (); }};
81    ( directive ; others ; $orchestra:expr ; NO_YAML ) => {{ $orchestra.directive_yaml (false).ok ().unwrap (); }};
82    ( directive ; others ; $orchestra:expr ; BORDER_TOP ) => {{ $orchestra.volume_border_top (true).ok ().unwrap (); }};
83    ( directive ; others ; $orchestra:expr ; NO_BORDER_TOP ) => {{ $orchestra.volume_border_top (false).ok ().unwrap (); }};
84    ( directive ; others ; $orchestra:expr ; BORDER_BOT ) => {{ $orchestra.volume_border_bot (true).ok ().unwrap (); }};
85    ( directive ; others ; $orchestra:expr ; NO_BORDER_BOT ) => {{ $orchestra.volume_border_bot (false).ok ().unwrap (); }};
86    ( directive ; others ; $orchestra:expr ; (TAG ; $shortcut:expr , $handle:expr ) ) => {};
87
88
89    ( styles ; [ $( $style:expr ),* ] ) => { [ $( &mut $style as &mut dyn $crate::model::style::Style ),* ] };
90
91    ( styles ; apply to common ; $common_styles:expr ; $styles:tt ) => {{
92        let mut cstyles = $common_styles;
93
94        let styles: &mut [ &mut dyn $crate::model::style::Style ] = &mut $crate::yamlette_compose! ( styles ; $styles );
95
96        for style in styles {
97            style.common_styles_apply (&mut cstyles);
98        }
99
100        cstyles
101    }};
102
103
104    ( volumes ; $orchestra:expr ; [ # $( $style:expr ),* => % $( $directive:tt ),* => $( $volume:tt ),* ] ; [ ] ; [ ] ) => {{
105        $crate::yamlette_compose! ( volumes ; $orchestra ; [ $( $volume ),* ] ; [ $( $style ),* ] ; [ $( $directive ),* ] )
106    }};
107
108
109    ( volumes ; $orchestra:expr ; [ % $( $directive:tt ),* => $( $volume:tt ),* ] ; [ ] ; [ ] ) => {{
110        $crate::yamlette_compose! ( volumes ; $orchestra ; [ $( $volume ),* ] ; [ ] ; [ $( $directive ),* ] )
111    }};
112
113
114    ( volumes ; $orchestra:expr ; [ # $( $style:expr ),* => $( $volume:tt ),* ] ; [ ] ; [ ] ) => {{
115        $crate::yamlette_compose! ( volumes ; $orchestra ; [ $( $volume ),* ] ; [ $( $style ),* ] ; [ ] )
116    }};
117
118
119    ( volumes ; $orchestra:expr ; [ $( $volume:tt ),* ] ; $styles:tt ; $directives:tt ) => {{
120        let mut _size = 0;
121
122        $( $crate::yamlette_compose! ( ignore ; $volume ; { _size += 1; } ); )*
123
124        $orchestra.volumes (_size).ok ().unwrap ();
125
126        let _common_styles = $orchestra.get_styles ();
127
128        $(
129            $crate::yamlette_compose! ( volume ; $orchestra ; _common_styles ; $volume ; $styles ; $directives );
130
131            $orchestra.vol_end ().ok ().unwrap ();
132        )*
133
134        $orchestra.the_end ().ok ().unwrap ();
135    }};
136
137
138    ( volume ; $orchestra:expr ; $common_styles:expr ; [ # $( $style:expr ),+ => % $( $directive:tt ),+ => $( $rule:tt ),* ] ; [ ] ; [ ] ) => {{
139        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; [ $( $style ),* ] ; [ $( $directive ),* ] );
140    }};
141
142    ( volume ; $orchestra:expr ; $common_styles:expr ; [ # $( $style:expr ),+ => % $( $directive:tt ),+ => $( $rule:tt ),* ] ; [ $( $parent_style:expr ),* ] ; [ ] ) => {{
143        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; [ $( $parent_style ),* , $( $style ),* ] ; [ $( $directive ),* ] );
144    }};
145
146
147    ( volume ; $orchestra:expr ; $common_styles:expr ; [ # $( $style:expr ),+ => % $( $directive:tt ),+ => $( $rule:tt ),* ] ; [ ] ; [ $( $parent_directive:tt ),* ] ) => {{
148        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; [ $( $style ),* ] ; [ $( $parent_directive ),* , $( $directive ),* ] );
149    }};
150
151
152    ( volume ; $orchestra:expr ; $common_styles:expr ; [ # $( $style:expr ),+ => % $( $directive:tt ),+ => $( $rule:tt ),* ] ; [ $( $parent_style:expr ),* ] ; [ $( $parent_directive:tt ),* ] ) => {{
153        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; [ $( $parent_style ),* , $( $style ),* ] ; [ $( $parent_directive ),* , $( $directive ),* ] );
154    }};
155
156
157    ( volume ; $orchestra:expr ; $common_styles:expr ; [ % $( $directive:tt ),* => $( $rule:tt ),* ] ; $styles:tt ; [ ] ) => {{
158        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; $styles ; [ $( $directive ),* ] );
159    }};
160
161
162    ( volume ; $orchestra:expr ; $common_styles:expr ; [ % $( $directive:tt ),* => $( $rule:tt ),* ] ; $styles:tt ; [ $( $parent_directive:tt ),* ] ) => {{
163        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; $styles ; [ $( $parent_directive ),* , $( $directive ),* ] );
164    }};
165
166
167    ( volume ; $orchestra:expr ; $common_styles:expr ; [ # $( $style:expr ),* => $( $rule:tt ),* ] ; [ ] ; $directives:tt ) => {{
168        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; [ $( $style ),* ] ; $directives );
169    }};
170
171
172    ( volume ; $orchestra:expr ; $common_styles:expr ; [ # $( $style:expr ),* => $( $rule:tt ),* ] ; [ $( $parent_style:expr ),* ] ; $directives:tt ) => {{
173        $crate::yamlette_compose! ( volume ; $orchestra ; $common_styles ; [ $( $rule ),* ] ; [ $( $parent_style ),* , $( $style ),* ] ; $directives );
174    }};
175
176
177    ( volume ; $orchestra:expr ; $common_styles:expr ; [ $( $rules:tt ),* ] ; $styles:tt ; $directives:tt ) => {{
178        let mut _size = 0;
179
180        $orchestra.vol_next ().ok ().unwrap ();
181
182        $crate::yamlette_compose! ( directives ; $orchestra ; $directives );
183
184        $( $crate::yamlette_compose! ( ignore ; $rules ; { _size += $crate::yamlette_compose! ( size ; $rules ); } ); )*
185
186        $orchestra.vol_reserve (_size).ok ().unwrap ();
187
188        let _common_styles = $crate::yamlette_compose! ( styles ; apply to common ; $common_styles ; $styles );
189
190        $(
191            $crate::yamlette_compose! ( play ; $orchestra ; 0 ; $rules ; _common_styles ; $styles ; None );
192        )*
193    }};
194
195
196    ( play ; $orchestra:expr ; $level:expr ; [ # $( $style:expr ),* => $( $element:tt ),* ] ; $common_styles:expr ; [] ; $alias:expr ) => {{
197        $crate::yamlette_compose! ( play ; $orchestra ; $level ; [ $( $element ),* ] ; $common_styles ; [ $( $style ),* ] ; $alias )
198    }};
199
200
201    ( play ; $orchestra:expr ; $level:expr ; [ # $( $style:expr ),* => $( $element:tt ),* ] ; $common_styles:expr ; [ $( $parent_style:expr ),+ ] ; $alias:expr ) => {{
202        $crate::yamlette_compose! ( play ; $orchestra ; $level ; [ $( $element ),* ] ; $common_styles ; [ $( $parent_style ),* , $( $style ),* ] ; $alias )
203    }};
204
205
206    ( play ; $orchestra:expr ; $level:expr ; [ $( $element:tt ),* ] ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
207        use $crate::orchestra::chord::{ Chord, EmptyList };
208
209        let styles: &mut [ &mut dyn $crate::model::style::Style ] = &mut $crate::yamlette_compose! ( styles ; $styles );
210
211        Chord::play (EmptyList, $orchestra, $level, $alias, $common_styles, styles).ok ().unwrap ();
212
213        let _common_styles = $crate::yamlette_compose! ( styles ; apply to common ; $common_styles ; $styles );
214
215        $(
216            $crate::yamlette_compose! ( play ; $orchestra ; $level + 1 ; $element ; _common_styles ; $styles ; None );
217        )*
218    }};
219
220
221    ( play ; $orchestra:expr ; $level:expr ; { # $( $style:expr ),* => $( $key:tt : $val:tt ),* } ; $common_styles:expr ; [] ; $alias:expr ) => {{
222        $crate::yamlette_compose! ( play ; $orchestra ; $level ; { $( $key : $val ),* } ; $common_styles ; [ $( $style ),* ] ; $alias )
223    }};
224
225
226    ( play ; $orchestra:expr ; $level:expr ; { # $( $style:expr ),* => $( $key:tt : $val:tt ),* } ; $common_styles:expr ; [ $( $parent_style:expr ),+ ] ; $alias:expr ) => {{
227        $crate::yamlette_compose! ( play ; $orchestra ; $level ; { $( $key : $val ),* } ; $common_styles ; [ $( $parent_style ),* , $( $style ),* ] ; $alias )
228    }};
229
230
231    ( play ; $orchestra:expr ; $level:expr ; { $( $key:tt : $val:tt ),* } ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
232        use $crate::orchestra::chord::{ Chord, EmptyDict };
233
234        let styles: &mut [ &mut dyn $crate::model::style::Style ] = &mut $crate::yamlette_compose! ( styles ; $styles );
235
236        Chord::play (EmptyDict, $orchestra, $level, $alias, $common_styles, styles).ok ().unwrap ();
237
238        let _common_styles = $crate::yamlette_compose! ( styles ; apply to common ; $common_styles ; $styles );
239
240        $(
241            $crate::yamlette_compose! ( play ; $orchestra ; $level + 1 ; $key ; _common_styles ; $styles ; None );
242            $crate::yamlette_compose! ( play ; $orchestra ; $level + 1 ; $val ; _common_styles ; $styles ; None );
243        )*
244    }};
245
246
247    ( play ; $orchestra:expr ; $level:expr ; ( # $( $style:expr ),* => $element:tt ) ; $common_styles:expr ; [ ] ; $alias:expr ) => {{
248        let _common_styles = $crate::yamlette_compose! ( styles ; apply to common ; $common_styles ; [ $( $style ),* ] );
249
250        $crate::yamlette_compose! ( play ; $orchestra ; $level ; $element ; _common_styles ; [ $( $style ),* ] ; $alias );
251    }};
252
253    ( play ; $orchestra:expr ; $level:expr ; ( # $( $style:expr ),* => $element:tt ) ; $common_styles:expr ; [ $( $parent_style:expr ),* ] ; $alias:expr ) => {{
254        let _common_styles = $crate::yamlette_compose! ( styles ; apply to common ; $common_styles ; [ $( $style ),* ] );
255
256        $crate::yamlette_compose! ( play ; $orchestra ; $level ; $element ; _common_styles ; [ $( $parent_style ),* , $( $style ),* ] ; $alias );
257    }};
258
259    ( play ; $orchestra:expr ; $level:expr ; ( # $( $style:expr ),* => $element:expr ) ; $common_styles:expr ; [ ] ; $alias:expr ) => {{
260        let _common_styles = $crate::yamlette_compose! ( styles ; apply to common ; $common_styles ; [ $( $style ),* ] );
261
262        $crate::yamlette_compose! ( play ; $orchestra ; $level ; $element ; _common_styles ; [ $( $style ),* ] ; $alias );
263    }};
264
265    ( play ; $orchestra:expr ; $level:expr ; ( # $( $style:expr ),* => $element:expr ) ; $common_styles:expr ; [ $( $parent_style:expr ),* ] ; $alias:expr ) => {{
266        let _common_styles = $crate::yamlette_compose! ( styles ; apply to common ; $common_styles ; [ $( $style ),* ] );
267
268        $crate::yamlette_compose! ( unit ; $orchestra ; $level ; $element ; _common_styles ; [ $( $parent_style ),* , $( $style ),* ] ; $alias );
269    }};
270
271    ( play ; $orchestra:expr ; $level:expr ; ( & $new_alias:ident $element:tt ) ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
272        use std::borrow::Cow;
273        $crate::yamlette_compose! ( play ; $orchestra ; $level ; $element ; $common_styles ; $styles ; Some (Cow::from (stringify! ($new_alias))) );
274    }};
275
276    ( play ; $orchestra:expr ; $level:expr ; ( & $new_alias:ident $element:expr ) ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
277        use std::borrow::Cow;
278        $crate::yamlette_compose! ( play ; $orchestra ; $level ; $element ; $common_styles ; $styles ; Some (Cow::from (stringify! ($new_alias))) );
279    }};
280
281    ( play ; $orchestra:expr ; $level:expr ; ( * $link:ident ) ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
282        use $crate::model::yamlette::literal::LiteralValue;
283        use $crate::model::TaggedValue;
284        $orchestra.play ($level, TaggedValue::from (LiteralValue::from (format! ("*{}", stringify! ($link))))).ok ().unwrap ();
285    }};
286
287    ( play ; $orchestra:expr ; $level:expr ; ( $element:tt ) ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
288        $crate::yamlette_compose! ( play ; $orchestra ; $level ; $element ; $common_styles ; $styles ; $alias );
289    }};
290
291    ( play ; $orchestra:expr ; $level:expr ; ( $element:expr ) ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
292        $crate::yamlette_compose! ( unit ; $orchestra ; $level ; $element ; $common_styles ; $styles ; $alias );
293    }};
294
295
296    ( play ; $orchestra:expr ; $level:expr ; $element:expr ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
297        $crate::yamlette_compose! ( unit ; $orchestra ; $level ; $element ; $common_styles ; $styles ; $alias );
298    }};
299
300
301    ( unit ; $orchestra:expr ; $level:expr ; $element:expr ; $common_styles:expr ; $styles:tt ; $alias:expr ) => {{
302        use $crate::orchestra::chord::Chord;
303
304        let styles: &mut [ &mut dyn $crate::model::style::Style ] = &mut $crate::yamlette_compose! ( styles ; $styles );
305
306        Chord::play ($element, $orchestra, $level, $alias, $common_styles, styles).ok ().unwrap ()
307    }};
308}
309
310#[cfg(all(test, not(feature = "dev")))]
311mod tests {
312    #[test]
313    fn size() {
314        let size = yamlette_compose! ( size ; "halo" );
315        assert_eq!(1, size);
316
317        let size = yamlette_compose! ( size ; () );
318        assert_eq!(1, size);
319
320        let size = yamlette_compose! ( size ; [ (), 1, "2", [ 4, { "a": 1, "b": 4 }, 3 ], () ] );
321        assert_eq!(13, size);
322    }
323}