Browse Source

Add `get_unchecked` method to `JsString` and `JsStr` (#3898)

* feat: add `get_unchecked` method to `JsString` and `JsStr`

* Clippy: fix

* chore: apply docs suggestions
pull/3907/head
CrazyboyQCD 4 months ago committed by GitHub
parent
commit
6bc78bf523
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 15
      core/string/src/lib.rs
  2. 95
      core/string/src/str.rs

15
core/string/src/lib.rs

@ -823,6 +823,21 @@ impl JsString {
I::get(self.as_str(), index) I::get(self.as_str(), index)
} }
/// Returns an element or subslice depending on the type of index, without doing bounds check.
///
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
#[must_use]
pub unsafe fn get_unchecked<'a, I>(&'a self, index: I) -> I::Value
where
I: JsSliceIndex<'a>,
{
// Safety: Caller must ensure the index is not out of bounds
unsafe { I::get_unchecked(self.as_str(), index) }
}
/// Get the element a the given index. /// Get the element a the given index.
/// ///
/// # Panics /// # Panics

95
core/string/src/str.rs

@ -191,6 +191,21 @@ impl<'a> JsStr<'a> {
I::get(self, index) I::get(self, index)
} }
/// Returns an element or subslice depending on the type of index, without doing bounds check.
///
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
#[must_use]
pub unsafe fn get_unchecked<I>(self, index: I) -> I::Value
where
I: JsSliceIndex<'a>,
{
// Safety: Caller must ensure the index is not out of bounds
unsafe { I::get_unchecked(self, index) }
}
/// Convert the [`JsStr`] into a [`Vec<U16>`]. /// Convert the [`JsStr`] into a [`Vec<U16>`].
#[inline] #[inline]
#[must_use] #[must_use]
@ -295,6 +310,8 @@ pub trait JsSliceIndex<'a>: SliceIndex<[u8]> + SliceIndex<[u16]> {
type Value; type Value;
fn get(_: JsStr<'a>, index: Self) -> Option<Self::Value>; fn get(_: JsStr<'a>, index: Self) -> Option<Self::Value>;
unsafe fn get_unchecked(value: JsStr<'a>, index: Self) -> Self::Value;
} }
impl<'a> JsSliceIndex<'a> for usize { impl<'a> JsSliceIndex<'a> for usize {
@ -307,6 +324,20 @@ impl<'a> JsSliceIndex<'a> for usize {
JsStrVariant::Utf16(v) => v.get(index).copied(), JsStrVariant::Utf16(v) => v.get(index).copied(),
} }
} }
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
unsafe fn get_unchecked(value: JsStr<'a>, index: Self) -> Self::Value {
// Safety: Caller must ensure the index is not out of bounds
unsafe {
match value.variant() {
JsStrVariant::Latin1(v) => u16::from(*v.get_unchecked(index)),
JsStrVariant::Utf16(v) => *v.get_unchecked(index),
}
}
}
} }
impl<'a> JsSliceIndex<'a> for std::ops::Range<usize> { impl<'a> JsSliceIndex<'a> for std::ops::Range<usize> {
@ -319,6 +350,20 @@ impl<'a> JsSliceIndex<'a> for std::ops::Range<usize> {
JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16), JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16),
} }
} }
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
unsafe fn get_unchecked(value: JsStr<'a>, index: Self) -> Self::Value {
// Safety: Caller must ensure the index is not out of bounds
unsafe {
match value.variant() {
JsStrVariant::Latin1(v) => JsStr::latin1(v.get_unchecked(index)),
JsStrVariant::Utf16(v) => JsStr::utf16(v.get_unchecked(index)),
}
}
}
} }
impl<'a> JsSliceIndex<'a> for std::ops::RangeInclusive<usize> { impl<'a> JsSliceIndex<'a> for std::ops::RangeInclusive<usize> {
@ -331,6 +376,20 @@ impl<'a> JsSliceIndex<'a> for std::ops::RangeInclusive<usize> {
JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16), JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16),
} }
} }
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
unsafe fn get_unchecked(value: JsStr<'a>, index: Self) -> Self::Value {
// Safety: Caller must ensure the index is not out of bounds
unsafe {
match value.variant() {
JsStrVariant::Latin1(v) => JsStr::latin1(v.get_unchecked(index)),
JsStrVariant::Utf16(v) => JsStr::utf16(v.get_unchecked(index)),
}
}
}
} }
impl<'a> JsSliceIndex<'a> for std::ops::RangeFrom<usize> { impl<'a> JsSliceIndex<'a> for std::ops::RangeFrom<usize> {
@ -343,6 +402,20 @@ impl<'a> JsSliceIndex<'a> for std::ops::RangeFrom<usize> {
JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16), JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16),
} }
} }
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
unsafe fn get_unchecked(value: JsStr<'a>, index: Self) -> Self::Value {
// Safety: Caller must ensure the index is not out of bounds
unsafe {
match value.variant() {
JsStrVariant::Latin1(v) => JsStr::latin1(v.get_unchecked(index)),
JsStrVariant::Utf16(v) => JsStr::utf16(v.get_unchecked(index)),
}
}
}
} }
impl<'a> JsSliceIndex<'a> for std::ops::RangeTo<usize> { impl<'a> JsSliceIndex<'a> for std::ops::RangeTo<usize> {
@ -355,6 +428,20 @@ impl<'a> JsSliceIndex<'a> for std::ops::RangeTo<usize> {
JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16), JsStrVariant::Utf16(v) => v.get(index).map(JsStr::utf16),
} }
} }
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
unsafe fn get_unchecked(value: JsStr<'a>, index: Self) -> Self::Value {
// Safety: Caller must ensure the index is not out of bounds
unsafe {
match value.variant() {
JsStrVariant::Latin1(v) => JsStr::latin1(v.get_unchecked(index)),
JsStrVariant::Utf16(v) => JsStr::utf16(v.get_unchecked(index)),
}
}
}
} }
impl<'a> JsSliceIndex<'a> for std::ops::RangeFull { impl<'a> JsSliceIndex<'a> for std::ops::RangeFull {
@ -364,4 +451,12 @@ impl<'a> JsSliceIndex<'a> for std::ops::RangeFull {
fn get(value: JsStr<'a>, _index: Self) -> Option<Self::Value> { fn get(value: JsStr<'a>, _index: Self) -> Option<Self::Value> {
Some(value) Some(value)
} }
/// # Safety
///
/// Caller must ensure the index is not out of bounds
#[inline]
unsafe fn get_unchecked(value: JsStr<'a>, _index: Self) -> Self::Value {
value
}
} }

Loading…
Cancel
Save