use core::slice;
use alloc::vec::{self, Vec};
use xitca_unsafe_collection::small_str::SmallBoxedStr;
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
struct Param {
key: SmallBoxedStr,
value: SmallBoxedStr,
}
impl Param {
fn key_str(&self) -> &str {
self.key.as_ref()
}
fn value_str(&self) -> &str {
self.value.as_ref()
}
}
#[derive(Clone, Debug)]
pub struct Params {
inner: Vec<Param>,
}
impl Default for Params {
fn default() -> Self {
Self::new()
}
}
impl Params {
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn get(&self, key: impl AsRef<str>) -> Option<&str> {
self.inner
.iter()
.find(|param| param.key_str() == key.as_ref())
.map(Param::value_str)
}
#[inline]
pub fn iter(&self) -> Iter<'_> {
Iter {
inner: self.inner.iter(),
}
}
}
impl Params {
pub(super) const fn new() -> Self {
Self { inner: Vec::new() }
}
pub(super) fn truncate(&mut self, n: usize) {
self.inner.truncate(n)
}
pub(super) fn push(&mut self, key: &str, value: &str) {
self.inner.push(Param {
key: key.into(),
value: value.into(),
});
}
pub(crate) fn for_each_key_mut(&mut self, f: impl Fn((usize, &mut SmallBoxedStr))) {
self.inner
.iter_mut()
.map(|param| &mut param.key)
.enumerate()
.for_each(f);
}
}
impl IntoIterator for Params {
type Item = (SmallBoxedStr, SmallBoxedStr);
type IntoIter = IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.inner.into_iter(),
}
}
}
pub struct Iter<'a> {
inner: slice::Iter<'a, Param>,
}
impl<'a> Iterator for Iter<'a> {
type Item = (&'a str, &'a str);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|p| (p.key.as_ref(), p.value.as_ref()))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
pub struct IntoIter {
inner: vec::IntoIter<Param>,
}
impl Iterator for IntoIter {
type Item = (SmallBoxedStr, SmallBoxedStr);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|p| (p.key, p.value))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_alloc() {
assert!(Params::new().is_empty());
}
#[test]
fn ignore_array_default() {
let params = Params::new();
assert!(params.get("").is_none());
}
}