use std::borrow::Cow;
use std::collections::BTreeSet;
use crate::cookie::parse::ParseError;
use crate::{Cookie, StringPrison};
pub use self::changed::CookieChange;
mod changed;
mod parse;
#[derive(Debug, Clone, Default)]
pub struct CookieJar<'a> {
prison: Option<StringPrison<'a>>,
cookie: BTreeSet<Cookie<'a>>,
changes: BTreeSet<CookieChange<'a>>,
}
impl<'a> CookieJar<'a> {
pub fn new(cookie: impl IntoIterator<Item = Cookie<'a>>) -> Self {
Self {
cookie: cookie.into_iter().collect(),
..Default::default()
}
}
pub fn get(&self, name: &str) -> Option<&Cookie<'a>> {
match self.changes.iter().find(|c| c.name() == name) {
Some(change) => change.cookie(),
None => self.cookie.iter().find(|c| c.name() == name),
}
}
pub fn add<C: Into<Cookie<'a>>>(&mut self, cookie: C) {
self.changes.replace(CookieChange::create(cookie.into()));
}
pub fn set<C: Into<Cookie<'a>>>(&mut self, cookie: C) {
self.add(cookie);
}
pub fn remove<N: Into<Cow<'a, str>>>(&mut self, name: N) {
self.changes.replace(CookieChange::remove(name.into()));
}
pub fn cookie(&self) -> impl Iterator<Item = &Cookie<'a>> + '_ {
self.changes.iter().filter_map(|c| c.cookie()).chain(
self.cookie
.iter()
.filter(|c| !self.changes.iter().any(|ch| ch.name() == c.name())),
)
}
pub fn len(&self) -> usize {
self.cookie().count()
}
pub fn is_empty(&self) -> bool {
self.cookie().next().is_none()
}
pub fn changes(&self) -> &BTreeSet<CookieChange<'a>> {
&self.changes
}
pub fn as_header_values(&self) -> Vec<String> {
self.changes.iter().map(|c| c.as_header_value()).collect()
}
}
impl std::str::FromStr for CookieJar<'_> {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s.to_owned())
}
}