MCPcopy Create free account
hub / github.com/csskit/csskit / parse_ascii_lower

Method parse_ascii_lower

crates/css_lexer/src/source_cursor.rs:654–711  ·  view source on GitHub ↗

Parse the cursor's content to ASCII lowercase using any allocator that implements the Allocator trait.

(&self, allocator: A)

Source from the content-addressed store, hash-verified

652
653 /// Parse the cursor's content to ASCII lowercase using any allocator that implements the Allocator trait.
654 pub fn parse_ascii_lower<A: Allocator + Clone + 'a>(&self, allocator: A) -> CowStr<'a, A> {
655 debug_assert!(self.token() != Kind::Delim);
656 let start = self.token().leading_len() as usize;
657 let end = self.source.len() - self.token().trailing_len() as usize;
658 if !self.token().contains_escape_chars() && self.token().is_lower_case() {
659 return CowStr::Borrowed(&self.source[start..end]);
660 }
661 let mut chars = self.source[start..end].chars().peekable();
662 let mut i = 0;
663 let mut vec: Vec<u8, A> = Vec::new_in(allocator.clone());
664 while let Some(c) = chars.next() {
665 if c == '\0' {
666 let mut buf = [0; 4];
667 let bytes = REPLACEMENT_CHARACTER.encode_utf8(&mut buf).as_bytes();
668 vec.extend_from_slice(bytes);
669 i += 1;
670 } else if c == '\\' {
671 // String has special rules
672 // https://drafts.csswg.org/css-syntax-3/#consume-string-cursor
673 if self.token().kind_bits() == Kind::String as u8 {
674 // When the token is a string, escaped EOF points are not consumed
675 // U+005C REVERSE SOLIDUS (\)
676 // If the next input code point is EOF, do nothing.
677 // Otherwise, if the next input code point is a newline, consume it.
678 let c = chars.peek();
679 if let Some(c) = c {
680 if is_newline(*c) {
681 chars.next();
682 if chars.peek() == Some(&'\n') {
683 i += 1;
684 }
685 i += 2;
686 chars = self.source[(start + i)..end].chars().peekable();
687 continue;
688 }
689 } else {
690 break;
691 }
692 }
693 i += 1;
694 let (ch, n) = self.source[(start + i)..].chars().parse_escape_sequence();
695 let char_to_push = if ch == '\0' { REPLACEMENT_CHARACTER } else { ch.to_ascii_lowercase() };
696 let mut buf = [0; 4];
697 let bytes = char_to_push.encode_utf8(&mut buf).as_bytes();
698 vec.extend_from_slice(bytes);
699 i += n as usize;
700 chars = self.source[(start + i)..end].chars().peekable();
701 } else {
702 let mut buf = [0; 4];
703 let bytes = c.to_ascii_lowercase().encode_utf8(&mut buf).as_bytes();
704 vec.extend_from_slice(bytes);
705 i += c.len_utf8();
706 }
707 }
708 let boxed_slice = vec.into_boxed_slice();
709 // SAFETY: The source is valid UTF-8, so the slice is valid UTF-8
710 unsafe { CowStr::Owned(Box::from_raw_in(Box::into_raw(boxed_slice) as *mut str, allocator)) }
711 }

Callers

nothing calls this directly

Calls 12

is_newlineFunction · 0.85
leading_lenMethod · 0.80
trailing_lenMethod · 0.80
contains_escape_charsMethod · 0.80
is_lower_caseMethod · 0.80
cloneMethod · 0.80
kind_bitsMethod · 0.80
tokenMethod · 0.45
lenMethod · 0.45
nextMethod · 0.45
peekMethod · 0.45
parse_escape_sequenceMethod · 0.45

Tested by

no test coverage detected