Some cleanup
This commit is contained in:
parent
9daecc56ea
commit
0144056d99
14
Cargo.toml
14
Cargo.toml
|
@ -7,22 +7,10 @@ edition = "2021"
|
|||
default = ["std"]
|
||||
alloc = []
|
||||
std = ["alloc"]
|
||||
# provides the test data and helpers used by the benches crate
|
||||
test = []
|
||||
|
||||
[dependencies]
|
||||
brisk = { git = "https://git.pfaff.dev/michael/brisk.git" }
|
||||
cache-padded = "1.2"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.4", features = [ "real_blackbox" ] }
|
||||
rand = "0.8.5"
|
||||
|
||||
[[bench]]
|
||||
name = "dec"
|
||||
harness = false
|
||||
required-features = ["test"]
|
||||
|
||||
[[bench]]
|
||||
name = "enc"
|
||||
harness = false
|
||||
required-features = ["test"]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "fast-hex-benches"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
fast-hex = { path = "../", features = ["test"] }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.4", features = [ "real_blackbox" ] }
|
||||
rand = "0.8.5"
|
||||
|
||||
[[bench]]
|
||||
name = "dec"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "enc"
|
||||
harness = false
|
|
@ -9,9 +9,11 @@ use fast_hex::dec::*;
|
|||
use fast_hex::defs::{DIGIT_BATCH_SIZE, WIDE_BATCH_SIZE};
|
||||
use fast_hex::test::name;
|
||||
|
||||
// TODO: change this example text to something less silly
|
||||
const ASCII_BYTES: &[u8; 16] = b"Donald J. Trump!";
|
||||
const HEX_BYTES: &[u8; ASCII_BYTES.len() * 2] = b"446F6E616C64204A2E205472756D7021";
|
||||
|
||||
// TODO: change this example text to something less silly
|
||||
const ASCII_BYTES_LONG: &[u8; 256] = b"Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!";
|
||||
const HEX_BYTES_LONG: &[u8; ASCII_BYTES_LONG.len() * 2] = b"446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021";
|
||||
|
|
@ -8,9 +8,11 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
|||
use fast_hex::enc::{Encode as _, Encoder};
|
||||
use fast_hex::test::name;
|
||||
|
||||
// TODO: change this example text to something less silly
|
||||
const ASCII_BYTES: &[u8; 16] = b"Donald J. Trump!";
|
||||
const HEX_BYTES: &[u8; ASCII_BYTES.len() * 2] = b"446F6E616C64204A2E205472756D7021";
|
||||
|
||||
// TODO: change this example text to something less silly
|
||||
const ASCII_BYTES_LONG: &[u8; 256] = b"Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!Donald J. Trump!";
|
||||
const HEX_BYTES_LONG: &[u8; ASCII_BYTES_LONG.len() * 2] = b"446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021446F6E616C64204A2E205472756D7021";
|
||||
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
use core::mem::MaybeUninit;
|
||||
use core::simd::*;
|
||||
use core::simd::num::SimdUint;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
@ -179,7 +180,7 @@ macro_rules! merge_hex_digits_into_bytes_inline {
|
|||
let lsb = simd::extract_hi_bytes($hex_digits);
|
||||
|
||||
let msb1: simd::arch::__m128i;
|
||||
unsafe { std::arch::asm!("vpsllq {dst}, {src}, 4", src = in(xmm_reg) msb, dst = lateout(xmm_reg) msb1, options(pure, nomem, preserves_flags, nostack)) };
|
||||
unsafe { core::arch::asm!("vpsllq {dst}, {src}, 4", src = in(xmm_reg) msb, dst = lateout(xmm_reg) msb1, options(pure, nomem, preserves_flags, nostack)) };
|
||||
if_trace_simd! {
|
||||
let msb1: Simd<u8, WIDE_BATCH_SIZE> = msb1.into();
|
||||
println!("msb1: {msb1:x?}");
|
||||
|
@ -350,9 +351,7 @@ pub const fn hex_bytes_sized_const<const N: usize>(ascii: &[u8; N * 2]) -> Optio
|
|||
if i >> 1 >= bytes.len() {
|
||||
unsafe { core::hint::unreachable_unchecked() };
|
||||
}
|
||||
match hex_byte(unsafe { *ascii.get_unchecked(i) }, unsafe {
|
||||
*ascii.get_unchecked(i + 1)
|
||||
}) {
|
||||
match hex_byte(ascii[i], ascii[i + 1]) {
|
||||
Some(b) => bytes[i >> 1] = MaybeUninit::new(b),
|
||||
None => return None,
|
||||
}
|
||||
|
|
109
src/enc.rs
109
src/enc.rs
|
@ -1,7 +1,10 @@
|
|||
//! SIMD-accelerated hex encoding.
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::simd::*;
|
||||
use core::fmt;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
|
@ -147,7 +150,7 @@ macro_rules! const_impl1 {
|
|||
|
||||
#[inline(always)]
|
||||
fn u64_to_ne_u16(v: u64) -> [u16; 4] {
|
||||
unsafe { std::mem::transmute(v.to_ne_bytes()) }
|
||||
unsafe { core::mem::transmute(v.to_ne_bytes()) }
|
||||
}
|
||||
|
||||
macro_rules! const_impl {
|
||||
|
@ -277,7 +280,7 @@ macro_rules! common_impl {
|
|||
//let chunk: simd::arch::__m128i = Simd::from_array(chunk).into();
|
||||
let chunk: simd::arch::__m128i;
|
||||
// We've aligned the src ptr
|
||||
std::arch::asm!("vmovdqu {dst}, [{src}]", src = in(reg) src, dst = lateout(xmm_reg) chunk, options(pure, readonly, preserves_flags, nostack));
|
||||
core::arch::asm!("vmovdqu {dst}, [{src}]", src = in(reg) src, dst = lateout(xmm_reg) chunk, options(pure, readonly, preserves_flags, nostack));
|
||||
|
||||
let hi = chunk.and(hi_mask);
|
||||
// 64 vs 16 seems to make no difference
|
||||
|
@ -337,7 +340,7 @@ macro_rules! common_impl {
|
|||
|
||||
if_trace_simd! {
|
||||
let slice: &[_] = $dst.as_ref();
|
||||
match std::str::from_utf8(unsafe { &*(slice as *const [_] as *const [u8]) }) {
|
||||
match core::str::from_utf8(unsafe { &*(slice as *const [_] as *const [u8]) }) {
|
||||
Ok(s) => {
|
||||
println!("encoded: {s:?}");
|
||||
}
|
||||
|
@ -355,9 +358,10 @@ macro_rules! define_encode {
|
|||
write => $write:ident
|
||||
$(,)?
|
||||
} $(where $( $where:tt )+)?) => {
|
||||
#[cfg(feature = "alloc")]
|
||||
fn $str$(<const $N: usize>)?(src: $in) -> String $( where $( $where )+ )?;
|
||||
|
||||
fn $write$(<const $N: usize>)?(w: impl std::fmt::Write, src: $in) -> std::fmt::Result $( where $( $where )+ )?;
|
||||
fn $write$(<const $N: usize>)?(w: impl fmt::Write, src: $in) -> fmt::Result $( where $( $where )+ )?;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -374,35 +378,42 @@ macro_rules! impl_encode_str {
|
|||
macro_rules! impl_encode_write {
|
||||
($name:ident$(<$N:ident>)?($in:ty) => $impl:ident (|$bytes:ident| $into_slice:expr) $(where $( $where:tt )+)?) => {
|
||||
#[inline]
|
||||
fn $name$(<const $N: usize>)?(mut w: impl std::fmt::Write, src: $in) -> std::fmt::Result $( where $( $where )+ )? {
|
||||
fn $name$(<const $N: usize>)?(mut w: impl fmt::Write, src: $in) -> fmt::Result $( where $( $where )+ )? {
|
||||
let $bytes = Self::$impl(src);
|
||||
let s = unsafe { std::str::from_utf8_unchecked($into_slice) };
|
||||
let s = unsafe { core::str::from_utf8_unchecked($into_slice) };
|
||||
w.write_str(s)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub struct DisplaySized<'a, E: Encode + ?Sized, const N: usize>(&'a [u8; N], std::marker::PhantomData<E>);
|
||||
pub struct DisplaySizedHeap<'a, E: Encode + ?Sized, const N: usize>(&'a [u8; N], std::marker::PhantomData<E>);
|
||||
pub struct DisplaySlice<'a, E: Encode + ?Sized>(&'a [u8], std::marker::PhantomData<E>);
|
||||
// TODO: keep only DisplaySized and DisplaySlice and for DisplaySized implement a heuristic to
|
||||
// decide when to use a fixed-size buffer and encode+write in chunks
|
||||
pub struct DisplaySized<'a, E: Encode + ?Sized, const N: usize>(&'a [u8; N], core::marker::PhantomData<E>);
|
||||
#[cfg(feature = "alloc")]
|
||||
#[deprecated(note = "Please don't start using this. It will be merged in to [`DisplaySized`] soon.")]
|
||||
pub struct DisplaySizedHeap<'a, E: Encode + ?Sized, const N: usize>(&'a [u8; N], core::marker::PhantomData<E>);
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct DisplaySlice<'a, E: Encode + ?Sized>(&'a [u8], core::marker::PhantomData<E>);
|
||||
|
||||
impl<'a, E: Encode, const N: usize> std::fmt::Display for DisplaySized<'a, E, N> where [u8; N * 2]: {
|
||||
impl<'a, E: Encode, const N: usize> fmt::Display for DisplaySized<'a, E, N> where [u8; N * 2]: {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
E::write_sized(f, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Encode, const N: usize> std::fmt::Display for DisplaySizedHeap<'a, E, N> where [u8; N * 2]: {
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a, E: Encode, const N: usize> fmt::Display for DisplaySizedHeap<'a, E, N> where [u8; N * 2]: {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
E::write_sized_heap(f, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Encode> std::fmt::Display for DisplaySlice<'a, E> {
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a, E: Encode> fmt::Display for DisplaySlice<'a, E> {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
E::write_slice(f, self.0)
|
||||
}
|
||||
}
|
||||
|
@ -414,38 +425,55 @@ pub trait Encode {
|
|||
[u8; N * 2]:;
|
||||
|
||||
/// Encodes the sized input on the heap.
|
||||
#[cfg(feature = "alloc")]
|
||||
fn enc_sized_heap<const N: usize>(src: &[u8; N]) -> Box<[u8; N * 2]>
|
||||
where
|
||||
[u8; N * 2]:;
|
||||
|
||||
/// Encodes the unsized input on the heap.
|
||||
#[cfg(feature = "alloc")]
|
||||
fn enc_slice(src: &[u8]) -> Box<[u8]>;
|
||||
|
||||
define_encode!(enc_sized<N>(&[u8; N]) {
|
||||
str => enc_str_sized,
|
||||
write => write_sized,
|
||||
} where [u8; N * 2]:);
|
||||
#[cfg(feature = "alloc")]
|
||||
define_encode!(enc_sized_heap<N>(&[u8; N]) {
|
||||
str => enc_str_sized_heap,
|
||||
write => write_sized_heap,
|
||||
} where [u8; N * 2]:);
|
||||
#[cfg(feature = "alloc")]
|
||||
define_encode!(enc_slice(&[u8]) {
|
||||
str => enc_str_slice,
|
||||
write => write_slice,
|
||||
});
|
||||
|
||||
/// Returns an `impl Display` of the sized input on the stack.
|
||||
#[inline(always)]
|
||||
fn display_sized<const N: usize>(src: &[u8; N]) -> DisplaySized<'_, Self, N>
|
||||
where
|
||||
[u8; N * 2]:;
|
||||
[u8; N * 2]:
|
||||
{
|
||||
DisplaySized(src, core::marker::PhantomData)
|
||||
}
|
||||
|
||||
/// Returns an `impl Display` of the sized input on the heap.
|
||||
#[cfg(feature = "alloc")]
|
||||
#[inline(always)]
|
||||
fn display_sized_heap<const N: usize>(src: &[u8; N]) -> DisplaySizedHeap<'_, Self, N>
|
||||
where
|
||||
[u8; N * 2]:;
|
||||
[u8; N * 2]:
|
||||
{
|
||||
DisplaySizedHeap(src, core::marker::PhantomData)
|
||||
}
|
||||
|
||||
/// Returns an `impl Display` of the unsized input on the heap.
|
||||
fn display_slice(src: &[u8]) -> DisplaySlice<'_, Self>;
|
||||
#[cfg(feature = "alloc")]
|
||||
#[inline(always)]
|
||||
fn display_slice(src: &[u8]) -> DisplaySlice<'_, Self> {
|
||||
DisplaySlice(src, core::marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Encoder<const UPPER: bool = false>;
|
||||
|
@ -461,7 +489,7 @@ impl<const N: usize> Buffer<N> where [u8; N * 2]: {
|
|||
#[inline]
|
||||
pub fn format_exact<const UPPER: bool>(&mut self, bytes: &[u8; N]) -> &str {
|
||||
self.0 = MaybeUninit::new(Encoder::<UPPER>::enc_sized(bytes));
|
||||
unsafe { std::str::from_utf8_unchecked(self.0.assume_init_ref()) }
|
||||
unsafe { core::str::from_utf8_unchecked(self.0.assume_init_ref()) }
|
||||
}
|
||||
|
||||
// TODO: support using only part of the buffer.
|
||||
|
@ -469,7 +497,7 @@ impl<const N: usize> Buffer<N> where [u8; N * 2]: {
|
|||
/*pub fn format<const UPPER: bool>(&mut self, bytes: &[u8]) -> &str {
|
||||
assert!(bytes.len() <= N);
|
||||
self.0 = MaybeUninit::new(Encoder::<UPPER>::enc_slice(bytes));
|
||||
unsafe { std::str::from_utf8_unchecked(self.0.assume_init_ref()) }
|
||||
unsafe { core::str::from_utf8_unchecked(self.0.assume_init_ref()) }
|
||||
}*/
|
||||
}
|
||||
|
||||
|
@ -490,6 +518,7 @@ impl<const UPPER: bool> Encode for Encoder<UPPER> {
|
|||
unsafe { MaybeUninit::array_assume_init(buf.0) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[inline]
|
||||
fn enc_sized_heap<const N: usize>(src: &[u8; N]) -> Box<[u8; N * 2]>
|
||||
where
|
||||
|
@ -501,6 +530,7 @@ impl<const UPPER: bool> Encode for Encoder<UPPER> {
|
|||
unsafe { Box::from_raw(Box::into_raw(buf).cast()) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[inline]
|
||||
fn enc_slice(src: &[u8]) -> Box<[u8]> {
|
||||
let mut buf: Box<[MaybeUninit<u8>]> =
|
||||
|
@ -509,36 +539,21 @@ impl<const UPPER: bool> Encode for Encoder<UPPER> {
|
|||
unsafe { Box::<[_]>::assume_init(buf) }
|
||||
}
|
||||
|
||||
// TODO: use an ArrayStr-like struct instead of allocating a String
|
||||
#[cfg(feature = "alloc")]
|
||||
impl_encode_str!(enc_str_sized<N>(&[u8; N]) => enc_sized (|bytes| bytes.into()) where [u8; N * 2]:);
|
||||
#[cfg(feature = "alloc")]
|
||||
impl_encode_str!(enc_str_sized_heap<N>(&[u8; N]) => enc_sized_heap (|bytes| {
|
||||
Vec::from_raw_parts(Box::into_raw(bytes) as *mut u8, N * 2, N * 2)
|
||||
}) where [u8; N * 2]:);
|
||||
#[cfg(feature = "alloc")]
|
||||
impl_encode_str!(enc_str_slice(&[u8]) => enc_slice (|bytes| Vec::from(bytes)));
|
||||
|
||||
impl_encode_write!(write_sized<N>(&[u8; N]) => enc_sized (|bytes| &bytes) where [u8; N * 2]:);
|
||||
#[cfg(feature = "alloc")]
|
||||
impl_encode_write!(write_sized_heap<N>(&[u8; N]) => enc_sized_heap (|bytes| bytes.as_ref()) where [u8; N * 2]:);
|
||||
#[cfg(feature = "alloc")]
|
||||
impl_encode_write!(write_slice(&[u8]) => enc_slice (|bytes| bytes.as_ref()));
|
||||
|
||||
#[inline(always)]
|
||||
fn display_sized<const N: usize>(src: &[u8; N]) -> DisplaySized<'_, Self, N>
|
||||
where
|
||||
[u8; N * 2]:,
|
||||
{
|
||||
DisplaySized(src, std::marker::PhantomData)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn display_sized_heap<const N: usize>(src: &[u8; N]) -> DisplaySizedHeap<'_, Self, N>
|
||||
where
|
||||
[u8; N * 2]:,
|
||||
{
|
||||
DisplaySizedHeap(src, std::marker::PhantomData)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn display_slice(src: &[u8]) -> DisplaySlice<'_, Self> {
|
||||
DisplaySlice(src, std::marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const UPPER: bool> Encoder<UPPER> {
|
||||
|
@ -556,6 +571,9 @@ impl<const UPPER: bool> Encoder<UPPER> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
use alloc::borrow::ToOwned;
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::test::*;
|
||||
|
@ -619,20 +637,25 @@ mod test {
|
|||
|
||||
for_each_sample!(enc_const, |_, _, b, hb| assert_eq!(Enc::enc_const(b), *hb));
|
||||
for_each_sample!(enc_sized, |_, _, b, hb| assert_eq!(Enc::enc_sized(b), *hb));
|
||||
#[cfg(feature = "alloc")]
|
||||
for_each_sample!(enc_sized_heap, |_, _, b, hb| assert_eq!(
|
||||
Enc::enc_sized_heap(b),
|
||||
Box::new(*hb)
|
||||
));
|
||||
#[cfg(feature = "alloc")]
|
||||
for_each_sample!(enc_slice, |_, _, b, hb| assert_eq!(
|
||||
Enc::enc_slice(b),
|
||||
(*hb).into_iter().collect::<Vec<_>>().into_boxed_slice()
|
||||
));
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
for_each_sample!(enc_str_sized, |_, hs, b, _| assert_eq!(Enc::enc_str_sized(b), hs.to_owned()));
|
||||
#[cfg(feature = "alloc")]
|
||||
for_each_sample!(enc_str_sized_heap, |_, hs, b, _| assert_eq!(
|
||||
Enc::enc_str_sized_heap(b),
|
||||
hs.to_owned()
|
||||
));
|
||||
#[cfg(feature = "alloc")]
|
||||
for_each_sample!(enc_str_slice, |_, hs, b, _| assert_eq!(
|
||||
Enc::enc_str_slice(b),
|
||||
hs.to_owned()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// ignores warning about `generic_const_exprs`
|
||||
#![allow(incomplete_features)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![feature(array_chunks)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_slice_index)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(effects)]
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_uninit_array)]
|
||||
|
@ -12,10 +12,7 @@
|
|||
#![feature(const_maybe_uninit_array_assume_init)]
|
||||
#![feature(const_maybe_uninit_uninit_array)]
|
||||
#![cfg_attr(feature = "alloc", feature(new_uninit))]
|
||||
#![feature(stdsimd)]
|
||||
#![feature(portable_simd)]
|
||||
// ignores warning about `generic_const_exprs`
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
macro_rules! from_utf8 {
|
||||
($bytes:ident) => {
|
||||
unsafe { std::str::from_utf8_unchecked($bytes) }
|
||||
unsafe { core::str::from_utf8_unchecked($bytes) }
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: change this example text to something less silly
|
||||
pub const BYTES: &[u8; 16] = b"Donald J. Trump!";
|
||||
pub const HEX_BYTES: &[u8; 32] = b"446F6E616C64204A2E205472756D7021";
|
||||
pub const STR: &str = from_utf8!(BYTES);
|
||||
|
@ -44,13 +45,13 @@ macro_rules! __test__name {
|
|||
concat!("[", $group, "] - ", $f)
|
||||
};
|
||||
($group:expr, $f:literal) => {
|
||||
std::boxed::Box::leak(format!(name!("{}", $f), $group).into_boxed_str())
|
||||
::alloc::boxed::Box::leak(format!(name!("{}", $f), $group).into_boxed_str())
|
||||
};
|
||||
($group:expr, $f:expr) => {
|
||||
std::boxed::Box::leak(format!(name!("{}", "{}"), $group, $f).into_boxed_str())
|
||||
::alloc::boxed::Box::leak(format!(name!("{}", "{}"), $group, $f).into_boxed_str())
|
||||
};
|
||||
($group:literal, $f:expr) => {
|
||||
std::boxed::Box::leak(format!(name!($group, "{}"), $f).into_boxed_str())
|
||||
::alloc::boxed::Box::leak(format!(name!($group, "{}"), $f).into_boxed_str())
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue