use lib::convert::AsRef;
use lib::{mem, ptr, slice};
#[inline]
pub fn distance<T>(first: *const T, last: *const T)
-> usize
{
debug_assert!(last >= first, "range must be positive.");
let f = first as usize;
let l = last as usize;
l - f
}
#[inline]
pub fn equal_to_slice(l: &[u8], r: &[u8])
-> bool
{
l == r
}
#[inline]
pub fn case_insensitive_equal(l: u8, r: u8)
-> bool
{
l.to_ascii_lowercase() == r.to_ascii_lowercase()
}
#[inline]
pub fn case_insensitive_equal_to_slice(l: &[u8], r: &[u8])
-> bool
{
let liter = l.iter().map(|li| li.to_ascii_lowercase());
let riter = r.iter().map(|ri| ri.to_ascii_lowercase());
l.len() == r.len() && liter.eq(riter)
}
#[inline]
pub fn case_insensitive_starts_with_slice(l: &[u8], r: &[u8])
-> bool
{
let lget = move || unsafe {l.get_unchecked(..r.len())};
l.len() >= r.len() && case_insensitive_equal_to_slice(lget(), r)
}
#[inline]
pub fn ends_with_slice(l: &[u8], r: &[u8])
-> bool
{
let rget = move || unsafe {l.get_unchecked(l.len()-r.len()..)};
l.len() >= r.len() && equal_to_slice(rget(), r)
}
#[inline]
pub fn ltrim_char_slice<'a>(slc: &'a [u8], c: u8)
-> (&'a [u8], usize)
{
let count = slc.iter().take_while(|&&si| si == c).count();
debug_assert!(count <= slc.len());
let slc = unsafe {slc.get_unchecked(count..)};
(slc, count)
}
#[cfg(any(feature = "correct", feature = "radix"))]
#[inline]
pub fn rtrim_char_slice<'a>(slc: &'a [u8], c: u8)
-> (&'a [u8], usize)
{
let count = slc.iter().rev().take_while(|&&si| si == c).count();
let index = slc.len() - count;
debug_assert!(count <= slc.len());
debug_assert!(index <= slc.len());
let slc = unsafe {slc.get_unchecked(..index)};
(slc, count)
}
#[inline]
pub fn copy_to_dst<'a, Bytes: AsRef<[u8]>>(dst: &'a mut [u8], src: Bytes)
-> usize
{
let src = src.as_ref();
let dst = &mut index_mut!(dst[..src.len()]);
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), dst.len());
}
src.len()
}
#[cfg(not(any(feature = "grisu3", feature = "ryu")))]
#[inline]
pub fn write_bytes(dst: &mut [u8], byte: u8)
{
unsafe {
ptr::write_bytes(dst.as_mut_ptr(), byte, dst.len());
}
}
#[inline]
pub fn explicit_uninitialized<T>() -> T {
unsafe {
#[cfg(debug_assertions)] {
mem::zeroed()
}
#[cfg(not(debug_assertions))] {
mem::uninitialized()
}
}
}
#[cfg(all(feature = "correct", feature = "radix"))]
#[inline]
pub fn slice_from_range<'a, T>(first: *const T, last: *const T)
-> &'a [T]
{
slice_from_span(first, distance(first, last))
}
#[cfg(feature = "correct")]
#[inline]
pub fn slice_from_span<'a, T>(first: *const T, length: usize)
-> &'a [T]
{
unsafe {
slice::from_raw_parts(first, length)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn distance_test() {
unsafe {
let x: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let first: *const u8 = x.as_ptr();
let last = first.add(x.len());
assert_eq!(distance(first, last), 10);
}
}
#[test]
fn equal_to_test() {
let x = "Hello";
let y = "Hello";
let z = "hello";
assert!(equal_to_slice(x.as_bytes(), y.as_bytes()));
assert!(!equal_to_slice(x.as_bytes(), z.as_bytes()));
assert!(!equal_to_slice(y.as_bytes(), z.as_bytes()));
}
#[test]
fn case_insensitive_equal_to_test() {
let w = "Hello";
let x = "Hello";
let y = "hello";
let z = "Strongbad";
assert!(case_insensitive_equal_to_slice(w.as_bytes(), x.as_bytes()));
assert!(case_insensitive_equal_to_slice(w.as_bytes(), y.as_bytes()));
assert!(case_insensitive_equal_to_slice(x.as_bytes(), y.as_bytes()));
assert!(!case_insensitive_equal_to_slice(w.as_bytes(), z.as_bytes()));
assert!(!case_insensitive_equal_to_slice(x.as_bytes(), z.as_bytes()));
assert!(!case_insensitive_equal_to_slice(y.as_bytes(), z.as_bytes()));
}
#[test]
fn case_insensitive_starts_with_test() {
let w = "Hello";
let x = "H";
let y = "h";
let z = "a";
assert!(case_insensitive_starts_with_slice(w.as_bytes(), x.as_bytes()));
assert!(case_insensitive_starts_with_slice(w.as_bytes(), y.as_bytes()));
assert!(case_insensitive_starts_with_slice(x.as_bytes(), y.as_bytes()));
assert!(!case_insensitive_starts_with_slice(w.as_bytes(), z.as_bytes()));
assert!(!case_insensitive_starts_with_slice(x.as_bytes(), z.as_bytes()));
assert!(!case_insensitive_starts_with_slice(y.as_bytes(), z.as_bytes()));
assert!(!case_insensitive_starts_with_slice(x.as_bytes(), w.as_bytes()));
assert!(!case_insensitive_starts_with_slice(y.as_bytes(), w.as_bytes()));
assert!(!case_insensitive_starts_with_slice(z.as_bytes(), w.as_bytes()));
}
#[test]
fn ends_with_test() {
let w = "Hello";
let x = "lO";
let y = "lo";
let z = "o";
assert!(!ends_with_slice(w.as_bytes(), x.as_bytes()));
assert!(ends_with_slice(w.as_bytes(), y.as_bytes()));
assert!(ends_with_slice(w.as_bytes(), z.as_bytes()));
assert!(!ends_with_slice(x.as_bytes(), y.as_bytes()));
assert!(!ends_with_slice(x.as_bytes(), z.as_bytes()));
assert!(ends_with_slice(y.as_bytes(), z.as_bytes()));
assert!(!ends_with_slice(z.as_bytes(), y.as_bytes()));
assert!(!ends_with_slice(z.as_bytes(), x.as_bytes()));
assert!(!ends_with_slice(z.as_bytes(), w.as_bytes()));
assert!(!ends_with_slice(y.as_bytes(), x.as_bytes()));
assert!(!ends_with_slice(y.as_bytes(), w.as_bytes()));
assert!(!ends_with_slice(x.as_bytes(), w.as_bytes()));
}
#[test]
fn ltrim_char_test() {
let w = "0001";
let x = "1010";
let y = "1.00";
let z = "1e05";
assert_eq!(ltrim_char_slice(w.as_bytes(), b'0').1, 3);
assert_eq!(ltrim_char_slice(x.as_bytes(), b'0').1, 0);
assert_eq!(ltrim_char_slice(x.as_bytes(), b'1').1, 1);
assert_eq!(ltrim_char_slice(y.as_bytes(), b'0').1, 0);
assert_eq!(ltrim_char_slice(y.as_bytes(), b'1').1, 1);
assert_eq!(ltrim_char_slice(z.as_bytes(), b'0').1, 0);
assert_eq!(ltrim_char_slice(z.as_bytes(), b'1').1, 1);
}
#[cfg(any(feature = "correct", feature = "radix"))]
#[test]
fn rtrim_char_test() {
let w = "0001";
let x = "1010";
let y = "1.00";
let z = "1e05";
assert_eq!(rtrim_char_slice(w.as_bytes(), b'0').1, 0);
assert_eq!(rtrim_char_slice(x.as_bytes(), b'0').1, 1);
assert_eq!(rtrim_char_slice(x.as_bytes(), b'1').1, 0);
assert_eq!(rtrim_char_slice(y.as_bytes(), b'0').1, 2);
assert_eq!(rtrim_char_slice(y.as_bytes(), b'1').1, 0);
assert_eq!(rtrim_char_slice(z.as_bytes(), b'0').1, 0);
assert_eq!(rtrim_char_slice(z.as_bytes(), b'5').1, 1);
}
}