Parse the cursor's content using any allocator that implements the Allocator trait.
(&self, allocator: A)
| 564 | |
| 565 | /// Parse the cursor's content using any allocator that implements the Allocator trait. |
| 566 | pub fn parse<A: Allocator + Clone + 'a>(&self, allocator: A) -> CowStr<'a, A> { |
| 567 | debug_assert!(self.token() != Kind::Delim); |
| 568 | let start = self.token().leading_len() as usize; |
| 569 | let end = self.source.len() - self.token().trailing_len() as usize; |
| 570 | if !self.token().contains_escape_chars() { |
| 571 | return CowStr::<A>::Borrowed(&self.source[start..end]); |
| 572 | } |
| 573 | let mut chars = self.source[start..end].chars().peekable(); |
| 574 | let mut i = 0; |
| 575 | let mut vec: Option<Vec<u8, A>> = None; |
| 576 | while let Some(c) = chars.next() { |
| 577 | if c == '\0' { |
| 578 | if vec.is_none() { |
| 579 | vec = if i == 0 { |
| 580 | Some(Vec::new_in(allocator.clone())) |
| 581 | } else { |
| 582 | Some({ |
| 583 | let mut v = Vec::new_in(allocator.clone()); |
| 584 | v.extend(self.source[start..(start + i)].bytes()); |
| 585 | v |
| 586 | }) |
| 587 | } |
| 588 | } |
| 589 | let mut buf = [0; 4]; |
| 590 | let bytes = REPLACEMENT_CHARACTER.encode_utf8(&mut buf).as_bytes(); |
| 591 | vec.as_mut().unwrap().extend_from_slice(bytes); |
| 592 | i += 1; |
| 593 | } else if c == '\\' { |
| 594 | if vec.is_none() { |
| 595 | vec = if i == 0 { |
| 596 | Some(Vec::new_in(allocator.clone())) |
| 597 | } else { |
| 598 | Some({ |
| 599 | let mut v = Vec::new_in(allocator.clone()); |
| 600 | v.extend(self.source[start..(start + i)].bytes()); |
| 601 | v |
| 602 | }) |
| 603 | } |
| 604 | } |
| 605 | // String has special rules |
| 606 | // https://drafts.csswg.org/css-syntax-3/#consume-string-cursor |
| 607 | if self.token().kind_bits() == Kind::String as u8 { |
| 608 | // When the token is a string, escaped EOF points are not consumed |
| 609 | // U+005C REVERSE SOLIDUS (\) |
| 610 | // If the next input code point is EOF, do nothing. |
| 611 | // Otherwise, if the next input code point is a newline, consume it. |
| 612 | let c = chars.peek(); |
| 613 | if let Some(c) = c { |
| 614 | if is_newline(*c) { |
| 615 | chars.next(); |
| 616 | if chars.peek() == Some(&'\n') { |
| 617 | i += 1; |
| 618 | } |
| 619 | i += 2; |
| 620 | chars = self.source[(start + i)..end].chars().peekable(); |
| 621 | continue; |
| 622 | } |
| 623 | } else { |