use core::slice;
use crate::{SmallStr, Vec};
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct Param {
key: SmallStr,
value: SmallStr,
}
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_val(&mut self, value: &str) {
self.inner.push(Param {
key: const { SmallStr::new() },
value: value.into(),
});
}
pub(super) fn push(&mut self, key: &str, value: &str) {
self.inner.push(Param {
key: key.into(),
value: value.into(),
});
}
pub(crate) fn apply_keys(&mut self, keys: &[SmallStr]) {
self.inner
.iter_mut()
.zip(keys.iter())
.for_each(|(param, key)| param.key = key.clone());
}
}
impl IntoIterator for Params {
type Item = (SmallStr, SmallStr);
type IntoIter = IntoIter<<Vec<Param> as IntoIterator>::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<I> {
inner: I,
}
impl<I> Iterator for IntoIter<I>
where
I: Iterator<Item = Param>,
{
type Item = (SmallStr, SmallStr);
#[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());
}
}