use bitflags::bitflags;
use serde::{Deserialize, Serialize};
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct PatchFlags: i32 {
const TEXT = 1;
const CLASS = 1 << 1;
const STYLE = 1 << 2;
const PROPS = 1 << 3;
const FULL_PROPS = 1 << 4;
const NEED_HYDRATION = 1 << 5;
const STABLE_FRAGMENT = 1 << 6;
const KEYED_FRAGMENT = 1 << 7;
const UNKEYED_FRAGMENT = 1 << 8;
const NEED_PATCH = 1 << 9;
const DYNAMIC_SLOTS = 1 << 10;
const DEV_ROOT_FRAGMENT = 1 << 11;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(i32)]
pub enum SpecialPatchFlag {
Cached = -1,
Bail = -2,
}
impl PatchFlags {
pub fn name(&self) -> &'static str {
match *self {
Self::TEXT => "TEXT",
Self::CLASS => "CLASS",
Self::STYLE => "STYLE",
Self::PROPS => "PROPS",
Self::FULL_PROPS => "FULL_PROPS",
Self::NEED_HYDRATION => "NEED_HYDRATION",
Self::STABLE_FRAGMENT => "STABLE_FRAGMENT",
Self::KEYED_FRAGMENT => "KEYED_FRAGMENT",
Self::UNKEYED_FRAGMENT => "UNKEYED_FRAGMENT",
Self::NEED_PATCH => "NEED_PATCH",
Self::DYNAMIC_SLOTS => "DYNAMIC_SLOTS",
Self::DEV_ROOT_FRAGMENT => "DEV_ROOT_FRAGMENT",
_ => "UNKNOWN",
}
}
pub fn names(&self) -> Vec<&'static str> {
let mut names = Vec::new();
if self.contains(Self::TEXT) {
names.push("TEXT");
}
if self.contains(Self::CLASS) {
names.push("CLASS");
}
if self.contains(Self::STYLE) {
names.push("STYLE");
}
if self.contains(Self::PROPS) {
names.push("PROPS");
}
if self.contains(Self::FULL_PROPS) {
names.push("FULL_PROPS");
}
if self.contains(Self::NEED_HYDRATION) {
names.push("NEED_HYDRATION");
}
if self.contains(Self::STABLE_FRAGMENT) {
names.push("STABLE_FRAGMENT");
}
if self.contains(Self::KEYED_FRAGMENT) {
names.push("KEYED_FRAGMENT");
}
if self.contains(Self::UNKEYED_FRAGMENT) {
names.push("UNKEYED_FRAGMENT");
}
if self.contains(Self::NEED_PATCH) {
names.push("NEED_PATCH");
}
if self.contains(Self::DYNAMIC_SLOTS) {
names.push("DYNAMIC_SLOTS");
}
if self.contains(Self::DEV_ROOT_FRAGMENT) {
names.push("DEV_ROOT_FRAGMENT");
}
names
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ShapeFlags: u32 {
const ELEMENT = 1;
const FUNCTIONAL_COMPONENT = 1 << 1;
const STATEFUL_COMPONENT = 1 << 2;
const TEXT_CHILDREN = 1 << 3;
const ARRAY_CHILDREN = 1 << 4;
const SLOTS_CHILDREN = 1 << 5;
const TELEPORT = 1 << 6;
const SUSPENSE = 1 << 7;
const COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8;
const COMPONENT_KEPT_ALIVE = 1 << 9;
const COMPONENT = Self::STATEFUL_COMPONENT.bits() | Self::FUNCTIONAL_COMPONENT.bits();
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u8)]
pub enum SlotFlags {
Stable = 1,
Dynamic = 2,
Forwarded = 3,
}
impl SlotFlags {
pub fn name(&self) -> &'static str {
match self {
Self::Stable => "STABLE",
Self::Dynamic => "DYNAMIC",
Self::Forwarded => "FORWARDED",
}
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct VaporVForFlags: u8 {
const FAST_REMOVE = 1;
const IS_COMPONENT = 1 << 1;
const ONCE = 1 << 2;
}
}
#[cfg(test)]
mod tests {
use super::{PatchFlags, ShapeFlags, SlotFlags};
#[test]
fn test_patch_flags() {
let flags = PatchFlags::TEXT | PatchFlags::CLASS;
assert!(flags.contains(PatchFlags::TEXT));
assert!(flags.contains(PatchFlags::CLASS));
assert!(!flags.contains(PatchFlags::STYLE));
}
#[test]
fn test_shape_flags_component() {
assert!(ShapeFlags::COMPONENT.contains(ShapeFlags::STATEFUL_COMPONENT));
assert!(ShapeFlags::COMPONENT.contains(ShapeFlags::FUNCTIONAL_COMPONENT));
}
#[test]
fn test_slot_flags() {
assert_eq!(SlotFlags::Stable.name(), "STABLE");
assert_eq!(SlotFlags::Dynamic.name(), "DYNAMIC");
}
}