use std::fmt;
use std::io::{self, Cursor};
use std::ops::{Deref, DerefMut};
use http::uri::Authority;
pub(crate) fn find_crlf(b: &[u8]) -> Option<usize> {
let cr = b.iter().position(|c| *c == b'\r')?;
let maybe_lf = b.get(cr + 1)?;
if *maybe_lf == b'\n' {
Some(cr)
} else {
None
}
}
pub(crate) fn compare_lowercase_ascii(a: &str, lowercased: &str) -> bool {
if a.len() != lowercased.len() {
return false;
}
for (a, b) in a.chars().zip(lowercased.chars()) {
if !a.is_ascii() {
return false;
}
let norm = a.to_ascii_lowercase();
if norm != b {
return false;
}
}
true
}
pub(crate) struct Writer<'a>(pub Cursor<&'a mut [u8]>);
impl<'a> Writer<'a> {
pub(crate) fn new(output: &'a mut [u8]) -> Writer<'a> {
Self(Cursor::new(output))
}
pub fn len(&self) -> usize {
self.0.position() as usize
}
pub fn available(&self) -> usize {
self.0.get_ref().len() - self.len()
}
pub(crate) fn try_write(&mut self, block: impl Fn(&mut Self) -> io::Result<()>) -> bool {
let pos = self.0.position();
let success = (block)(self).is_ok();
if !success {
self.0.set_position(pos);
}
success
}
}
impl<'a> io::Write for Writer<'a> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.0.flush()
}
}
const CHARS_PER_ROW: usize = 16;
impl<'a> Drop for Writer<'a> {
fn drop(&mut self) {
let len = self.len();
log_data(&self.0.get_ref()[..len]);
}
}
pub(crate) fn log_data(data: &[u8]) {
for row in data.chunks(CHARS_PER_ROW) {
trace!("{:?}", Row(row))
}
}
struct Row<'a>(&'a [u8]);
impl<'a> fmt::Debug for Row<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for i in 0..CHARS_PER_ROW {
if let Some(v) = self.0.get(i) {
write!(f, "{}", HEX[*v as usize])?
} else {
write!(f, "--")?;
}
if i % 2 == 1 {
write!(f, " ")?;
}
}
write!(f, " ")?;
for i in 0..CHARS_PER_ROW {
if let Some(v) = self.0.get(i) {
if v.is_ascii_alphanumeric() || v.is_ascii_punctuation() {
write!(f, "{}", *v as char)?;
} else {
write!(f, ".")?;
}
} else {
write!(f, ".")?;
}
}
Ok(())
}
}
const HEX: [&str; 256] = [
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
];
pub struct ArrayVec<T, const N: usize> {
len: usize,
arr: [T; N],
}
impl<T, const N: usize> Deref for ArrayVec<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.arr[..self.len]
}
}
impl<T, const N: usize> DerefMut for ArrayVec<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.arr[..self.len]
}
}
impl<T, const N: usize> ArrayVec<T, N> {
pub fn from_fn(cb: impl FnMut(usize) -> T) -> Self {
Self {
len: 0,
arr: std::array::from_fn(cb),
}
}
pub fn push(&mut self, value: T) {
self.arr[self.len] = value;
self.len += 1;
}
pub fn truncate(&mut self, len: usize) {
assert!(len <= self.len);
self.len = len;
}
}
impl<T, const N: usize> fmt::Debug for ArrayVec<T, N>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ArrayVec")
.field("len", &self.len)
.field("arr", &&self.arr[..self.len])
.finish()
}
}
impl<'a, T, const N: usize> IntoIterator for &'a ArrayVec<T, N> {
type Item = &'a T;
type IntoIter = core::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self[..self.len].iter()
}
}
pub(crate) trait AuthorityExt {
fn userinfo(&self) -> Option<&str>;
fn username(&self) -> Option<&str>;
fn password(&self) -> Option<&str>;
}
impl AuthorityExt for Authority {
fn userinfo(&self) -> Option<&str> {
let s = self.as_str();
s.rfind('@').map(|i| &s[..i])
}
fn username(&self) -> Option<&str> {
self.userinfo()
.map(|a| a.rfind(':').map(|i| &a[..i]).unwrap_or(a))
}
fn password(&self) -> Option<&str> {
self.userinfo()
.and_then(|a| a.rfind(':').map(|i| &a[i + 1..]))
}
}