#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct LayerSet(u8);
impl LayerSet {
pub const NAV: Self = Self(1 << 0);
pub const FORM: Self = Self(1 << 1);
pub const SESSION: Self = Self(1 << 2);
pub const DOM: Self = Self(1 << 3);
pub const VISUAL: Self = Self(1 << 4);
pub const fn empty() -> Self {
Self(0)
}
pub const fn all() -> Self {
Self(0b1_1111)
}
pub const fn contains(self, other: Self) -> bool {
self.0 & other.0 == other.0
}
pub const fn intersect(self, other: Self) -> Self {
Self(self.0 & other.0)
}
pub const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
pub const fn is_empty(self) -> bool {
self.0 == 0
}
}
impl core::ops::BitOr for LayerSet {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SameSite {
Strict,
Lax,
None,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Cookie {
pub name: String,
pub value: String,
pub domain: String,
pub path: String,
pub secure: bool,
pub http_only: bool,
pub same_site: Option<SameSite>,
pub expires: Option<f64>,
pub partitioned: bool,
}
#[derive(Clone, Debug, Default)]
pub struct FormValues(pub Vec<(String, String)>);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FrameHandle(pub u64);
#[derive(Clone, Debug, Default)]
pub struct PortableViewState {
pub url: Option<String>,
pub scroll: (f32, f32),
pub form: Option<FormValues>,
pub cookies: Vec<Cookie>,
pub dom_snapshot: Option<String>,
pub visual: Option<FrameHandle>,
}
#[derive(Clone, Debug, Default)]
pub struct BackState {
pub url: String,
pub scroll: (f32, f32),
pub form: Option<FormValues>,
pub cookies: Vec<Cookie>,
}
pub enum Carry {
Forward(PortableViewState),
Back(BackState),
}
pub trait FlipDonor {
fn donates(&self) -> LayerSet;
fn capture(&self) -> PortableViewState;
}
pub trait FlipBack {
fn extract(&self) -> BackState;
}
pub trait FlipReceiver {
fn receives(&self) -> LayerSet;
fn present(&mut self, carry: Carry);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn layerset_intersection_is_the_carried_set() {
let donor = LayerSet::all();
let receiver = LayerSet::NAV | LayerSet::SESSION | LayerSet::VISUAL;
let carried = donor.intersect(receiver);
assert!(carried.contains(LayerSet::NAV));
assert!(carried.contains(LayerSet::SESSION));
assert!(!carried.contains(LayerSet::DOM));
}
#[test]
fn empty_and_all_bound_the_lattice() {
assert!(LayerSet::empty().is_empty());
assert!(LayerSet::all().contains(LayerSet::DOM));
assert!(LayerSet::all().contains(LayerSet::VISUAL));
}
}