node_ref.rs 9.0 KB

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