Upgrade rustfmt.

This commit is contained in:
Henri Sivonen
2018-05-07 14:13:26 +03:00
parent 665664095f
commit bae16c05f4
19 changed files with 1246 additions and 884 deletions
+398 -361
View File
@@ -21,8 +21,16 @@
// on Raspberry Pi 3 measurements. The UTF-16 and UTF-8 ALU cases take
// different approaches based on benchmarking on Raspberry Pi 3.
#[cfg(all(feature = "simd-accel",
any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))]
#[cfg(
all(
feature = "simd-accel",
any(
target_feature = "sse2",
all(target_endian = "little", target_arch = "aarch64"),
all(target_endian = "little", target_feature = "neon")
)
)
)]
use simd_funcs::*;
// `as` truncates, so works on 32-bit, too.
@@ -35,22 +43,25 @@ pub const BASIC_LATIN_MASK: usize = 0xFF80FF80_FF80FF80u64 as usize;
#[allow(unused_macros)]
macro_rules! ascii_naive {
($name:ident,
$src_unit:ty,
$dst_unit:ty) => (
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) -> Option<($src_unit, usize)> {
// Yes, manually omitting the bound check here matters
// a lot for perf.
for i in 0..len {
let code_unit = *(src.offset(i as isize));
if code_unit > 127 {
return Some((code_unit, i));
($name:ident, $src_unit:ty, $dst_unit:ty) => {
#[inline(always)]
pub unsafe fn $name(
src: *const $src_unit,
dst: *mut $dst_unit,
len: usize,
) -> Option<($src_unit, usize)> {
// Yes, manually omitting the bound check here matters
// a lot for perf.
for i in 0..len {
let code_unit = *(src.offset(i as isize));
if code_unit > 127 {
return Some((code_unit, i));
}
*(dst.offset(i as isize)) = code_unit as $dst_unit;
}
*(dst.offset(i as isize)) = code_unit as $dst_unit;
return None;
}
return None;
});
};
}
#[allow(unused_macros)]
@@ -223,364 +234,397 @@ macro_rules! basic_latin_alu {
#[allow(unused_macros)]
macro_rules! latin1_alu {
($name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_fn:ident) => (
#[cfg_attr(feature = "cargo-clippy", allow(never_loop))]
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
// This loop is only broken out of as a `goto` forward
loop {
let mut until_alignment = {
if ::std::mem::size_of::<$src_unit>() < ::std::mem::size_of::<$dst_unit>() {
// unpack
let src_until_alignment = (ALU_ALIGNMENT - ((src as usize) & ALU_ALIGNMENT_MASK)) & ALU_ALIGNMENT_MASK;
if (dst.offset(src_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK != 0 {
break;
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_fn:ident) => {
#[cfg_attr(feature = "cargo-clippy", allow(never_loop))]
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
// This loop is only broken out of as a `goto` forward
loop {
let mut until_alignment = {
if ::std::mem::size_of::<$src_unit>() < ::std::mem::size_of::<$dst_unit>() {
// unpack
let src_until_alignment = (ALU_ALIGNMENT
- ((src as usize) & ALU_ALIGNMENT_MASK))
& ALU_ALIGNMENT_MASK;
if (dst.offset(src_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK
!= 0
{
break;
}
src_until_alignment
} else {
// pack
let dst_until_alignment = (ALU_ALIGNMENT
- ((dst as usize) & ALU_ALIGNMENT_MASK))
& ALU_ALIGNMENT_MASK;
if (src.offset(dst_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK
!= 0
{
break;
}
dst_until_alignment
}
};
if until_alignment + ALU_STRIDE_SIZE <= len {
while until_alignment != 0 {
let code_unit = *(src.offset(offset as isize));
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
until_alignment -= 1;
}
let len_minus_stride = len - ALU_STRIDE_SIZE;
loop {
$stride_fn(
src.offset(offset as isize) as *const usize,
dst.offset(offset as isize) as *mut usize,
);
offset += ALU_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
break;
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
}
};
}
#[allow(unused_macros)]
macro_rules! ascii_simd_check_align {
(
$name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_both_aligned:ident,
$stride_src_aligned:ident,
$stride_dst_aligned:ident,
$stride_neither_aligned:ident
) => {
#[inline(always)]
pub unsafe fn $name(
src: *const $src_unit,
dst: *mut $dst_unit,
len: usize,
) -> Option<($src_unit, usize)> {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
// XXX Should we first process one stride unconditinoally as unaligned to
// avoid the cost of the branchiness below if the first stride fails anyway?
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
// on Haswell, it would make sense to just use unaligned and not bother
// checking. Need to benchmark older architectures before deciding.
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
if dst_masked == 0 {
loop {
if !$stride_both_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
if !$stride_src_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
src_until_alignment
} else {
// pack
let dst_until_alignment = (ALU_ALIGNMENT - ((dst as usize) & ALU_ALIGNMENT_MASK)) & ALU_ALIGNMENT_MASK;
if (src.offset(dst_until_alignment as isize) as usize) & ALU_ALIGNMENT_MASK != 0 {
if dst_masked == 0 {
loop {
if !$stride_dst_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
if !$stride_neither_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
if code_unit > 127 {
return Some((code_unit, offset));
}
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
None
}
};
}
#[allow(unused_macros)]
macro_rules! latin1_simd_check_align {
(
$name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_both_aligned:ident,
$stride_src_aligned:ident,
$stride_dst_aligned:ident,
$stride_neither_aligned:ident
) => {
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
// XXX Should we first process one stride unconditinoally as unaligned to
// avoid the cost of the branchiness below if the first stride fails anyway?
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
// on Haswell, it would make sense to just use unaligned and not bother
// checking. Need to benchmark older architectures before deciding.
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
if dst_masked == 0 {
loop {
$stride_both_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
$stride_src_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
} else {
if dst_masked == 0 {
loop {
$stride_dst_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
$stride_neither_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
// On x86_64, this loop autovectorizes but in the pack
// case there are instructions whose purpose is to make sure
// each u16 in the vector is truncated before packing. However,
// since we don't care about saturating behavior of SSE2 packing
// when the input isn't Latin1, those instructions are useless.
// Unfortunately, using the `assume` intrinsic to lie to the
// optimizer doesn't make LLVM omit the trunctation that we
// don't need. Possibly this loop could be manually optimized
// to do the sort of thing that LLVM does but without the
// ANDing the read vectors of u16 with a constant that discards
// the high half of each u16. As far as I can tell, the
// optimization assumes that doing a SIMD read past the end of
// the array is OK.
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
}
};
}
#[allow(unused_macros)]
macro_rules! ascii_simd_unalign {
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_neither_aligned:ident) => {
#[inline(always)]
pub unsafe fn $name(
src: *const $src_unit,
dst: *mut $dst_unit,
len: usize,
) -> Option<($src_unit, usize)> {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
if !$stride_neither_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
) {
break;
}
dst_until_alignment
}
};
if until_alignment + ALU_STRIDE_SIZE <= len {
while until_alignment != 0 {
let code_unit = *(src.offset(offset as isize));
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
until_alignment -= 1;
}
let len_minus_stride = len - ALU_STRIDE_SIZE;
loop {
$stride_fn(src.offset(offset as isize) as *const usize,
dst.offset(offset as isize) as *mut usize);
offset += ALU_STRIDE_SIZE;
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
break;
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
});
}
#[allow(unused_macros)]
macro_rules! ascii_simd_check_align {
($name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_both_aligned:ident,
$stride_src_aligned:ident,
$stride_dst_aligned:ident,
$stride_neither_aligned:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) -> Option<($src_unit, usize)> {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
// XXX Should we first process one stride unconditinoally as unaligned to
// avoid the cost of the branchiness below if the first stride fails anyway?
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
// on Haswell, it would make sense to just use unaligned and not bother
// checking. Need to benchmark older architectures before deciding.
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
if dst_masked == 0 {
loop {
if !$stride_both_aligned(src.offset(offset as isize),
dst.offset(offset as isize)) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
if !$stride_src_aligned(src.offset(offset as isize),
dst.offset(offset as isize)) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
} else {
if dst_masked == 0 {
loop {
if !$stride_dst_aligned(src.offset(offset as isize),
dst.offset(offset as isize)) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
if !$stride_neither_aligned(src.offset(offset as isize),
dst.offset(offset as isize)) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
if code_unit > 127 {
return Some((code_unit, offset));
}
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
None
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
if code_unit > 127 {
return Some((code_unit, offset));
}
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
None
});
}
#[allow(unused_macros)]
macro_rules! latin1_simd_check_align {
($name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_both_aligned:ident,
$stride_src_aligned:ident,
$stride_dst_aligned:ident,
$stride_neither_aligned:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
// XXX Should we first process one stride unconditinoally as unaligned to
// avoid the cost of the branchiness below if the first stride fails anyway?
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
// on Haswell, it would make sense to just use unaligned and not bother
// checking. Need to benchmark older architectures before deciding.
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
if dst_masked == 0 {
loop {
$stride_both_aligned(src.offset(offset as isize),
dst.offset(offset as isize));
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
$stride_src_aligned(src.offset(offset as isize),
dst.offset(offset as isize));
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
} else {
if dst_masked == 0 {
loop {
$stride_dst_aligned(src.offset(offset as isize),
dst.offset(offset as isize));
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
} else {
loop {
$stride_neither_aligned(src.offset(offset as isize),
dst.offset(offset as isize));
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
// On x86_64, this loop autovectorizes but in the pack
// case there are instructions whose purpose is to make sure
// each u16 in the vector is truncated before packing. However,
// since we don't care about saturating behavior of SSE2 packing
// when the input isn't Latin1, those instructions are useless.
// Unfortunately, using the `assume` intrinsic to lie to the
// optimizer doesn't make LLVM omit the trunctation that we
// don't need. Possibly this loop could be manually optimized
// to do the sort of thing that LLVM does but without the
// ANDing the read vectors of u16 with a constant that discards
// the high half of each u16. As far as I can tell, the
// optimization assumes that doing a SIMD read past the end of
// the array is OK.
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
});
}
#[allow(unused_macros)]
macro_rules! ascii_simd_unalign {
($name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_neither_aligned:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) -> Option<($src_unit, usize)> {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
if !$stride_neither_aligned(src.offset(offset as isize),
dst.offset(offset as isize)) {
break;
}
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
if code_unit > 127 {
return Some((code_unit, offset));
}
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
None
});
};
}
#[allow(unused_macros)]
macro_rules! latin1_simd_unalign {
($name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_neither_aligned:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
$stride_neither_aligned(src.offset(offset as isize),
dst.offset(offset as isize));
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
($name:ident, $src_unit:ty, $dst_unit:ty, $stride_neither_aligned:ident) => {
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
loop {
$stride_neither_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride {
break;
}
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
});
};
}
#[allow(unused_macros)]
macro_rules! ascii_to_ascii_simd_stride {
($name:ident,
$load:ident,
$store:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u8) -> bool {
let simd = $load(src);
if !simd_is_ascii(simd) {
return false;
($name:ident, $load:ident, $store:ident) => {
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u8) -> bool {
let simd = $load(src);
if !simd_is_ascii(simd) {
return false;
}
$store(dst, simd);
true
}
$store(dst, simd);
true
});
};
}
#[allow(unused_macros)]
macro_rules! ascii_to_basic_latin_simd_stride {
($name:ident,
$load:ident,
$store:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u16) -> bool {
let simd = $load(src);
if !simd_is_ascii(simd) {
return false;
($name:ident, $load:ident, $store:ident) => {
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u16) -> bool {
let simd = $load(src);
if !simd_is_ascii(simd) {
return false;
}
let (first, second) = simd_unpack(simd);
$store(dst, first);
$store(dst.offset(8), second);
true
}
let (first, second) = simd_unpack(simd);
$store(dst, first);
$store(dst.offset(8), second);
true
});
};
}
#[allow(unused_macros)]
macro_rules! unpack_simd_stride {
($name:ident,
$load:ident,
$store:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u16) {
let simd = $load(src);
let (first, second) = simd_unpack(simd);
$store(dst, first);
$store(dst.offset(8), second);
});
($name:ident, $load:ident, $store:ident) => {
#[inline(always)]
pub unsafe fn $name(src: *const u8, dst: *mut u16) {
let simd = $load(src);
let (first, second) = simd_unpack(simd);
$store(dst, first);
$store(dst.offset(8), second);
}
};
}
#[allow(unused_macros)]
macro_rules! basic_latin_to_ascii_simd_stride {
($name:ident,
$load:ident,
$store:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const u16, dst: *mut u8) -> bool {
let first = $load(src);
let second = $load(src.offset(8));
if simd_is_basic_latin(first | second) {
$store(dst, simd_pack(first, second));
true
} else {
false
($name:ident, $load:ident, $store:ident) => {
#[inline(always)]
pub unsafe fn $name(src: *const u16, dst: *mut u8) -> bool {
let first = $load(src);
let second = $load(src.offset(8));
if simd_is_basic_latin(first | second) {
$store(dst, simd_pack(first, second));
true
} else {
false
}
}
});
};
}
#[allow(unused_macros)]
macro_rules! pack_simd_stride {
($name:ident,
$load:ident,
$store:ident) => (
#[inline(always)]
pub unsafe fn $name(src: *const u16, dst: *mut u8) {
let first = $load(src);
let second = $load(src.offset(8));
$store(dst, simd_pack(first, second));
});
($name:ident, $load:ident, $store:ident) => {
#[inline(always)]
pub unsafe fn $name(src: *const u16, dst: *mut u8) {
let first = $load(src);
let second = $load(src.offset(8));
$store(dst, simd_pack(first, second));
}
};
}
cfg_if! {
@@ -1091,7 +1135,6 @@ cfg_if! {
}
}
pub fn ascii_valid_up_to(bytes: &[u8]) -> usize {
match validate_ascii(bytes) {
None => bytes.len(),
@@ -1117,38 +1160,32 @@ mod tests {
use super::*;
macro_rules! test_ascii {
($test_name:ident,
$fn_tested:ident,
$src_unit:ty,
$dst_unit:ty) => (
#[test]
fn $test_name() {
let mut src: Vec<$src_unit> = Vec::with_capacity(32);
let mut dst: Vec<$dst_unit> = Vec::with_capacity(32);
for i in 0..32 {
src.clear();
dst.clear();
dst.resize(32, 0);
for j in 0..32 {
let c = if i == j {
0xAA
} else {
j + 0x40
};
src.push(c as $src_unit);
}
match unsafe { $fn_tested(src.as_ptr(), dst.as_mut_ptr(), 32) } {
None => unreachable!("Should always find non-ASCII"),
Some((non_ascii, num_ascii)) => {
assert_eq!(non_ascii, 0xAA);
assert_eq!(num_ascii, i);
for j in 0..i {
assert_eq!(dst[j], (j + 0x40) as $dst_unit);
($test_name:ident, $fn_tested:ident, $src_unit:ty, $dst_unit:ty) => {
#[test]
fn $test_name() {
let mut src: Vec<$src_unit> = Vec::with_capacity(32);
let mut dst: Vec<$dst_unit> = Vec::with_capacity(32);
for i in 0..32 {
src.clear();
dst.clear();
dst.resize(32, 0);
for j in 0..32 {
let c = if i == j { 0xAA } else { j + 0x40 };
src.push(c as $src_unit);
}
match unsafe { $fn_tested(src.as_ptr(), dst.as_mut_ptr(), 32) } {
None => unreachable!("Should always find non-ASCII"),
Some((non_ascii, num_ascii)) => {
assert_eq!(non_ascii, 0xAA);
assert_eq!(num_ascii, i);
for j in 0..i {
assert_eq!(dst[j], (j + 0x40) as $dst_unit);
}
}
}
}
}
});
};
}
test_ascii!(test_ascii_to_ascii, ascii_to_ascii, u8, u8);
+3 -3
View File
@@ -7,10 +7,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use handles::*;
use data::*;
use variant::*;
use super::*;
use data::*;
use handles::*;
use variant::*;
// Rust 1.14.0 requires the following despite the asterisk above.
use super::in_inclusive_range32;
+3 -3
View File
@@ -7,10 +7,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use handles::*;
use data::*;
use variant::*;
use super::*;
use data::*;
use handles::*;
use variant::*;
// Rust 1.14.0 requires the following despite the asterisk above.
use super::in_inclusive_range16;
+4 -4
View File
@@ -7,13 +7,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use handles::*;
use data::*;
use variant::*;
use super::*;
use data::*;
use handles::*;
use variant::*;
// Rust 1.14.0 requires the following despite the asterisk above.
use super::in_range16;
use super::in_inclusive_range16;
use super::in_range16;
pub struct EucKrDecoder {
lead: Option<u8>,
+3 -3
View File
@@ -7,10 +7,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use handles::*;
use data::*;
use variant::*;
use super::*;
use data::*;
use handles::*;
use variant::*;
// Rust 1.14.0 requires the following despite the asterisk above.
use super::in_inclusive_range16;
use super::in_range16;
+1 -1
View File
@@ -19,8 +19,8 @@
use super::DecoderResult;
use super::EncoderResult;
use ascii::*;
use utf_8::utf8_valid_up_to;
use utf_8::convert_utf8_to_utf16_up_to_invalid;
use utf_8::utf8_valid_up_to;
pub enum Space<T> {
Available(T),
+3 -3
View File
@@ -7,10 +7,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use handles::*;
use data::*;
use variant::*;
use super::*;
use data::*;
use handles::*;
use variant::*;
// Rust 1.14.0 requires the following despite the asterisk above.
use super::in_inclusive_range16;
+41 -20
View File
@@ -636,14 +636,23 @@
//! See the section [_UTF-16LE, UTF-16BE and Unicode Encoding Schemes_](#utf-16le-utf-16be-and-unicode-encoding-schemes)
//! for discussion about the UTF-16 family.
#![cfg_attr(feature = "simd-accel",
feature(cfg_target_feature, platform_intrinsics, core_intrinsics))]
#![cfg_attr(
feature = "simd-accel", feature(cfg_target_feature, platform_intrinsics, core_intrinsics)
)]
#[macro_use]
extern crate cfg_if;
#[cfg(all(feature = "simd-accel",
any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))]
#[cfg(
all(
feature = "simd-accel",
any(
target_feature = "sse2",
all(target_endian = "little", target_arch = "aarch64"),
all(target_endian = "little", target_feature = "neon")
)
)
)]
extern crate simd;
#[cfg(feature = "serde")]
@@ -660,51 +669,63 @@ extern crate serde_json;
#[macro_use]
mod macros;
#[cfg(all(feature = "simd-accel",
any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))]
#[cfg(
all(
feature = "simd-accel",
any(
target_feature = "sse2",
all(target_endian = "little", target_arch = "aarch64"),
all(target_endian = "little", target_feature = "neon")
)
)
)]
mod simd_funcs;
#[cfg(any(all(feature = "simd-accel", target_feature = "sse2"),
all(target_endian = "little", target_arch = "aarch64"),
all(target_endian = "little", target_arch = "arm")))]
#[cfg(
any(
all(feature = "simd-accel", target_feature = "sse2"),
all(target_endian = "little", target_arch = "aarch64"),
all(target_endian = "little", target_arch = "arm")
)
)]
mod utf_8_core;
#[cfg(test)]
mod testing;
mod single_byte;
mod utf_8;
mod gb18030;
mod big5;
mod euc_jp;
mod iso_2022_jp;
mod shift_jis;
mod euc_kr;
mod gb18030;
mod iso_2022_jp;
mod replacement;
mod x_user_defined;
mod shift_jis;
mod single_byte;
mod utf_16;
mod utf_8;
mod x_user_defined;
mod ascii;
mod handles;
mod data;
mod handles;
mod variant;
pub mod mem;
use variant::*;
use utf_8::utf8_valid_up_to;
use ascii::ascii_valid_up_to;
use ascii::iso_2022_jp_ascii_valid_up_to;
use utf_8::utf8_valid_up_to;
use variant::*;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::hash::Hash;
use std::hash::Hasher;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde")]
use serde::de::Visitor;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// This has to be the max length of an NCR instead of max
/// minus one, because we can't rely on getting the minus
+375 -327
View File
@@ -71,49 +71,55 @@ macro_rules! decoder_function {
}
macro_rules! decoder_functions {
($preamble:block,
$loop_preable:block,
$eof:block,
$body:block,
$slf:ident,
$src_consumed:ident,
$dest:ident,
$source:ident,
$b:ident,
$destination_handle:ident,
$unread_handle:ident,
$destination_check:ident) => (
decoder_function!($preamble,
$loop_preable,
$eof,
$body,
$slf,
$src_consumed,
$dest,
$source,
$b,
$destination_handle,
$unread_handle,
$destination_check,
decode_to_utf8_raw,
u8,
Utf8Destination);
decoder_function!($preamble,
$loop_preable,
$eof,
$body,
$slf,
$src_consumed,
$dest,
$source,
$b,
$destination_handle,
$unread_handle,
$destination_check,
decode_to_utf16_raw,
u16,
Utf16Destination);
);
(
$preamble:block,
$loop_preable:block,
$eof:block,
$body:block,
$slf:ident,
$src_consumed:ident,
$dest:ident,
$source:ident,
$b:ident,
$destination_handle:ident,
$unread_handle:ident,
$destination_check:ident
) => {
decoder_function!(
$preamble,
$loop_preable,
$eof,
$body,
$slf,
$src_consumed,
$dest,
$source,
$b,
$destination_handle,
$unread_handle,
$destination_check,
decode_to_utf8_raw,
u8,
Utf8Destination
);
decoder_function!(
$preamble,
$loop_preable,
$eof,
$body,
$slf,
$src_consumed,
$dest,
$source,
$b,
$destination_handle,
$unread_handle,
$destination_check,
decode_to_utf16_raw,
u16,
Utf16Destination
);
};
}
macro_rules! ascii_compatible_two_byte_decoder_function {
@@ -278,52 +284,58 @@ macro_rules! ascii_compatible_two_byte_decoder_function {
}
macro_rules! ascii_compatible_two_byte_decoder_functions {
($lead:block,
$trail:block,
$slf:ident,
$non_ascii:ident,
$byte:ident,
$lead_minus_offset:ident,
$unread_handle_trail:ident,
$source:ident,
$handle:ident,
$outermost:tt,
$copy_ascii:ident,
$destination_check:ident,
$ascii_punctuation:expr) => (
ascii_compatible_two_byte_decoder_function!($lead,
$trail,
$slf,
$non_ascii,
$byte,
$lead_minus_offset,
$unread_handle_trail,
$source,
$handle,
$outermost,
$copy_ascii,
$destination_check,
decode_to_utf8_raw,
u8,
Utf8Destination,
$ascii_punctuation);
ascii_compatible_two_byte_decoder_function!($lead,
$trail,
$slf,
$non_ascii,
$byte,
$lead_minus_offset,
$unread_handle_trail,
$source,
$handle,
$outermost,
$copy_ascii,
$destination_check,
decode_to_utf16_raw,
u16,
Utf16Destination,
$ascii_punctuation);
);
(
$lead:block,
$trail:block,
$slf:ident,
$non_ascii:ident,
$byte:ident,
$lead_minus_offset:ident,
$unread_handle_trail:ident,
$source:ident,
$handle:ident,
$outermost:tt,
$copy_ascii:ident,
$destination_check:ident,
$ascii_punctuation:expr
) => {
ascii_compatible_two_byte_decoder_function!(
$lead,
$trail,
$slf,
$non_ascii,
$byte,
$lead_minus_offset,
$unread_handle_trail,
$source,
$handle,
$outermost,
$copy_ascii,
$destination_check,
decode_to_utf8_raw,
u8,
Utf8Destination,
$ascii_punctuation
);
ascii_compatible_two_byte_decoder_function!(
$lead,
$trail,
$slf,
$non_ascii,
$byte,
$lead_minus_offset,
$unread_handle_trail,
$source,
$handle,
$outermost,
$copy_ascii,
$destination_check,
decode_to_utf16_raw,
u16,
Utf16Destination,
$ascii_punctuation
);
};
}
macro_rules! gb18030_decoder_function {
@@ -583,70 +595,76 @@ macro_rules! gb18030_decoder_function {
}
macro_rules! gb18030_decoder_functions {
($first_body:block,
$second_body:block,
$third_body:block,
$fourth_body:block,
$slf:ident,
$non_ascii:ident,
$first_minus_offset:ident,
$second:ident,
$second_minus_offset:ident,
$unread_handle_second:ident,
$third:ident,
$third_minus_offset:ident,
$unread_handle_third:ident,
$fourth:ident,
$fourth_minus_offset:ident,
$unread_handle_fourth:ident,
$source:ident,
$handle:ident,
$outermost:tt) => (
gb18030_decoder_function!($first_body,
$second_body,
$third_body,
$fourth_body,
$slf,
$non_ascii,
$first_minus_offset,
$second,
$second_minus_offset,
$unread_handle_second,
$third,
$third_minus_offset,
$unread_handle_third,
$fourth,
$fourth_minus_offset,
$unread_handle_fourth,
$source,
$handle,
$outermost,
decode_to_utf8_raw,
u8,
Utf8Destination);
gb18030_decoder_function!($first_body,
$second_body,
$third_body,
$fourth_body,
$slf,
$non_ascii,
$first_minus_offset,
$second,
$second_minus_offset,
$unread_handle_second,
$third,
$third_minus_offset,
$unread_handle_third,
$fourth,
$fourth_minus_offset,
$unread_handle_fourth,
$source,
$handle,
$outermost,
decode_to_utf16_raw,
u16,
Utf16Destination);
);
(
$first_body:block,
$second_body:block,
$third_body:block,
$fourth_body:block,
$slf:ident,
$non_ascii:ident,
$first_minus_offset:ident,
$second:ident,
$second_minus_offset:ident,
$unread_handle_second:ident,
$third:ident,
$third_minus_offset:ident,
$unread_handle_third:ident,
$fourth:ident,
$fourth_minus_offset:ident,
$unread_handle_fourth:ident,
$source:ident,
$handle:ident,
$outermost:tt
) => {
gb18030_decoder_function!(
$first_body,
$second_body,
$third_body,
$fourth_body,
$slf,
$non_ascii,
$first_minus_offset,
$second,
$second_minus_offset,
$unread_handle_second,
$third,
$third_minus_offset,
$unread_handle_third,
$fourth,
$fourth_minus_offset,
$unread_handle_fourth,
$source,
$handle,
$outermost,
decode_to_utf8_raw,
u8,
Utf8Destination
);
gb18030_decoder_function!(
$first_body,
$second_body,
$third_body,
$fourth_body,
$slf,
$non_ascii,
$first_minus_offset,
$second,
$second_minus_offset,
$unread_handle_second,
$third,
$third_minus_offset,
$unread_handle_third,
$fourth,
$fourth_minus_offset,
$unread_handle_fourth,
$source,
$handle,
$outermost,
decode_to_utf16_raw,
u16,
Utf16Destination
);
};
}
macro_rules! euc_jp_decoder_function {
@@ -880,55 +898,61 @@ macro_rules! euc_jp_decoder_function {
}
macro_rules! euc_jp_decoder_functions {
($jis0802_trail_body:block,
$jis0812_lead_body:block,
$jis0812_trail_body:block,
$half_width_katakana_body:block,
$slf:ident,
$non_ascii:ident,
$jis0208_lead_minus_offset:ident,
$byte:ident,
$unread_handle_trail:ident,
$jis0212_lead_minus_offset:ident,
$lead:ident,
$unread_handle_jis0212:ident,
$source:ident,
$handle:ident) => (
euc_jp_decoder_function!($jis0802_trail_body,
$jis0812_lead_body,
$jis0812_trail_body,
$half_width_katakana_body,
$slf,
$non_ascii,
$jis0208_lead_minus_offset,
$byte,
$unread_handle_trail,
$jis0212_lead_minus_offset,
$lead,
$unread_handle_jis0212,
$source,
$handle,
decode_to_utf8_raw,
u8,
Utf8Destination);
euc_jp_decoder_function!($jis0802_trail_body,
$jis0812_lead_body,
$jis0812_trail_body,
$half_width_katakana_body,
$slf,
$non_ascii,
$jis0208_lead_minus_offset,
$byte,
$unread_handle_trail,
$jis0212_lead_minus_offset,
$lead,
$unread_handle_jis0212,
$source,
$handle,
decode_to_utf16_raw,
u16,
Utf16Destination);
(
$jis0802_trail_body:block,
$jis0812_lead_body:block,
$jis0812_trail_body:block,
$half_width_katakana_body:block,
$slf:ident,
$non_ascii:ident,
$jis0208_lead_minus_offset:ident,
$byte:ident,
$unread_handle_trail:ident,
$jis0212_lead_minus_offset:ident,
$lead:ident,
$unread_handle_jis0212:ident,
$source:ident,
$handle:ident
) => {
euc_jp_decoder_function!(
$jis0802_trail_body,
$jis0812_lead_body,
$jis0812_trail_body,
$half_width_katakana_body,
$slf,
$non_ascii,
$jis0208_lead_minus_offset,
$byte,
$unread_handle_trail,
$jis0212_lead_minus_offset,
$lead,
$unread_handle_jis0212,
$source,
$handle,
decode_to_utf8_raw,
u8,
Utf8Destination
);
euc_jp_decoder_function!(
$jis0802_trail_body,
$jis0812_lead_body,
$jis0812_trail_body,
$half_width_katakana_body,
$slf,
$non_ascii,
$jis0208_lead_minus_offset,
$byte,
$unread_handle_trail,
$jis0212_lead_minus_offset,
$lead,
$unread_handle_jis0212,
$source,
$handle,
decode_to_utf16_raw,
u16,
Utf16Destination
);
};
}
macro_rules! encoder_function {
@@ -983,43 +1007,49 @@ macro_rules! encoder_function {
}
macro_rules! encoder_functions {
($eof:block,
$body:block,
$slf:ident,
$src_consumed:ident,
$source:ident,
$dest:ident,
$c:ident,
$destination_handle:ident,
$unread_handle:ident,
$destination_check:ident) => (
encoder_function!($eof,
$body,
$slf,
$src_consumed,
$source,
$dest,
$c,
$destination_handle,
$unread_handle,
$destination_check,
encode_from_utf8_raw,
str,
Utf8Source);
encoder_function!($eof,
$body,
$slf,
$src_consumed,
$source,
$dest,
$c,
$destination_handle,
$unread_handle,
$destination_check,
encode_from_utf16_raw,
[u16],
Utf16Source);
);
(
$eof:block,
$body:block,
$slf:ident,
$src_consumed:ident,
$source:ident,
$dest:ident,
$c:ident,
$destination_handle:ident,
$unread_handle:ident,
$destination_check:ident
) => {
encoder_function!(
$eof,
$body,
$slf,
$src_consumed,
$source,
$dest,
$c,
$destination_handle,
$unread_handle,
$destination_check,
encode_from_utf8_raw,
str,
Utf8Source
);
encoder_function!(
$eof,
$body,
$slf,
$src_consumed,
$source,
$dest,
$c,
$destination_handle,
$unread_handle,
$destination_check,
encode_from_utf16_raw,
[u16],
Utf16Source
);
};
}
macro_rules! ascii_compatible_encoder_function {
@@ -1133,101 +1163,119 @@ macro_rules! ascii_compatible_encoder_function {
}
macro_rules! ascii_compatible_encoder_functions {
($bmp_body:block,
$astral_body:block,
$bmp:ident,
$astral:ident,
$slf:ident,
$source:ident,
$handle:ident,
$copy_ascii:ident,
$destination_check:ident,
$ascii_punctuation:expr) => (
ascii_compatible_encoder_function!($bmp_body,
$astral_body,
$bmp,
$astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
encode_from_utf8_raw,
str,
Utf8Source,
$ascii_punctuation);
ascii_compatible_encoder_function!($bmp_body,
$astral_body,
$bmp,
$astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
encode_from_utf16_raw,
[u16],
Utf16Source,
$ascii_punctuation);
);
(
$bmp_body:block,
$astral_body:block,
$bmp:ident,
$astral:ident,
$slf:ident,
$source:ident,
$handle:ident,
$copy_ascii:ident,
$destination_check:ident,
$ascii_punctuation:expr
) => {
ascii_compatible_encoder_function!(
$bmp_body,
$astral_body,
$bmp,
$astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
encode_from_utf8_raw,
str,
Utf8Source,
$ascii_punctuation
);
ascii_compatible_encoder_function!(
$bmp_body,
$astral_body,
$bmp,
$astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
encode_from_utf16_raw,
[u16],
Utf16Source,
$ascii_punctuation
);
};
}
macro_rules! ascii_compatible_bmp_encoder_function {
($bmp_body:block,
$bmp:ident,
$slf:ident,
$source:ident,
$handle:ident,
$copy_ascii:ident,
$destination_check:ident,
$name:ident,
$input:ty,
$source_struct:ident,
$ascii_punctuation:expr) => (
ascii_compatible_encoder_function!($bmp_body,
{
return (EncoderResult::Unmappable(astral),
$source.consumed(),
$handle.written());
},
$bmp,
astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
$name,
$input,
$source_struct,
$ascii_punctuation);
);
(
$bmp_body:block,
$bmp:ident,
$slf:ident,
$source:ident,
$handle:ident,
$copy_ascii:ident,
$destination_check:ident,
$name:ident,
$input:ty,
$source_struct:ident,
$ascii_punctuation:expr
) => {
ascii_compatible_encoder_function!(
$bmp_body,
{
return (
EncoderResult::Unmappable(astral),
$source.consumed(),
$handle.written(),
);
},
$bmp,
astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
$name,
$input,
$source_struct,
$ascii_punctuation
);
};
}
macro_rules! ascii_compatible_bmp_encoder_functions {
($bmp_body:block,
$bmp:ident,
$slf:ident,
$source:ident,
$handle:ident,
$copy_ascii:ident,
$destination_check:ident,
$ascii_punctuation:expr) => (
ascii_compatible_encoder_functions!($bmp_body,
{
return (EncoderResult::Unmappable(astral),
$source.consumed(),
$handle.written());
},
$bmp,
astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
$ascii_punctuation);
);
(
$bmp_body:block,
$bmp:ident,
$slf:ident,
$source:ident,
$handle:ident,
$copy_ascii:ident,
$destination_check:ident,
$ascii_punctuation:expr
) => {
ascii_compatible_encoder_functions!(
$bmp_body,
{
return (
EncoderResult::Unmappable(astral),
$source.consumed(),
$handle.written(),
);
},
$bmp,
astral,
$slf,
$source,
$handle,
$copy_ascii,
$destination_check,
$ascii_punctuation
);
};
}
macro_rules! public_decode_function{
+126 -112
View File
@@ -21,14 +21,14 @@
//! in-memory encoding is sometimes used as a storage optimization of text
//! when UTF-16 indexing and length semantics are exposed.
use ascii::*;
use super::in_inclusive_range8;
use super::in_inclusive_range16;
use super::in_range16;
use super::in_inclusive_range32;
use super::in_inclusive_range8;
use super::in_range16;
use super::in_range32;
use super::DecoderResult;
use super::EncoderResult;
use ascii::*;
use utf_8::*;
cfg_if!{
@@ -65,138 +65,152 @@ const LATIN1_MASK: usize = 0xFF00FF00_FF00FF00u64 as usize;
#[allow(unused_macros)]
macro_rules! by_unit_check_alu {
($name:ident,
$unit:ty,
$bound:expr,
$mask:ident) => (
#[inline(always)]
fn $name(buffer: &[$unit]) -> bool {
let mut offset = 0usize;
let mut accu = 0usize;
let unit_size = ::std::mem::size_of::<$unit>();
let len = buffer.len();
if len >= ALU_ALIGNMENT / unit_size {
// The most common reason to return `false` is for the first code
// unit to fail the test, so check that first.
if buffer[0] >= $bound {
return false;
}
let src = buffer.as_ptr();
let mut until_alignment = ((ALU_ALIGNMENT - ((src as usize) & ALU_ALIGNMENT_MASK)) &
ALU_ALIGNMENT_MASK) / unit_size;
if until_alignment + ALU_ALIGNMENT / unit_size <= len {
if until_alignment != 0 {
accu |= buffer[offset] as usize;
offset += 1;
until_alignment -= 1;
while until_alignment != 0 {
($name:ident, $unit:ty, $bound:expr, $mask:ident) => {
#[inline(always)]
fn $name(buffer: &[$unit]) -> bool {
let mut offset = 0usize;
let mut accu = 0usize;
let unit_size = ::std::mem::size_of::<$unit>();
let len = buffer.len();
if len >= ALU_ALIGNMENT / unit_size {
// The most common reason to return `false` is for the first code
// unit to fail the test, so check that first.
if buffer[0] >= $bound {
return false;
}
let src = buffer.as_ptr();
let mut until_alignment = ((ALU_ALIGNMENT - ((src as usize) & ALU_ALIGNMENT_MASK))
& ALU_ALIGNMENT_MASK) / unit_size;
if until_alignment + ALU_ALIGNMENT / unit_size <= len {
if until_alignment != 0 {
accu |= buffer[offset] as usize;
offset += 1;
until_alignment -= 1;
}
if accu >= $bound {
return false;
}
}
let len_minus_stride = len - ALU_ALIGNMENT / unit_size;
if offset + (4 * (ALU_ALIGNMENT / unit_size)) <= len {
let len_minus_unroll = len - (4 * (ALU_ALIGNMENT / unit_size));
loop {
let unroll_accu = unsafe { *(src.offset(offset as isize) as *const usize) } |
unsafe { *(src.offset((offset + (ALU_ALIGNMENT / unit_size)) as isize) as *const usize) } |
unsafe { *(src.offset((offset + (2 * (ALU_ALIGNMENT / unit_size))) as isize) as *const usize) } |
unsafe { *(src.offset((offset + (3 * (ALU_ALIGNMENT / unit_size))) as isize) as *const usize) };
if unroll_accu & $mask != 0 {
while until_alignment != 0 {
accu |= buffer[offset] as usize;
offset += 1;
until_alignment -= 1;
}
if accu >= $bound {
return false;
}
offset += 4 * (ALU_ALIGNMENT / unit_size);
if offset > len_minus_unroll {
break;
}
let len_minus_stride = len - ALU_ALIGNMENT / unit_size;
if offset + (4 * (ALU_ALIGNMENT / unit_size)) <= len {
let len_minus_unroll = len - (4 * (ALU_ALIGNMENT / unit_size));
loop {
let unroll_accu = unsafe {
*(src.offset(offset as isize) as *const usize)
} | unsafe {
*(src.offset((offset + (ALU_ALIGNMENT / unit_size)) as isize)
as *const usize)
} | unsafe {
*(src.offset((offset + (2 * (ALU_ALIGNMENT / unit_size))) as isize)
as *const usize)
} | unsafe {
*(src.offset((offset + (3 * (ALU_ALIGNMENT / unit_size))) as isize)
as *const usize)
};
if unroll_accu & $mask != 0 {
return false;
}
offset += 4 * (ALU_ALIGNMENT / unit_size);
if offset > len_minus_unroll {
break;
}
}
}
}
while offset <= len_minus_stride {
accu |= unsafe { *(src.offset(offset as isize) as *const usize) };
offset += ALU_ALIGNMENT / unit_size;
while offset <= len_minus_stride {
accu |= unsafe { *(src.offset(offset as isize) as *const usize) };
offset += ALU_ALIGNMENT / unit_size;
}
}
}
for &unit in &buffer[offset..] {
accu |= unit as usize;
}
accu & $mask == 0
}
for &unit in &buffer[offset..] {
accu |= unit as usize;
}
accu & $mask == 0
})
};
}
#[allow(unused_macros)]
macro_rules! by_unit_check_simd {
($name:ident,
$unit:ty,
$splat:expr,
$simd_ty:ty,
$bound:expr,
$func:ident) => (
#[inline(always)]
fn $name(buffer: &[$unit]) -> bool {
let mut offset = 0usize;
let mut accu = 0usize;
let unit_size = ::std::mem::size_of::<$unit>();
let len = buffer.len();
if len >= SIMD_STRIDE_SIZE / unit_size {
// The most common reason to return `false` is for the first code
// unit to fail the test, so check that first.
if buffer[0] >= $bound {
return false;
}
let src = buffer.as_ptr();
let mut until_alignment = ((SIMD_ALIGNMENT - ((src as usize) & SIMD_ALIGNMENT_MASK)) &
SIMD_ALIGNMENT_MASK) / unit_size;
if until_alignment + SIMD_STRIDE_SIZE / unit_size <= len {
if until_alignment != 0 {
accu |= buffer[offset] as usize;
offset += 1;
until_alignment -= 1;
while until_alignment != 0 {
($name:ident, $unit:ty, $splat:expr, $simd_ty:ty, $bound:expr, $func:ident) => {
#[inline(always)]
fn $name(buffer: &[$unit]) -> bool {
let mut offset = 0usize;
let mut accu = 0usize;
let unit_size = ::std::mem::size_of::<$unit>();
let len = buffer.len();
if len >= SIMD_STRIDE_SIZE / unit_size {
// The most common reason to return `false` is for the first code
// unit to fail the test, so check that first.
if buffer[0] >= $bound {
return false;
}
let src = buffer.as_ptr();
let mut until_alignment = ((SIMD_ALIGNMENT - ((src as usize) & SIMD_ALIGNMENT_MASK))
& SIMD_ALIGNMENT_MASK) / unit_size;
if until_alignment + SIMD_STRIDE_SIZE / unit_size <= len {
if until_alignment != 0 {
accu |= buffer[offset] as usize;
offset += 1;
until_alignment -= 1;
while until_alignment != 0 {
accu |= buffer[offset] as usize;
offset += 1;
until_alignment -= 1;
}
if accu >= $bound {
return false;
}
}
if accu >= $bound {
let len_minus_stride = len - SIMD_STRIDE_SIZE / unit_size;
if offset + (4 * (SIMD_STRIDE_SIZE / unit_size)) <= len {
let len_minus_unroll = len - (4 * (SIMD_STRIDE_SIZE / unit_size));
loop {
let unroll_accu = unsafe {
*(src.offset(offset as isize) as *const $simd_ty)
} | unsafe {
*(src.offset((offset + (SIMD_STRIDE_SIZE / unit_size)) as isize)
as *const $simd_ty)
} | unsafe {
*(src.offset(
(offset + (2 * (SIMD_STRIDE_SIZE / unit_size))) as isize,
) as *const $simd_ty)
} | unsafe {
*(src.offset(
(offset + (3 * (SIMD_STRIDE_SIZE / unit_size))) as isize,
) as *const $simd_ty)
};
if !$func(unroll_accu) {
return false;
}
offset += 4 * (SIMD_STRIDE_SIZE / unit_size);
if offset > len_minus_unroll {
break;
}
}
}
let mut simd_accu = $splat;
while offset <= len_minus_stride {
simd_accu = simd_accu | unsafe {
*(src.offset(offset as isize) as *const $simd_ty)
};
offset += SIMD_STRIDE_SIZE / unit_size;
}
if !$func(simd_accu) {
return false;
}
}
let len_minus_stride = len - SIMD_STRIDE_SIZE / unit_size;
if offset + (4 * (SIMD_STRIDE_SIZE / unit_size)) <= len {
let len_minus_unroll = len - (4 * (SIMD_STRIDE_SIZE / unit_size));
loop {
let unroll_accu = unsafe { *(src.offset(offset as isize) as *const $simd_ty) } |
unsafe { *(src.offset((offset + (SIMD_STRIDE_SIZE / unit_size)) as isize) as *const $simd_ty) } |
unsafe { *(src.offset((offset + (2 * (SIMD_STRIDE_SIZE / unit_size))) as isize) as *const $simd_ty) } |
unsafe { *(src.offset((offset + (3 * (SIMD_STRIDE_SIZE / unit_size))) as isize) as *const $simd_ty) };
if !$func(unroll_accu) {
return false;
}
offset += 4 * (SIMD_STRIDE_SIZE / unit_size);
if offset > len_minus_unroll {
break;
}
}
}
let mut simd_accu = $splat;
while offset <= len_minus_stride {
simd_accu = simd_accu | unsafe { *(src.offset(offset as isize) as *const $simd_ty) };
offset += SIMD_STRIDE_SIZE / unit_size;
}
if !$func(simd_accu) {
return false;
}
}
for &unit in &buffer[offset..] {
accu |= unit as usize;
}
accu < $bound
}
for &unit in &buffer[offset..] {
accu |= unit as usize;
}
accu < $bound
})
};
}
cfg_if!{
+1 -1
View File
@@ -7,8 +7,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use variant::*;
use super::*;
use variant::*;
pub struct ReplacementDecoder {
emitted: bool,
+3 -3
View File
@@ -7,10 +7,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use handles::*;
use data::*;
use variant::*;
use super::*;
use data::*;
use handles::*;
use variant::*;
// Rust 1.14.0 requires the following despite the asterisk above.
use super::in_inclusive_range;
use super::in_inclusive_range16;
+3 -3
View File
@@ -7,8 +7,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use simd::u8x16;
use simd::u16x8;
use simd::u8x16;
use simd::Simd;
// TODO: Migrate unaligned access to stdlib code if/when the RFC
@@ -222,10 +222,10 @@ cfg_if! {
}
macro_rules! in_range16x8 {
($s:ident, $start:expr, $end:expr) => ({
($s:ident, $start:expr, $end:expr) => {{
// SIMD sub is wrapping
($s - u16x8::splat($start)).lt(u16x8::splat($end - $start))
})
}};
}
#[inline(always)]
+2 -2
View File
@@ -7,10 +7,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::*;
use ascii::*;
use handles::*;
use variant::*;
use ascii::*;
use super::*;
pub struct SingleByteDecoder {
table: &'static [u16; 128],
+1 -1
View File
@@ -7,9 +7,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::*;
use handles::*;
use variant::*;
use super::*;
pub struct Utf16Decoder {
lead_surrogate: u16, // If non-zero and pending_bmp == false, a pending lead surrogate
+2 -2
View File
@@ -10,11 +10,11 @@
#[cfg(feature = "parallel-utf8")]
extern crate rayon;
use handles::*;
use variant::*;
use super::*;
use ascii::ascii_to_basic_latin;
use ascii::basic_latin_to_ascii;
use handles::*;
use variant::*;
// Keep this cfg_if in sync with whether the utf_8_core module is defined in lib.rs.
cfg_if! {
+269 -27
View File
@@ -76,21 +76,23 @@ pub fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
};
let old_offset = index;
macro_rules! err {
($error_len: expr) => {
($error_len:expr) => {
return Err(Utf8Error {
valid_up_to: old_offset,
})
}
});
};
}
macro_rules! next { () => {{
index += 1;
// we needed data, but there was none: error!
if index >= len {
err!(None)
}
v[index]
}}}
macro_rules! next {
() => {{
index += 1;
// we needed data, but there was none: error!
if index >= len {
err!(None)
}
v[index]
}};
}
'inner: loop {
let w = UTF8_CHAR_WIDTH[first as usize];
@@ -164,22 +166,262 @@ pub fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
// https://tools.ietf.org/html/rfc3629
static UTF8_CHAR_WIDTH: [u8; 256] = [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 0x1F
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 0x3F
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 0x5F
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1, // 0x7F
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, // 0x9F
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, // 0xBF
0,
0,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2, // 0xDF
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3, // 0xEF
4,
4,
4,
4,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0, // 0xFF
];
/// Mask of the value bits of a continuation byte
+7 -7
View File
@@ -19,18 +19,18 @@
//! The purpose of making `Decoder` and `Encoder` `Sized` is to allow stack
//! allocation in Rust code, including the convenience methods on `Encoding`.
use single_byte::*;
use utf_8::*;
use gb18030::*;
use super::*;
use big5::*;
use euc_jp::*;
use iso_2022_jp::*;
use shift_jis::*;
use euc_kr::*;
use gb18030::*;
use iso_2022_jp::*;
use replacement::*;
use x_user_defined::*;
use shift_jis::*;
use single_byte::*;
use utf_16::*;
use super::*;
use utf_8::*;
use x_user_defined::*;
pub enum VariantDecoder {
SingleByte(SingleByteDecoder),
+1 -1
View File
@@ -7,9 +7,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::*;
use handles::*;
use variant::*;
use super::*;
cfg_if!{
if #[cfg(feature = "simd-accel")] {