-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from rodrimati1992/0_2_5
0.2.5 release
- Loading branch information
Showing
21 changed files
with
738 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "const_panic" | ||
version = "0.2.4" | ||
version = "0.2.5" | ||
authors = ["rodrimati1992 <[email protected]>"] | ||
edition = "2021" | ||
license = "Zlib" | ||
|
@@ -24,13 +24,18 @@ version = "=0.2.0" | |
path = "./const_panic_proc_macros/" | ||
optional = true | ||
|
||
[dev-dependencies.arrayvec] | ||
version = "0.7" | ||
|
||
[dev-dependencies.rand] | ||
version = "0.8.4" | ||
default_features = false | ||
features = ["small_rng"] | ||
|
||
[features] | ||
default = ["non_basic"] | ||
|
||
rust_1_64 = [] | ||
non_basic = [] | ||
docsrs = [] | ||
derive = ["const_panic_proc_macros"] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
//! `char`-formatted related items | ||
use crate::{ | ||
fmt::{FmtArg, FmtKind}, | ||
fmt_impls::basic_fmt_impls::primitive_static_panicfmt, | ||
panic_val::{PanicVal, PanicVariant}, | ||
utils::{string_cap, PreFmtString, StartAndBytes}, | ||
}; | ||
|
||
#[cfg(all(test, not(miri)))] | ||
mod tests; | ||
|
||
impl PanicVal<'_> { | ||
/// Constructs a `PanicVal` from a `char`. | ||
pub const fn from_char(c: char, fmtarg: FmtArg) -> Self { | ||
let StartAndBytes { start, bytes } = match fmtarg.fmt_kind { | ||
FmtKind::Display => { | ||
let (arr, len) = char_to_utf8(c); | ||
crate::utils::tail_byte_array::<{ string_cap::PREFMT }>(len, &arr) | ||
} | ||
FmtKind::Debug => { | ||
let fmtchar = char_to_debug(c); | ||
crate::utils::tail_byte_array(fmtchar.len(), &fmtchar.encoded) | ||
} | ||
}; | ||
// SAFETY: | ||
// char_to_utf8 is exhaustively tested in the tests module. | ||
// char_to_debug is exhaustively tested in the tests module. | ||
// tail_byte_array is also tested for smaller/equal/larger input arrays. | ||
let prefmt = unsafe { PreFmtString::new(start, bytes) }; | ||
PanicVal { | ||
var: PanicVariant::PreFmt(prefmt), | ||
} | ||
} | ||
} | ||
|
||
primitive_static_panicfmt! { | ||
fn[](&self: char, fmtarg) { | ||
PanicVal::from_char(*self.0, fmtarg) | ||
} | ||
} | ||
|
||
/// Converts 0..=0xF to its ascii representation of '0'..='9' and 'A'..='F' | ||
#[inline] | ||
const fn hex_as_ascii(n: u8) -> u8 { | ||
if n < 10 { | ||
n + b'0' | ||
} else { | ||
n - 10 + b'A' | ||
} | ||
} | ||
|
||
#[cfg(any(test, feature = "fmt"))] | ||
pub(crate) const fn char_debug_len(c: char) -> usize { | ||
let inner = match c { | ||
'\t' | '\r' | '\n' | '\\' | '\'' => 2, | ||
'\x00'..='\x1F' => 4, | ||
_ => c.len_utf8(), | ||
}; | ||
inner + 2 | ||
} | ||
|
||
const fn char_to_utf8(char: char) -> ([u8; 4], usize) { | ||
let u32 = char as u32; | ||
match u32 { | ||
0..=127 => ([u32 as u8, 0, 0, 0], 1), | ||
0x80..=0x7FF => { | ||
let b0 = 0b1100_0000 | (u32 >> 6) as u8; | ||
let b1 = 0b1000_0000 | (u32 & 0b0011_1111) as u8; | ||
([b0, b1, 0, 0], 2) | ||
} | ||
0x800..=0xFFFF => { | ||
let b0 = 0b1110_0000 | (u32 >> 12) as u8; | ||
let b1 = 0b1000_0000 | ((u32 >> 6) & 0b0011_1111) as u8; | ||
let b2 = 0b1000_0000 | (u32 & 0b0011_1111) as u8; | ||
([b0, b1, b2, 0], 3) | ||
} | ||
0x10000..=u32::MAX => { | ||
let b0 = 0b1111_0000 | (u32 >> 18) as u8; | ||
let b1 = 0b1000_0000 | ((u32 >> 12) & 0b0011_1111) as u8; | ||
let b2 = 0b1000_0000 | ((u32 >> 6) & 0b0011_1111) as u8; | ||
let b3 = 0b1000_0000 | (u32 & 0b0011_1111) as u8; | ||
([b0, b1, b2, b3], 4) | ||
} | ||
} | ||
} | ||
|
||
/// Display formats a `char` | ||
pub const fn char_to_display(char: char) -> FmtChar { | ||
let ([b0, b1, b2, b3], len) = char_to_utf8(char); | ||
FmtChar { | ||
encoded: [b0, b1, b2, b3, 0, 0, 0, 0, 0, 0, 0, 0], | ||
len: len as u8, | ||
} | ||
} | ||
|
||
/// Debug formats a `char` | ||
pub const fn char_to_debug(c: char) -> FmtChar { | ||
let ([b0, b1, b2, b3], len) = match c { | ||
'\t' => (*br#"\t "#, 2), | ||
'\r' => (*br#"\r "#, 2), | ||
'\n' => (*br#"\n "#, 2), | ||
'\\' => (*br#"\\ "#, 2), | ||
'\'' => (*br#"\' "#, 2), | ||
'\"' => (*br#"" "#, 1), | ||
'\x00'..='\x1F' => { | ||
let n = c as u8; | ||
( | ||
[b'\\', b'x', hex_as_ascii(n >> 4), hex_as_ascii(n & 0b1111)], | ||
4, | ||
) | ||
} | ||
_ => char_to_utf8(c), | ||
}; | ||
|
||
let mut encoded = [b'\'', b0, b1, b2, b3, 0, 0, 0, 0, 0, 0, 0]; | ||
encoded[len + 1] = b'\''; | ||
|
||
FmtChar { | ||
encoded, | ||
len: (len as u8) + 2, | ||
} | ||
} | ||
|
||
/// An byte slice with a display/debug formatted `char`. | ||
/// | ||
/// To get the encoded character, you need to do | ||
/// `&fmt_char.encoded()[..fmt_char.len()]`. | ||
#[derive(Copy, Clone)] | ||
pub struct FmtChar { | ||
encoded: [u8; 12], | ||
len: u8, | ||
} | ||
|
||
impl FmtChar { | ||
/// Array which contains the display/debug-formatted `char`, | ||
/// and trailing `0` padding. | ||
pub const fn encoded(&self) -> &[u8; 12] { | ||
&self.encoded | ||
} | ||
|
||
/// The length of the subslice that contains the formatted character. | ||
pub const fn len(&self) -> usize { | ||
self.len as usize | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
use super::{char_debug_len, char_to_debug, char_to_display, FmtChar}; | ||
|
||
fn as_bytes(fmt: &FmtChar) -> &[u8] { | ||
&fmt.encoded()[..fmt.len()] | ||
} | ||
|
||
#[test] | ||
fn char_to_utf8_encoding_test() { | ||
for c in '\0'..=core::char::MAX { | ||
let mut utf8_std = [0u8; 4]; | ||
let utf8_std = c.encode_utf8(&mut utf8_std); | ||
|
||
let utf8_here = char_to_display(c); | ||
assert_eq!(utf8_std.as_bytes(), as_bytes(&utf8_here)); | ||
} | ||
} | ||
|
||
#[test] | ||
fn char_to_utf8_display_test() { | ||
for c in '\0'..=core::char::MAX { | ||
let mut utf8_std = [0u8; 4]; | ||
let utf8_std = c.encode_utf8(&mut utf8_std); | ||
|
||
let utf8_here = char_to_display(c); | ||
assert_eq!(utf8_std.as_bytes(), as_bytes(&utf8_here)); | ||
} | ||
} | ||
|
||
#[test] | ||
fn char_to_utf8_debug_test() { | ||
let first_escapes = [ | ||
('\x00', r#"'\x00'"#), | ||
('\x01', r#"'\x01'"#), | ||
('\x02', r#"'\x02'"#), | ||
('\x03', r#"'\x03'"#), | ||
('\x04', r#"'\x04'"#), | ||
('\x05', r#"'\x05'"#), | ||
('\x06', r#"'\x06'"#), | ||
('\x07', r#"'\x07'"#), | ||
('\x08', r#"'\x08'"#), | ||
('\t', r#"'\t'"#), | ||
('\n', r#"'\n'"#), | ||
('\x0B', r#"'\x0B'"#), | ||
('\x0C', r#"'\x0C'"#), | ||
('\r', r#"'\r'"#), | ||
('\x0E', r#"'\x0E'"#), | ||
('\x0F', r#"'\x0F'"#), | ||
('\x10', r#"'\x10'"#), | ||
('\x11', r#"'\x11'"#), | ||
('\x12', r#"'\x12'"#), | ||
('\x13', r#"'\x13'"#), | ||
('\x14', r#"'\x14'"#), | ||
('\x15', r#"'\x15'"#), | ||
('\x16', r#"'\x16'"#), | ||
('\x17', r#"'\x17'"#), | ||
('\x18', r#"'\x18'"#), | ||
('\x19', r#"'\x19'"#), | ||
('\x1A', r#"'\x1A'"#), | ||
('\x1B', r#"'\x1B'"#), | ||
('\x1C', r#"'\x1C'"#), | ||
('\x1D', r#"'\x1D'"#), | ||
('\x1E', r#"'\x1E'"#), | ||
('\x1F', r#"'\x1F'"#), | ||
]; | ||
|
||
for (c, expected) in first_escapes.iter().copied() { | ||
let utf8_here = char_to_debug(c); | ||
assert_eq!(expected.as_bytes(), as_bytes(&utf8_here), "{:?}", c); | ||
assert_eq!(expected.len(), char_debug_len(c), "{:?}", c); | ||
} | ||
|
||
let other_escapes = [('\'', r#"'\''"#), ('\"', r#"'"'"#), ('\\', r#"'\\'"#)]; | ||
|
||
let mut buffer = arrayvec::ArrayString::<12>::new(); | ||
for c in '\x20'..=core::char::MAX { | ||
let utf8_here = char_to_debug(c); | ||
|
||
if let Some((_, expected)) = Some(c) | ||
.filter(|c| *c <= '\x7F') | ||
.and_then(|c| other_escapes.iter().copied().find(|x| x.0 == c)) | ||
{ | ||
assert_eq!(expected.as_bytes(), as_bytes(&utf8_here), "{:?}", c); | ||
assert_eq!(expected.len(), char_debug_len(c), "{:?}", c); | ||
} else { | ||
buffer.clear(); | ||
buffer.push('\''); | ||
buffer.push(c); | ||
buffer.push('\''); | ||
assert_eq!(buffer.as_bytes(), as_bytes(&utf8_here), "{:?}", c); | ||
assert_eq!(buffer.len(), char_debug_len(c), "{:?}", c); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.