@@ -208,6 +208,13 @@ impl MultiTemplate {
208208 /// let template = Template::parse("{split:,:..|sort|join: - }").unwrap();
209209 /// ```
210210 pub fn parse ( template : & str ) -> Result < Self , String > {
211+ // Fast-path: if the input is a *single* template block (no outer-level
212+ // literal text) we can skip the multi-template scanner and directly
213+ // parse the operation list.
214+ if let Some ( single) = Self :: try_single_block ( template) ? {
215+ return Ok ( single) ;
216+ }
217+
211218 let ( sections, _) = parser:: parse_multi_template ( template) ?;
212219 Ok ( Self :: new ( template. to_string ( ) , sections, false ) )
213220 }
@@ -252,6 +259,14 @@ impl MultiTemplate {
252259 /// let template = Template::parse_with_debug("{upper}", Some(true)).unwrap();
253260 /// ```
254261 pub fn parse_with_debug ( template : & str , debug : Option < bool > ) -> Result < Self , String > {
262+ // Re-use the single-block shortcut when applicable.
263+ if let Some ( mut single) = Self :: try_single_block ( template) ? {
264+ if let Some ( dbg_override) = debug {
265+ single. debug = dbg_override;
266+ }
267+ return Ok ( single) ;
268+ }
269+
255270 let ( sections, inner_dbg) = parser:: parse_multi_template ( template) ?;
256271 Ok ( Self :: new (
257272 template. to_string ( ) ,
@@ -588,6 +603,45 @@ impl MultiTemplate {
588603 . collect :: < Vec < _ > > ( )
589604 . join ( " | " )
590605 }
606+
607+ /* -------- helper: detect plain single-block templates ------------- */
608+
609+ /// Detects and parses templates that consist of exactly one `{ ... }` block
610+ /// with no surrounding literal text. Returns `Ok(Some(MultiTemplate))` when
611+ /// the fast path can be applied, `Ok(None)` otherwise.
612+ fn try_single_block ( template : & str ) -> Result < Option < Self > , String > {
613+ // Must start with '{' and end with '}' to be a candidate.
614+ if !( template. starts_with ( '{' ) && template. ends_with ( '}' ) ) {
615+ return Ok ( None ) ;
616+ }
617+
618+ // Verify that the outer-most braces close at the very end and that the
619+ // brace nesting never returns to zero before the last char.
620+ let mut depth = 0u32 ;
621+ for ch in template[ 1 ..template. len ( ) - 1 ] . chars ( ) {
622+ match ch {
623+ '{' => depth += 1 ,
624+ '}' => {
625+ if depth == 0 {
626+ // Closed the top-level early → literal content exists.
627+ return Ok ( None ) ;
628+ }
629+ depth -= 1 ;
630+ }
631+ _ => { }
632+ }
633+ }
634+
635+ if depth != 0 {
636+ // Unbalanced braces – fall back to full parser for proper error.
637+ return Ok ( None ) ;
638+ }
639+
640+ // Safe to treat as single template block.
641+ let ( ops, dbg_flag) = parser:: parse_template ( template) ?;
642+ let sections = vec ! [ TemplateSection :: Template ( ops) ] ;
643+ Ok ( Some ( Self :: new ( template. to_string ( ) , sections, dbg_flag) ) )
644+ }
591645}
592646
593647/* ---------- trait impls -------------------------------------------------- */
0 commit comments