@@ -21,6 +21,7 @@ pub struct Cursor<'a> {
2121pub ( crate ) const EOF_CHAR : char = '\0' ;
2222
2323impl < ' a > Cursor < ' a > {
24+ #[ inline]
2425 pub fn new ( input : & ' a str , frontmatter_allowed : FrontmatterAllowed ) -> Cursor < ' a > {
2526 Cursor {
2627 len_remaining : input. len ( ) ,
@@ -31,6 +32,7 @@ impl<'a> Cursor<'a> {
3132 }
3233 }
3334
35+ #[ inline]
3436 pub fn as_str ( & self ) -> & ' a str {
3537 self . chars . as_str ( )
3638 }
@@ -53,12 +55,14 @@ impl<'a> Cursor<'a> {
5355 /// If requested position doesn't exist, `EOF_CHAR` is returned.
5456 /// However, getting `EOF_CHAR` doesn't always mean actual end of file,
5557 /// it should be checked with `is_eof` method.
58+ #[ inline]
5659 pub fn first ( & self ) -> char {
5760 // `.next()` optimizes better than `.nth(0)`
5861 self . chars . clone ( ) . next ( ) . unwrap_or ( EOF_CHAR )
5962 }
6063
6164 /// Peeks the second symbol from the input stream without consuming it.
65+ #[ inline]
6266 pub ( crate ) fn second ( & self ) -> char {
6367 // `.next()` optimizes better than `.nth(1)`
6468 let mut iter = self . chars . clone ( ) ;
@@ -67,6 +71,7 @@ impl<'a> Cursor<'a> {
6771 }
6872
6973 /// Peeks the third symbol from the input stream without consuming it.
74+ #[ inline]
7075 pub fn third ( & self ) -> char {
7176 // `.next()` optimizes better than `.nth(2)`
7277 let mut iter = self . chars . clone ( ) ;
@@ -76,21 +81,25 @@ impl<'a> Cursor<'a> {
7681 }
7782
7883 /// Checks if there is nothing more to consume.
84+ #[ inline]
7985 pub ( crate ) fn is_eof ( & self ) -> bool {
8086 self . chars . as_str ( ) . is_empty ( )
8187 }
8288
8389 /// Returns amount of already consumed symbols.
90+ #[ inline]
8491 pub ( crate ) fn pos_within_token ( & self ) -> u32 {
8592 ( self . len_remaining - self . chars . as_str ( ) . len ( ) ) as u32
8693 }
8794
8895 /// Resets the number of bytes consumed to 0.
96+ #[ inline]
8997 pub ( crate ) fn reset_pos_within_token ( & mut self ) {
9098 self . len_remaining = self . chars . as_str ( ) . len ( ) ;
9199 }
92100
93101 /// Moves to the next character.
102+ #[ inline]
94103 pub ( crate ) fn bump ( & mut self ) -> Option < char > {
95104 let c = self . chars . next ( ) ?;
96105
@@ -102,24 +111,75 @@ impl<'a> Cursor<'a> {
102111 Some ( c)
103112 }
104113
114+ #[ inline]
115+ pub ( crate ) fn bump_if ( & mut self , expected : char ) -> bool {
116+ let mut chars = self . chars . clone ( ) ;
117+ if chars. next ( ) == Some ( expected) {
118+ self . chars = chars;
119+ true
120+ } else {
121+ false
122+ }
123+ }
124+
125+ /// Bumps the cursor if the next character is either of the two expected characters.
126+ #[ inline]
127+ pub ( crate ) fn bump_if2 ( & mut self , expected1 : char , expected2 : char ) -> bool {
128+ let mut chars = self . chars . clone ( ) ;
129+ if let Some ( c) = chars. next ( )
130+ && ( c == expected1 || c == expected2) {
131+ self . chars = chars;
132+ return true ;
133+ }
134+ false
135+ }
136+
105137 /// Moves to a substring by a number of bytes.
138+ #[ inline]
106139 pub ( crate ) fn bump_bytes ( & mut self , n : usize ) {
107- self . chars = self . as_str ( ) [ n..] . chars ( ) ;
140+ self . chars = self . as_str ( ) . get ( n..) . unwrap_or ( "" ) . chars ( ) ;
108141 }
109142
110143 /// Eats symbols while predicate returns true or until the end of file is reached.
144+ #[ inline]
111145 pub ( crate ) fn eat_while ( & mut self , mut predicate : impl FnMut ( char ) -> bool ) {
112146 // It was tried making optimized version of this for eg. line comments, but
113147 // LLVM can inline all of this and compile it down to fast iteration over bytes.
114148 while predicate ( self . first ( ) ) && !self . is_eof ( ) {
115149 self . bump ( ) ;
116150 }
117151 }
152+ /// Eats characters until the given byte is found.
153+ /// Returns true if the byte was found, false if end of file was reached.
154+ #[ inline]
155+ pub ( crate ) fn eat_until ( & mut self , byte : u8 ) -> bool {
156+ match memchr:: memchr ( byte, self . as_str ( ) . as_bytes ( ) ) {
157+ Some ( index) => {
158+ self . bump_bytes ( index) ;
159+ true
160+ }
161+ None => {
162+ self . chars = "" . chars ( ) ;
163+ false
164+ }
165+ }
166+ }
118167
119- pub ( crate ) fn eat_until ( & mut self , byte : u8 ) {
120- self . chars = match memchr:: memchr ( byte, self . as_str ( ) . as_bytes ( ) ) {
121- Some ( index) => self . as_str ( ) [ index..] . chars ( ) ,
122- None => "" . chars ( ) ,
168+ /// Eats characters until any of the given bytes is found, then consumes past it.
169+ /// Returns the found byte if any, or None if end of file was reached.
170+ #[ inline]
171+ pub ( crate ) fn eat_past2 ( & mut self , byte1 : u8 , byte2 : u8 ) -> Option < u8 > {
172+ let bytes = self . as_str ( ) . as_bytes ( ) ;
173+ match memchr:: memchr2 ( byte1, byte2, bytes) {
174+ Some ( index) => {
175+ let found = bytes[ index] ;
176+ self . bump_bytes ( index + 1 ) ;
177+ Some ( found)
178+ }
179+ None => {
180+ self . chars = "" . chars ( ) ;
181+ None
182+ }
123183 }
124184 }
125185}
0 commit comments