diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-02 18:36:06 -0600 |
| commit | 8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch) | |
| tree | 22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/matchit/src/escape.rs | |
| parent | 4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff) | |
chore: add vendor directory
Diffstat (limited to 'vendor/matchit/src/escape.rs')
| -rw-r--r-- | vendor/matchit/src/escape.rs | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/vendor/matchit/src/escape.rs b/vendor/matchit/src/escape.rs new file mode 100644 index 00000000..ef8ddbfb --- /dev/null +++ b/vendor/matchit/src/escape.rs @@ -0,0 +1,184 @@ +use std::{fmt, ops::Range}; + +/// An unescaped route that keeps track of the position of escaped characters ('{{' or '}}'). +/// +/// Note that this type dereferences to `&[u8]`. +#[derive(Clone, Default)] +pub struct UnescapedRoute { + // The raw unescaped route. + inner: Vec<u8>, + escaped: Vec<usize>, +} + +impl UnescapedRoute { + /// Unescapes escaped brackets ('{{' or '}}') in a route. + pub fn new(mut inner: Vec<u8>) -> UnescapedRoute { + let mut escaped = Vec::new(); + let mut i = 0; + + while let Some(&c) = inner.get(i) { + if (c == b'{' && inner.get(i + 1) == Some(&b'{')) + || (c == b'}' && inner.get(i + 1) == Some(&b'}')) + { + inner.remove(i); + escaped.push(i); + } + + i += 1; + } + + UnescapedRoute { inner, escaped } + } + + /// Returns true if the character at the given index was escaped. + pub fn is_escaped(&self, i: usize) -> bool { + self.escaped.contains(&i) + } + + /// Replaces the characters in the given range. + pub fn splice( + &mut self, + range: Range<usize>, + replace: Vec<u8>, + ) -> impl Iterator<Item = u8> + '_ { + // Ignore any escaped characters in the range being replaced. + self.escaped.retain(|x| !range.contains(x)); + + // Update the escaped indices. + let offset = (replace.len() as isize) - (range.len() as isize); + for i in &mut self.escaped { + if *i > range.end { + *i = i.checked_add_signed(offset).unwrap(); + } + } + + self.inner.splice(range, replace) + } + + /// Appends another route to the end of this one. + pub fn append(&mut self, other: &UnescapedRoute) { + for i in &other.escaped { + self.escaped.push(self.inner.len() + i); + } + + self.inner.extend_from_slice(&other.inner); + } + + /// Truncates the route to the given length. + pub fn truncate(&mut self, to: usize) { + self.escaped.retain(|&x| x < to); + self.inner.truncate(to); + } + + /// Returns a reference to this route. + pub fn as_ref(&self) -> UnescapedRef<'_> { + UnescapedRef { + inner: &self.inner, + escaped: &self.escaped, + offset: 0, + } + } + + /// Returns a reference to the unescaped slice. + pub fn unescaped(&self) -> &[u8] { + &self.inner + } + + /// Returns the unescaped route. + pub fn into_unescaped(self) -> Vec<u8> { + self.inner + } +} + +impl std::ops::Deref for UnescapedRoute { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl fmt::Debug for UnescapedRoute { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(std::str::from_utf8(&self.inner).unwrap(), f) + } +} + +/// A reference to an `UnescapedRoute`. +#[derive(Copy, Clone)] +pub struct UnescapedRef<'a> { + pub inner: &'a [u8], + escaped: &'a [usize], + // An offset applied to each escaped index. + offset: isize, +} + +impl<'a> UnescapedRef<'a> { + /// Converts this reference into an owned route. + pub fn to_owned(self) -> UnescapedRoute { + let mut escaped = Vec::new(); + for &i in self.escaped { + let i = i.checked_add_signed(self.offset); + + match i { + Some(i) if i < self.inner.len() => escaped.push(i), + _ => {} + } + } + + UnescapedRoute { + escaped, + inner: self.inner.to_owned(), + } + } + + /// Returns `true` if the character at the given index was escaped. + pub fn is_escaped(&self, i: usize) -> bool { + if let Some(i) = i.checked_add_signed(-self.offset) { + return self.escaped.contains(&i); + } + + false + } + + /// Slices the route with `start..`. + pub fn slice_off(&self, start: usize) -> UnescapedRef<'a> { + UnescapedRef { + inner: &self.inner[start..], + escaped: self.escaped, + offset: self.offset - (start as isize), + } + } + + /// Slices the route with `..end`. + pub fn slice_until(&self, end: usize) -> UnescapedRef<'a> { + UnescapedRef { + inner: &self.inner[..end], + escaped: self.escaped, + offset: self.offset, + } + } + + /// Returns a reference to the unescaped slice. + pub fn unescaped(&self) -> &[u8] { + self.inner + } +} + +impl<'a> std::ops::Deref for UnescapedRef<'a> { + type Target = &'a [u8]; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl<'a> fmt::Debug for UnescapedRef<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UnescapedRef") + .field("inner", &std::str::from_utf8(self.inner)) + .field("escaped", &self.escaped) + .field("offset", &self.offset) + .finish() + } +} |
