@@ -23,6 +23,18 @@ pub enum Token {
2323 ) ,
2424 IncompleteSection ( Vec < String > , bool , String , bool ) ,
2525 Partial ( String , String , String ) ,
26+ #[ cfg( feature = "CFEngine" ) ]
27+ At ,
28+ #[ cfg( feature = "CFEngine" ) ]
29+ JSON ( Vec < String > , String ) ,
30+ #[ cfg( feature = "CFEngine" ) ]
31+ JSONMulti ( Vec < String > , String ) ,
32+ #[ cfg( feature = "CFEngine" ) ]
33+ TopJSON ( Vec < String > , String ) ,
34+ #[ cfg( feature = "CFEngine" ) ]
35+ TopJSONMulti ( Vec < String > , String ) ,
36+ #[ cfg( feature = "CFEngine" ) ]
37+ TopSection ( Vec < Token > ) ,
2638}
2739
2840/// Error type to represent parsing failure.
@@ -374,15 +386,38 @@ impl<'a, T: Iterator<Item = char>> Parser<'a, T> {
374386 // ignore comments
375387 self . eat_whitespace ( ) ;
376388 }
377- '&' => {
389+ #[ cfg( feature = "CFEngine" ) ]
390+ '%' => {
391+ // Data to be rendered as multi-line JSON representation
378392 let name = & content[ 1 ..len] ;
379393 let name = get_name_or_implicit ( name) ?;
394+
395+ self . tokens
396+ . push ( if name. first ( ) == Some ( & "-top-" . to_string ( ) ) {
397+ Token :: TopJSONMulti ( name, tag)
398+ } else {
399+ Token :: JSONMulti ( name, tag)
400+ } ) ;
401+ }
402+ #[ cfg( feature = "CFEngine" ) ]
403+ '$' => {
404+ // Data to be rendered as compact JSON representation
405+ let name = get_name_or_implicit ( & content[ 1 ..len] ) ?;
406+
407+ self . tokens
408+ . push ( if name. first ( ) == Some ( & "-top-" . to_string ( ) ) {
409+ Token :: TopJSON ( name, tag)
410+ } else {
411+ Token :: JSON ( name, tag)
412+ } ) ;
413+ }
414+ '&' => {
415+ let name = get_name_or_implicit ( & content[ 1 ..len] ) ?;
380416 self . tokens . push ( Token :: UnescapedTag ( name, tag) ) ;
381417 }
382418 '{' => {
383419 if content. ends_with ( '}' ) {
384- let name = & content[ 1 ..len - 1 ] ;
385- let name = get_name_or_implicit ( name) ?;
420+ let name = get_name_or_implicit ( & content[ 1 ..len - 1 ] ) ?;
386421 self . tokens . push ( Token :: UnescapedTag ( name, tag) ) ;
387422 } else {
388423 return Err ( Error :: UnbalancedUnescapeTag ) ;
@@ -402,6 +437,10 @@ impl<'a, T: Iterator<Item = char>> Parser<'a, T> {
402437 self . tokens
403438 . push ( Token :: IncompleteSection ( name, true , tag, newlined) ) ;
404439 }
440+ #[ cfg( feature = "CFEngine" ) ]
441+ '@' => {
442+ self . tokens . push ( Token :: At ) ;
443+ }
405444 '/' => {
406445 self . eat_whitespace ( ) ;
407446
@@ -423,6 +462,12 @@ impl<'a, T: Iterator<Item = char>> Parser<'a, T> {
423462 let mut srcs = Vec :: new ( ) ;
424463 for child in children. iter ( ) {
425464 match * child {
465+ #[ cfg( feature = "CFEngine" ) ]
466+ Token :: JSON ( _, ref s)
467+ | Token :: JSONMulti ( _, ref s)
468+ | Token :: TopJSON ( _, ref s)
469+ | Token :: TopJSONMulti ( _, ref s) => srcs. push ( s. clone ( ) ) ,
470+
426471 Token :: Text ( ref s)
427472 | Token :: EscapedTag ( _, ref s)
428473 | Token :: UnescapedTag ( _, ref s)
@@ -455,6 +500,24 @@ impl<'a, T: Iterator<Item = char>> Parser<'a, T> {
455500 src. push_str ( s) ;
456501 }
457502
503+ #[ cfg( feature = "CFEngine" ) ]
504+ self . tokens
505+ . push ( if name. first ( ) == Some ( & "-top-" . to_string ( ) ) {
506+ Token :: TopSection ( children)
507+ } else {
508+ Token :: Section (
509+ name,
510+ inverted,
511+ children,
512+ self . opening_tag . clone ( ) ,
513+ osection,
514+ src,
515+ tag,
516+ self . closing_tag . clone ( ) ,
517+ )
518+ } ) ;
519+
520+ #[ cfg( not( feature = "CFEngine" ) ) ]
458521 self . tokens . push ( Token :: Section (
459522 name,
460523 inverted,
@@ -465,6 +528,7 @@ impl<'a, T: Iterator<Item = char>> Parser<'a, T> {
465528 tag,
466529 self . closing_tag . clone ( ) ,
467530 ) ) ;
531+
468532 break ;
469533 } else {
470534 return Err ( Error :: UnclosedSection ( section_name. join ( "." ) ) ) ;
@@ -763,4 +827,39 @@ mod tests {
763827 let input = "{{=<% %>=}} <%{ %>" ;
764828 assert_eq ! ( parse( input) , Err ( Error :: UnbalancedUnescapeTag ) )
765829 }
830+
831+ mod cfengine {
832+ use super :: * ;
833+
834+ #[ test]
835+ fn test_json_multi ( ) {
836+ assert ! ( parse( "{{%var}}" ) . is_ok( ) ) ;
837+ }
838+
839+ #[ test]
840+ fn test_json_compact ( ) {
841+ assert ! ( parse( "{{$var}}" ) . is_ok( ) ) ;
842+ }
843+
844+ #[ test]
845+ fn test_top ( ) {
846+ assert ! ( parse( "{{%-top-}}" ) . is_ok( ) ) ;
847+ assert ! ( parse( "{{$-top-}}" ) . is_ok( ) ) ;
848+ }
849+
850+ #[ test]
851+ fn test_top_section ( ) {
852+ assert ! ( parse( "{{#-top-}} {{.}}{{/-top-}}" ) . is_ok( ) ) ;
853+ }
854+
855+ #[ test]
856+ fn test_at ( ) {
857+ assert ! ( parse( "{{#-top-}} {{{@}}}{{/-top-}}" ) . is_ok( ) ) ;
858+ }
859+
860+ #[ test]
861+ fn test_at_dot ( ) {
862+ assert ! ( parse( "{{#-top-}} {{{@}}} {{.}}{{/-top-}}" ) . is_ok( ) ) ;
863+ }
864+ }
766865}
0 commit comments