master
Avril 4 years ago
parent 054f55b734
commit 70816f31f7
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -7,6 +7,9 @@ use std::{
ops::{
Range,
},
marker::{
PhantomData,
},
};
use tokio::{
io::AsyncRead,
@ -131,12 +134,105 @@ const ASCII_MAP: [char; 256] = [
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',
];
pub struct HexStringIter<'a, I>(&'a I, bool);
pub struct HexView<'a, I>(&'a I);
const fn create_hex_map() -> [(u8, u8); 256]
{
let mut out = [(0, 0); 256];
const HEX: &[u8; 16] = b"0123456789abcdef";
let mut i = 0usize;
while i <= 255
{
out[i] = (
HEX[i >> 4],
HEX[i & 0xf]
);
i+=1;
}
out
}
const HEX_MAP: [(u8, u8); 256] = create_hex_map();
pub struct HexStringView<'a, I:?Sized>(&'a I, bool);
pub struct HexStringIter<'a, I:?Sized>(std::slice::Iter<'a, u8>, (u8, u8), PhantomData<&'a I>);
pub struct HexView<'a, I:?Sized>(&'a I);
pub struct AsciiView<'a, I:?Sized>(&'a I);
pub struct AsciiIter<'a, I:?Sized>(&'a [u8], PhantomData<&'a I>);
const SPLIT_EVERY: usize = 16;
impl<'a, I: AsRef<[u8]>> fmt::Display for HexView<'a, I>
impl<'a, I: ?Sized+AsRef<[u8]>> Iterator for AsciiIter<'a, I>
{
type Item = char;
fn next(&mut self) -> Option<Self::Item>
{
match match self.0 {
[] => None,
[chr, ..] => Some(ASCII_MAP[*chr as usize]),
} {
x @ Some(_) => {
self.0 = &self.0[1..];
x
},
_ => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.0.len(), Some(self.0.len()))
}
}
impl<'a, I: ?Sized+AsRef<[u8]>> ExactSizeIterator for AsciiIter<'a, I>{}
impl<'a, I: ?Sized+AsRef<[u8]>> std::iter::FusedIterator for AsciiIter<'a, I>{}
impl<'a, I: ?Sized+AsRef<[u8]>> Iterator for HexStringIter<'a, I>
{
type Item = char;
fn next(&mut self) -> Option<Self::Item>
{
match self.1 {
ref mut buf @ (0, 0) => {
// both are taken
if let Some(&byte) = self.0.next() {
*buf = HEX_MAP[byte as usize];
} else {
return None;
}
(Some(buf.0 as char),buf.0 = 0).0
},
(0, ref mut second) => {
// first is taken
(Some(*second as char),*second = 0).0
},
#[cold] (ref mut first, _) => {
// neither are taken, usually shouldn't happen
(Some(*first as char),*first = 0).0
},
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let sz = self.0.size_hint();
(sz.0 * 2, sz.1.map(|x| x*2))
}
}
impl<'a, I: ?Sized+AsRef<[u8]>> ExactSizeIterator for HexStringIter<'a, I>{}
impl<'a, I: ?Sized+AsRef<[u8]>> std::iter::FusedIterator for HexStringIter<'a, I>{}
impl<'a, I: AsRef<[u8]>+?Sized> fmt::Display for AsciiView<'a, I>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
for byte in self.0.as_ref().iter().map(|&byte| ASCII_MAP[byte as usize])
{
use std::fmt::Write;
f.write_char(byte)?;
}
Ok(())
}
}
impl<'a, I: AsRef<[u8]>+?Sized> fmt::Display for HexView<'a, I>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
@ -178,7 +274,7 @@ impl<'a, I: AsRef<[u8]>> fmt::Display for HexView<'a, I>
}
}
impl<'a, I: AsRef<[u8]>> fmt::Display for HexStringIter<'a, I>
impl<'a, I: AsRef<[u8]>+?Sized> fmt::Display for HexStringView<'a, I>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
@ -202,10 +298,26 @@ impl<'a, I: AsRef<[u8]>> fmt::Display for HexStringIter<'a, I>
}
}
pub trait HexStringExt: Sized + AsRef<[u8]>
/// Extensions on byte slices to print them nicely
pub trait HexStringExt: AsRef<[u8]>
{
/// An iterator that prints readable ascii of each byte
fn iter_ascii(&self) -> AsciiIter<'_, Self>;
/// A `Display` implementor that prints ascii of each byte
fn fmt_ascii(&self) -> AsciiView<'_, Self>;
/// A pretty hex view `Display` implementor of the bytes
fn fmt_view(&self) -> HexView<'_, Self>;
fn fmt_hex(&self) -> HexStringIter<'_, Self>;
/// A `Display` implementor that prints the hex of each byte in lowercase
fn fmt_hex(&self) -> HexStringView<'_, Self>;
/// An iterator over `char`s that yields the hex of each byte
///
/// # Notes
/// This yields each character one at a time, to get the hex of each byte, chunk it with a window of 2.
fn iter_hex(&self) -> HexStringIter<'_, Self>;
/// Convenience method for creating a hex string.
fn to_hex_string(&self) -> String
{
let mut string = String::with_capacity(self.as_ref().len()*2);
@ -213,9 +325,11 @@ pub trait HexStringExt: Sized + AsRef<[u8]>
write!(&mut string, "{}", self.fmt_hex()).unwrap();
string
}
/// Convenience method for creating a hex string with each byte broken by a hyphen.
fn to_broken_hex_string(&self) -> String
{
let fmt = HexStringIter(
let fmt = HexStringView(
self.fmt_hex().0,
true
);
@ -224,13 +338,37 @@ pub trait HexStringExt: Sized + AsRef<[u8]>
write!(&mut string, "{}", fmt).unwrap();
string
}
/// Convenience method for creating a string from `fmt_view()`
#[inline] fn to_view_string(&self) -> String
{
format!("{}", self.fmt_view())
}
/// Convenience method for creating a string from `fmt_ascii()`
#[inline] fn to_ascii_string(&self) -> String
{
self.iter_ascii().collect()
}
}
impl<T: AsRef<[u8]>> HexStringExt for T
impl<T: AsRef<[u8]>+?Sized> HexStringExt for T
{
fn fmt_hex(&self) -> HexStringIter<'_, Self>
fn iter_hex(&self) -> HexStringIter<'_, Self>
{
HexStringIter(self.as_ref().iter(), (0,0), PhantomData)
}
fn iter_ascii(&self) -> AsciiIter<'_, Self>
{
AsciiIter(self.as_ref(), PhantomData)
}
fn fmt_ascii(&self) -> AsciiView<'_, Self>
{
AsciiView(&self)
}
fn fmt_hex(&self) -> HexStringView<'_, Self>
{
HexStringIter(&self, false)
HexStringView(&self, false)
}
fn fmt_view(&self) -> HexView<'_, Self>

Loading…
Cancel
Save