#![warn(missing_docs)]
use std::{
collections::HashMap,
fmt::{Display, Formatter},
hash::{Hash, Hasher},
ops::Deref,
};
use ahash::AHashMap;
use crate::helpers::FromRequest;
#[derive(Clone, Debug)]
pub struct ByteKey(Vec<u8>);
impl ByteKey {
pub fn new(data: impl AsRef<[u8]>) -> Self {
Self(data.as_ref().to_vec())
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> {
std::str::from_utf8(&self.0)
}
}
impl Hash for ByteKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl PartialEq for ByteKey {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for ByteKey {}
impl AsRef<[u8]> for ByteKey {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Display for ByteKey {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match std::str::from_utf8(&self.0) {
Ok(s) => write!(f, "{}", s),
Err(_) => write!(f, "{:?}", self.0),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct RequestData {
inner: AHashMap<ByteKey, Vec<u8>>,
}
impl Display for RequestData {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "RequestData {{ ")?;
let mut first = true;
for (k, v) in &self.inner {
if !first {
write!(f, ", ")?;
}
write!(f, "{}: ", k)?;
match std::str::from_utf8(v) {
Ok(s) => write!(f, "{}", s)?,
Err(_) => write!(f, "{:?}", v)?,
}
first = false;
}
write!(f, " }}")
}
}
impl RequestData {
pub fn new() -> Self {
Self {
inner: AHashMap::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
inner: AHashMap::with_capacity(capacity),
}
}
pub fn insert(&mut self, key: impl AsRef<[u8]>, value: impl AsRef<[u8]>) {
let key = ByteKey::new(key);
let value = value.as_ref().to_vec();
self.inner.insert(key, value);
}
pub fn insert_owned(&mut self, key: Vec<u8>, value: Vec<u8>) {
self.inner.insert(ByteKey(key), value);
}
pub fn get(&self, key: impl AsRef<[u8]>) -> Option<String> {
let key = ByteKey::new(key);
self.inner
.get(&key)
.and_then(|data| String::from_utf8(data.clone()).ok())
}
pub fn remove(&mut self, key: impl AsRef<[u8]>) -> Option<Vec<u8>> {
let key = ByteKey::new(key);
self.inner.remove(&key)
}
pub fn contains_key(&self, key: impl AsRef<[u8]>) -> bool {
let key = ByteKey::new(key);
self.inner.contains_key(&key)
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn clear(&mut self) {
self.inner.clear();
}
pub fn iter(&self) -> impl Iterator<Item = (&[u8], &[u8])> {
self.inner.iter().map(|(k, v)| (k.as_bytes(), v.as_slice()))
}
pub fn keys(&self) -> impl Iterator<Item = &[u8]> {
self.inner.keys().map(|k| k.as_bytes())
}
pub fn values(&self) -> impl Iterator<Item = &[u8]> {
self.inner.values().map(|v| v.as_slice())
}
pub fn from_map<K, V>(map: HashMap<K, V>) -> Self
where
K: AsRef<[u8]>,
V: AsRef<[u8]>,
{
let inner = map
.into_iter()
.map(|(k, v)| (ByteKey::new(k), v.as_ref().to_vec()))
.collect();
Self { inner }
}
pub fn byte_size(&self) -> usize {
self.inner
.iter()
.map(|(k, v)| k.0.len() + v.len())
.sum::<usize>()
+ self.inner.capacity() * std::mem::size_of::<(ByteKey, Vec<u8>)>()
}
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit();
for value in self.inner.values_mut() {
value.shrink_to_fit();
}
}
}
impl IntoIterator for RequestData {
type Item = (Vec<u8>, Vec<u8>);
type IntoIter = std::iter::Map<
std::collections::hash_map::IntoIter<ByteKey, Vec<u8>>,
fn((ByteKey, Vec<u8>)) -> (Vec<u8>, Vec<u8>),
>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter().map(|(k, v)| (k.0, v))
}
}
pub struct Data<T>(T);
impl<T> Deref for Data<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: FromData> FromRequest for Data<T> {
type Error = String;
fn from_request(req: &super::HttpRequest) -> Result<Self, Self::Error> {
Ok(Self(T::from_data(&req.data)?))
}
}
pub trait FromData: Sized {
fn from_data(data: &RequestData) -> Result<Self, String>;
}