use crate::re2_c;
#[cfg(doc)]
use crate::RE2;
use std::{cmp, fmt, hash, marker::PhantomData, mem, ops, os::raw::c_char, ptr, slice, str};
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct StringView<'a> {
inner: re2_c::StringView,
_ph: PhantomData<&'a u8>,
}
impl<'a> StringView<'a> {
pub fn index_range(&self, range: impl slice::SliceIndex<[u8], Output=[u8]>) -> Option<Self> {
self.as_slice().get(range).map(Self::from_slice)
}
pub const fn empty() -> Self {
let inner = re2_c::StringView {
data_: ptr::null(),
len_: 0,
};
Self::from_native(inner)
}
pub(crate) const fn from_native(inner: re2_c::StringView) -> Self {
Self {
inner,
_ph: PhantomData,
}
}
pub(crate) const fn into_native(self) -> re2_c::StringView { self.inner }
pub const fn from_slice(b: &'a [u8]) -> Self {
let inner = re2_c::StringView {
data_: b.as_ptr() as *const c_char,
len_: b.len(),
};
Self::from_native(inner)
}
pub const fn from_str(s: &'a str) -> Self { Self::from_slice(s.as_bytes()) }
const unsafe fn data_pointer(&self) -> *const u8 { mem::transmute(self.inner.data_) }
pub const fn is_empty(&self) -> bool { self.len() == 0 }
pub const fn len(&self) -> usize { self.inner.len_ }
pub const fn as_slice(&self) -> &'a [u8] {
if self.is_empty() {
&[]
} else {
unsafe { slice::from_raw_parts(self.data_pointer(), self.len()) }
}
}
pub const unsafe fn as_str(&self) -> &'a str { str::from_utf8_unchecked(self.as_slice()) }
pub(crate) fn as_mut_native(&mut self) -> &mut re2_c::StringView { &mut self.inner }
}
impl<'a> From<&'a [u8]> for StringView<'a> {
fn from(x: &'a [u8]) -> Self { Self::from_slice(x) }
}
impl<'a, const N: usize> From<&'a [u8; N]> for StringView<'a> {
fn from(x: &'a [u8; N]) -> Self { Self::from_slice(x.as_ref()) }
}
impl<'a> From<&'a str> for StringView<'a> {
fn from(x: &'a str) -> Self { Self::from_str(x) }
}
impl<'a> Default for StringView<'a> {
fn default() -> Self { Self::empty() }
}
impl<'a> fmt::Debug for StringView<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = self.as_slice();
match str::from_utf8(s) {
Ok(s) => write!(f, "{:?}", s),
Err(_) => write!(f, "{:?}", s),
}
}
}
impl<'a> fmt::Display for StringView<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = self.as_slice();
match str::from_utf8(s) {
Ok(s) => write!(f, "{}", s),
Err(_) => write!(f, "{:?}", s),
}
}
}
impl<'a> cmp::PartialEq for StringView<'a> {
fn eq(&self, other: &Self) -> bool { self.as_slice().eq(other.as_slice()) }
}
impl<'a> cmp::Eq for StringView<'a> {}
impl<'a> cmp::PartialOrd for StringView<'a> {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }
}
impl<'a> cmp::Ord for StringView<'a> {
fn cmp(&self, other: &Self) -> cmp::Ordering { self.as_slice().cmp(other.as_slice()) }
}
impl<'a> hash::Hash for StringView<'a> {
fn hash<H>(&self, state: &mut H)
where H: hash::Hasher {
self.as_slice().hash(state);
}
}
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct StringMut<'a> {
inner: re2_c::StringMut,
_ph: PhantomData<&'a mut u8>,
}
impl<'a> StringMut<'a> {
pub fn empty() -> Self {
let inner = re2_c::StringMut {
data_: ptr::null_mut(),
len_: 0,
};
Self::from_native(inner)
}
pub(crate) fn from_native(inner: re2_c::StringMut) -> Self {
Self {
inner,
_ph: PhantomData,
}
}
pub fn from_mut_slice(b: &'a mut [u8]) -> Self {
let inner = re2_c::StringMut {
data_: b.as_mut_ptr() as *mut c_char,
len_: b.len(),
};
Self::from_native(inner)
}
pub fn from_mut_str(s: &'a mut str) -> Self { Self::from_mut_slice(unsafe { s.as_bytes_mut() }) }
const unsafe fn mut_data_pointer(&self) -> *mut u8 { mem::transmute(self.inner.data_) }
pub const fn is_empty(&self) -> bool { self.len() == 0 }
pub const fn len(&self) -> usize { self.inner.len_ }
pub fn as_mut_slice(&self) -> &'a mut [u8] {
if self.is_empty() {
&mut []
} else {
unsafe { slice::from_raw_parts_mut(self.mut_data_pointer(), self.len()) }
}
}
pub unsafe fn as_mut_str(&self) -> &'a mut str {
str::from_utf8_unchecked_mut(self.as_mut_slice())
}
}
impl<'a> From<&'a mut [u8]> for StringMut<'a> {
fn from(x: &'a mut [u8]) -> Self { Self::from_mut_slice(x) }
}
impl<'a, const N: usize> From<&'a mut [u8; N]> for StringMut<'a> {
fn from(x: &'a mut [u8; N]) -> Self { Self::from_mut_slice(x.as_mut()) }
}
impl<'a> From<&'a mut str> for StringMut<'a> {
fn from(x: &'a mut str) -> Self { Self::from_mut_str(x) }
}
impl<'a> Default for StringMut<'a> {
fn default() -> Self { Self::empty() }
}
impl<'a> fmt::Debug for StringMut<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = self.as_mut_slice();
match str::from_utf8(s) {
Ok(s) => write!(f, "{:?}", s),
Err(_) => write!(f, "{:?}", s),
}
}
}
impl<'a> fmt::Display for StringMut<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = self.as_mut_slice();
match str::from_utf8(s) {
Ok(s) => write!(f, "{}", s),
Err(_) => write!(f, "{:?}", s),
}
}
}
impl<'a> cmp::PartialEq for StringMut<'a> {
fn eq(&self, other: &Self) -> bool { self.as_mut_slice().eq(&other.as_mut_slice()) }
}
impl<'a> cmp::Eq for StringMut<'a> {}
impl<'a> cmp::PartialOrd for StringMut<'a> {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }
}
impl<'a> cmp::Ord for StringMut<'a> {
fn cmp(&self, other: &Self) -> cmp::Ordering { self.as_mut_slice().cmp(&other.as_mut_slice()) }
}
impl<'a> hash::Hash for StringMut<'a> {
fn hash<H>(&self, state: &mut H)
where H: hash::Hasher {
self.as_mut_slice().hash(state);
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct StringWrapper(re2_c::StringWrapper);
impl StringWrapper {
pub const fn blank() -> Self {
Self(re2_c::StringWrapper {
inner_: ptr::null_mut(),
})
}
pub fn from_view(s: StringView) -> Self {
Self(unsafe { re2_c::StringWrapper::new(s.into_native()) })
}
pub(crate) fn as_mut_native(&mut self) -> &mut re2_c::StringWrapper { &mut self.0 }
pub fn as_view(&self) -> StringView { unsafe { StringView::from_native(self.0.as_view()) } }
pub fn as_mut_view(&mut self) -> StringMut<'_> {
unsafe { StringMut::from_native(self.0.as_mut_view()) }
}
pub fn resize(&mut self, len: usize) {
unsafe {
self.0.resize(len);
}
}
pub fn clear(&mut self) {
unsafe {
self.0.clear();
}
}
}
impl ops::Drop for StringWrapper {
fn drop(&mut self) { self.clear(); }
}