pub trait EncodedChars {
fn start_ptr(&self) -> *const onig_sys::OnigUChar;
fn limit_ptr(&self) -> *const onig_sys::OnigUChar;
fn encoding(&self) -> onig_sys::OnigEncoding {
unsafe { &mut onig_sys::OnigEncodingUTF8 }
}
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> EncodedChars for T
where
T: AsRef<str>,
{
fn start_ptr(&self) -> *const onig_sys::OnigUChar {
self.as_ref().as_bytes().as_ptr()
}
fn limit_ptr(&self) -> *const onig_sys::OnigUChar {
let bytes = self.as_ref().as_bytes();
bytes[bytes.len()..].as_ptr()
}
fn len(&self) -> usize {
self.as_ref().len()
}
}
pub struct EncodedBytes<'a> {
bytes: &'a [u8],
enc: onig_sys::OnigEncoding,
}
impl<'a> EncodedBytes<'a> {
pub fn from_parts(bytes: &'a [u8], enc: onig_sys::OnigEncoding) -> EncodedBytes<'a> {
EncodedBytes { bytes, enc }
}
pub fn ascii(bytes: &'a [u8]) -> EncodedBytes<'a> {
EncodedBytes {
bytes,
enc: unsafe { &mut onig_sys::OnigEncodingASCII },
}
}
}
impl<'a> EncodedChars for EncodedBytes<'a> {
fn start_ptr(&self) -> *const onig_sys::OnigUChar {
self.bytes.as_ptr()
}
fn limit_ptr(&self) -> *const onig_sys::OnigUChar {
self.bytes[self.bytes.len()..].as_ptr()
}
fn encoding(&self) -> onig_sys::OnigEncoding {
self.enc
}
fn len(&self) -> usize {
self.bytes.len()
}
}
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
pub fn rust_string_encoding_is_utf8() {
let foo = "foo";
assert_eq!(
unsafe { &mut onig_sys::OnigEncodingUTF8 } as onig_sys::OnigEncoding,
foo.encoding()
);
let bar = String::from(".*");
assert_eq!(
unsafe { &mut onig_sys::OnigEncodingUTF8 } as onig_sys::OnigEncoding,
bar.encoding()
);
}
#[test]
pub fn rust_bytes_encoding_is_ascii() {
let fizz = b"fizz";
let buff = EncodedBytes::ascii(fizz);
assert_eq!(
unsafe { &mut onig_sys::OnigEncodingASCII } as onig_sys::OnigEncoding,
buff.encoding()
);
}
#[test]
pub fn rust_string_ptr_offsets_are_valid() {
let test_string = "hello world";
assert_eq!(
test_string.limit_ptr() as usize - test_string.start_ptr() as usize,
test_string.len()
);
}
#[test]
pub fn rust_bytes_ptr_offsets_are_valid() {
let fozz = b"foo.*bar";
let buff = EncodedBytes::ascii(fozz);
assert_eq!(
buff.limit_ptr() as usize - buff.start_ptr() as usize,
fozz.len()
);
}
#[test]
pub fn byte_buffer_create() {
let buff = b"hello world";
let enc_buffer =
EncodedBytes::from_parts(buff, unsafe { &mut onig_sys::OnigEncodingASCII });
assert_eq!(
unsafe { &mut onig_sys::OnigEncodingASCII } as onig_sys::OnigEncoding,
enc_buffer.encoding()
);
assert_eq!(
enc_buffer.limit_ptr() as usize - enc_buffer.start_ptr() as usize,
buff.len()
);
}
}