node_ref.rs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. use dioxus_core::ElementId;
  2. use crate::{
  3. node::{FromAnyValue, NodeData, NodeType, OwnedAttributeView},
  4. state::union_ordered_iter,
  5. RealNodeId,
  6. };
  7. /// A view into a [VNode] with limited access.
  8. #[derive(Debug)]
  9. pub struct NodeView<'a, V: FromAnyValue = ()> {
  10. inner: &'a NodeData<V>,
  11. mask: NodeMask,
  12. }
  13. impl<'a, V: FromAnyValue> NodeView<'a, V> {
  14. /// Create a new NodeView from a VNode, and mask.
  15. pub fn new(node: &'a NodeData<V>, view: NodeMask) -> Self {
  16. Self {
  17. inner: node,
  18. mask: view,
  19. }
  20. }
  21. /// Get the id of the node
  22. pub fn id(&self) -> Option<ElementId> {
  23. self.inner.element_id
  24. }
  25. /// Get the node id of the node
  26. pub fn node_id(&self) -> RealNodeId {
  27. self.inner.node_id
  28. }
  29. /// Get the tag of the node if the tag is enabled in the mask
  30. pub fn tag(&self) -> Option<&'a str> {
  31. self.mask
  32. .tag
  33. .then_some(match &self.inner.node_type {
  34. NodeType::Element { tag, .. } => Some(&**tag),
  35. _ => None,
  36. })
  37. .flatten()
  38. }
  39. /// Get the tag of the node if the namespace is enabled in the mask
  40. pub fn namespace(&self) -> Option<&'a str> {
  41. self.mask
  42. .namespace
  43. .then_some(match &self.inner.node_type {
  44. NodeType::Element { namespace, .. } => namespace.as_deref(),
  45. _ => None,
  46. })
  47. .flatten()
  48. }
  49. /// Get any attributes that are enabled in the mask
  50. pub fn attributes<'b>(
  51. &'b self,
  52. ) -> Option<impl Iterator<Item = OwnedAttributeView<'a, V>> + 'b> {
  53. match &self.inner.node_type {
  54. NodeType::Element { attributes, .. } => Some(
  55. attributes
  56. .iter()
  57. .filter(move |(attr, _)| self.mask.attritutes.contains_attribute(&attr.name))
  58. .map(|(attr, val)| OwnedAttributeView {
  59. attribute: attr,
  60. value: val,
  61. }),
  62. ),
  63. _ => None,
  64. }
  65. }
  66. /// Get the text if it is enabled in the mask
  67. pub fn text(&self) -> Option<&str> {
  68. self.mask
  69. .text
  70. .then_some(match &self.inner.node_type {
  71. NodeType::Text { text } => Some(&**text),
  72. _ => None,
  73. })
  74. .flatten()
  75. }
  76. /// Get the listeners if it is enabled in the mask
  77. pub fn listeners(&self) -> Option<impl Iterator<Item = &'a str> + '_> {
  78. if self.mask.listeners {
  79. match &self.inner.node_type {
  80. NodeType::Element { listeners, .. } => Some(listeners.iter().map(|l| &**l)),
  81. _ => None,
  82. }
  83. } else {
  84. None
  85. }
  86. }
  87. }
  88. /// A mask that contains a list of attributes that are visible.
  89. #[derive(PartialEq, Eq, Clone, Debug)]
  90. pub enum AttributeMask {
  91. All,
  92. /// A list of attribute names that are visible, this list must be sorted
  93. Dynamic(Vec<String>),
  94. /// A list of attribute names that are visible, this list must be sorted
  95. Static(&'static [&'static str]),
  96. }
  97. impl AttributeMask {
  98. /// A empty attribute mask
  99. pub const NONE: Self = Self::Static(&[]);
  100. fn contains_attribute(&self, attr: &str) -> bool {
  101. match self {
  102. AttributeMask::All => true,
  103. AttributeMask::Dynamic(l) => l.binary_search_by_key(&attr, |s| s.as_str()).is_ok(),
  104. AttributeMask::Static(l) => l.binary_search(&attr).is_ok(),
  105. }
  106. }
  107. /// Create a new dynamic attribute mask with a single attribute
  108. pub fn single(new: &str) -> Self {
  109. Self::Dynamic(vec![new.to_string()])
  110. }
  111. /// Ensure the attribute list is sorted.
  112. pub fn verify(&self) {
  113. match &self {
  114. AttributeMask::Static(attrs) => debug_assert!(
  115. attrs.windows(2).all(|w| w[0] < w[1]),
  116. "attritutes must be increasing"
  117. ),
  118. AttributeMask::Dynamic(attrs) => debug_assert!(
  119. attrs.windows(2).all(|w| w[0] < w[1]),
  120. "attritutes must be increasing"
  121. ),
  122. _ => (),
  123. }
  124. }
  125. /// Combine two attribute masks
  126. pub fn union(&self, other: &Self) -> Self {
  127. let new = match (self, other) {
  128. (AttributeMask::Dynamic(s), AttributeMask::Dynamic(o)) => {
  129. AttributeMask::Dynamic(union_ordered_iter(
  130. s.iter().map(|s| s.as_str()),
  131. o.iter().map(|s| s.as_str()),
  132. s.len() + o.len(),
  133. ))
  134. }
  135. (AttributeMask::Static(s), AttributeMask::Dynamic(o)) => {
  136. AttributeMask::Dynamic(union_ordered_iter(
  137. s.iter().copied(),
  138. o.iter().map(|s| s.as_str()),
  139. s.len() + o.len(),
  140. ))
  141. }
  142. (AttributeMask::Dynamic(s), AttributeMask::Static(o)) => {
  143. AttributeMask::Dynamic(union_ordered_iter(
  144. s.iter().map(|s| s.as_str()),
  145. o.iter().copied(),
  146. s.len() + o.len(),
  147. ))
  148. }
  149. (AttributeMask::Static(s), AttributeMask::Static(o)) => AttributeMask::Dynamic(
  150. union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
  151. ),
  152. _ => AttributeMask::All,
  153. };
  154. new.verify();
  155. new
  156. }
  157. /// Check if two attribute masks overlap
  158. fn overlaps(&self, other: &Self) -> bool {
  159. fn overlaps_iter<'a>(
  160. self_iter: impl Iterator<Item = &'a str>,
  161. mut other_iter: impl Iterator<Item = &'a str>,
  162. ) -> bool {
  163. if let Some(mut other_attr) = other_iter.next() {
  164. for self_attr in self_iter {
  165. while other_attr < self_attr {
  166. if let Some(attr) = other_iter.next() {
  167. other_attr = attr;
  168. } else {
  169. return false;
  170. }
  171. }
  172. if other_attr == self_attr {
  173. return true;
  174. }
  175. }
  176. }
  177. false
  178. }
  179. match (self, other) {
  180. (AttributeMask::All, AttributeMask::All) => true,
  181. (AttributeMask::All, AttributeMask::Dynamic(v)) => !v.is_empty(),
  182. (AttributeMask::All, AttributeMask::Static(s)) => !s.is_empty(),
  183. (AttributeMask::Dynamic(v), AttributeMask::All) => !v.is_empty(),
  184. (AttributeMask::Static(s), AttributeMask::All) => !s.is_empty(),
  185. (AttributeMask::Dynamic(v1), AttributeMask::Dynamic(v2)) => {
  186. overlaps_iter(v1.iter().map(|s| s.as_str()), v2.iter().map(|s| s.as_str()))
  187. }
  188. (AttributeMask::Dynamic(v), AttributeMask::Static(s)) => {
  189. overlaps_iter(v.iter().map(|s| s.as_str()), s.iter().copied())
  190. }
  191. (AttributeMask::Static(s), AttributeMask::Dynamic(v)) => {
  192. overlaps_iter(v.iter().map(|s| s.as_str()), s.iter().copied())
  193. }
  194. (AttributeMask::Static(s1), AttributeMask::Static(s2)) => {
  195. overlaps_iter(s1.iter().copied(), s2.iter().copied())
  196. }
  197. }
  198. }
  199. }
  200. impl Default for AttributeMask {
  201. fn default() -> Self {
  202. AttributeMask::Static(&[])
  203. }
  204. }
  205. /// A mask that limits what parts of a node a dependency can see.
  206. #[derive(Default, PartialEq, Eq, Clone, Debug)]
  207. pub struct NodeMask {
  208. attritutes: AttributeMask,
  209. tag: bool,
  210. namespace: bool,
  211. text: bool,
  212. listeners: bool,
  213. }
  214. impl NodeMask {
  215. /// A node mask with no parts visible.
  216. pub const NONE: Self = Self::new();
  217. /// A node mask with every part visible.
  218. pub const ALL: Self = Self::new_with_attrs(AttributeMask::All)
  219. .with_text()
  220. .with_element()
  221. .with_listeners();
  222. /// Check if two masks overlap
  223. pub fn overlaps(&self, other: &Self) -> bool {
  224. (self.tag && other.tag)
  225. || (self.namespace && other.namespace)
  226. || self.attritutes.overlaps(&other.attritutes)
  227. || (self.text && other.text)
  228. || (self.listeners && other.listeners)
  229. }
  230. /// Combine two node masks
  231. pub fn union(&self, other: &Self) -> Self {
  232. Self {
  233. attritutes: self.attritutes.union(&other.attritutes),
  234. tag: self.tag | other.tag,
  235. namespace: self.namespace | other.namespace,
  236. text: self.text | other.text,
  237. listeners: self.listeners | other.listeners,
  238. }
  239. }
  240. /// Create a new node mask with the given attributes
  241. pub const fn new_with_attrs(attritutes: AttributeMask) -> Self {
  242. Self {
  243. attritutes,
  244. tag: false,
  245. namespace: false,
  246. text: false,
  247. listeners: false,
  248. }
  249. }
  250. /// Create a empty node mask
  251. pub const fn new() -> Self {
  252. Self::new_with_attrs(AttributeMask::NONE)
  253. }
  254. /// Allow the mask to view the tag
  255. pub const fn with_tag(mut self) -> Self {
  256. self.tag = true;
  257. self
  258. }
  259. /// Allow the mask to view the namespace
  260. pub const fn with_namespace(mut self) -> Self {
  261. self.namespace = true;
  262. self
  263. }
  264. /// Allow the mask to view the namespace and tag
  265. pub const fn with_element(self) -> Self {
  266. self.with_namespace().with_tag()
  267. }
  268. /// Allow the mask to view the text
  269. pub const fn with_text(mut self) -> Self {
  270. self.text = true;
  271. self
  272. }
  273. /// Allow the mask to view the listeners
  274. pub const fn with_listeners(mut self) -> Self {
  275. self.listeners = true;
  276. self
  277. }
  278. }