File tree Expand file tree Collapse file tree 2 files changed +57
-6
lines changed
crates/djls-templates/src Expand file tree Collapse file tree 2 files changed +57
-6
lines changed Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ use djls_source::Span;
22
33use crate :: tokens:: TagDelimiter ;
44use crate :: tokens:: Token ;
5+ use crate :: tokens:: TokenStream ;
56
67pub struct Lexer {
78 source : String ,
@@ -20,11 +21,7 @@ impl Lexer {
2021 }
2122
2223 pub fn tokenize ( & mut self ) -> Vec < Token > {
23- // Conservative estimate: most templates have 1 token per 15-20 chars
24- // Min 32 to avoid reallocation for tiny templates
25- // Max 1024 to avoid over-allocation for huge templates
26- let estimated_tokens = ( self . source . len ( ) / 15 ) . clamp ( 32 , 1024 ) ;
27- let mut tokens = Vec :: with_capacity ( estimated_tokens) ;
24+ let mut tokens = TokenStream :: with_estimated_capacity ( & self . source ) ;
2825
2926 while !self . is_at_end ( ) {
3027 self . start = self . current ;
@@ -59,7 +56,7 @@ impl Lexer {
5956
6057 tokens. push ( Token :: Eof ) ;
6158
62- tokens
59+ tokens. into ( )
6360 }
6461
6562 fn lex_django_tag (
Original file line number Diff line number Diff line change @@ -289,3 +289,57 @@ impl TokenSnapshotVec {
289289 self . 0 . iter ( ) . map ( Token :: to_snapshot) . collect ( )
290290 }
291291}
292+
293+ #[ derive( Debug , Clone ) ]
294+ pub struct TokenStream ( Vec < Token > ) ;
295+
296+ impl TokenStream {
297+ const CHARS_PER_TOKEN : usize = 6 ;
298+ const MIN_CAPACITY : usize = 32 ;
299+ const MAX_CAPACITY : usize = 1024 ;
300+
301+ #[ must_use]
302+ pub fn with_estimated_capacity ( source : & str ) -> Self {
303+ let capacity =
304+ ( source. len ( ) / Self :: CHARS_PER_TOKEN ) . clamp ( Self :: MIN_CAPACITY , Self :: MAX_CAPACITY ) ;
305+ Self ( Vec :: with_capacity ( capacity) )
306+ }
307+
308+ #[ inline]
309+ pub fn push ( & mut self , token : Token ) {
310+ self . 0 . push ( token) ;
311+ }
312+
313+ /// Get the number of tokens in the stream.
314+ #[ must_use]
315+ pub fn len ( & self ) -> usize {
316+ self . 0 . len ( )
317+ }
318+
319+ /// Get the number of content tokens (excluding EOF).
320+ #[ must_use]
321+ pub fn content_len ( & self ) -> usize {
322+ self . 0 . len ( ) . saturating_sub ( 1 )
323+ }
324+
325+ /// Check if stream is empty.
326+ #[ must_use]
327+ pub fn is_empty ( & self ) -> bool {
328+ self . 0 . is_empty ( )
329+ }
330+ }
331+
332+ impl From < TokenStream > for Vec < Token > {
333+ fn from ( val : TokenStream ) -> Self {
334+ val. 0
335+ }
336+ }
337+
338+ impl IntoIterator for TokenStream {
339+ type Item = Token ;
340+ type IntoIter = std:: vec:: IntoIter < Token > ;
341+
342+ fn into_iter ( self ) -> Self :: IntoIter {
343+ self . 0 . into_iter ( )
344+ }
345+ }
You can’t perform that action at this time.
0 commit comments