patch.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. //! Changelist
  2. //! ----------
  3. //!
  4. //! This module exposes the "changelist" object which allows 3rd party implementors to handle diffs to the virtual dom.
  5. //!
  6. //! # Design
  7. //! ---
  8. //! In essence, the changelist object connects a diff of two vdoms to the actual edits required to update the output renderer.
  9. //!
  10. //! This abstraction relies on the assumption that the final renderer accepts a tree of elements. For most target platforms,
  11. //! this is an appropriate abstraction .
  12. //!
  13. //! During the diff phase, the change list is built. Once the diff phase is over, the change list is finished and returned back
  14. //! to the renderer. The renderer is responsible for propogating the updates to the final display.
  15. //!
  16. //! Because the change list references data internal to the vdom, it needs to be consumed by the renderer before the vdom
  17. //! can continue to work. This means once a change list is generated, it should be consumed as fast as possible, otherwise the
  18. //! dom will be blocked from progressing. This is enforced by lifetimes on the returend changelist object.
  19. //!
  20. //!
  21. use bumpalo::Bump;
  22. use crate::innerlude::{Listener, ScopeIdx};
  23. use serde::{Deserialize, Serialize};
  24. /// The `Edit` represents a single modifcation of the renderer tree.
  25. /// todo@ jon: allow serde to be optional
  26. #[derive(Debug, Serialize, Deserialize)]
  27. #[serde(tag = "type")]
  28. pub enum Edit<'d> {
  29. SetText {
  30. text: &'d str,
  31. },
  32. RemoveSelfAndNextSiblings {},
  33. ReplaceWith,
  34. SetAttribute {
  35. name: &'d str,
  36. value: &'d str,
  37. },
  38. RemoveAttribute {
  39. name: &'d str,
  40. },
  41. PushReverseChild {
  42. n: u32,
  43. },
  44. PopPushChild {
  45. n: u32,
  46. },
  47. Pop,
  48. AppendChild,
  49. CreateTextNode {
  50. text: &'d str,
  51. },
  52. CreateElement {
  53. tag_name: &'d str,
  54. },
  55. CreateElementNs {
  56. tag_name: &'d str,
  57. ns: &'d str,
  58. },
  59. SaveChildrenToTemporaries {
  60. temp: u32,
  61. start: u32,
  62. end: u32,
  63. },
  64. PushChild {
  65. n: u32,
  66. },
  67. PushTemporary {
  68. temp: u32,
  69. },
  70. InsertBefore,
  71. PopPushReverseChild {
  72. n: u32,
  73. },
  74. RemoveChild {
  75. n: u32,
  76. },
  77. SetClass {
  78. class_name: &'d str,
  79. },
  80. // push a known node on to the stack
  81. TraverseToKnown {
  82. node: ScopeIdx,
  83. },
  84. // Add the current top of the stack to the known nodes
  85. MakeKnown {
  86. node: ScopeIdx,
  87. },
  88. // Remove the current top of the stack from the known nodes
  89. RemoveKnown,
  90. NewListener {
  91. event: &'d str,
  92. scope: ScopeIdx,
  93. id: usize,
  94. },
  95. UpdateListener {
  96. event: &'d str,
  97. scope: ScopeIdx,
  98. id: usize,
  99. },
  100. RemoveListener {
  101. event: &'d str,
  102. },
  103. // NewListener { event: &'d str, id: usize, s: ScopeIdx },
  104. }
  105. pub type EditList<'src> = Vec<Edit<'src>>;
  106. pub struct EditMachine<'src> {
  107. pub traversal: Traversal,
  108. next_temporary: u32,
  109. forcing_new_listeners: bool,
  110. pub emitter: EditList<'src>,
  111. }
  112. impl<'b> EditMachine<'b> {
  113. pub fn new(_bump: &'b Bump) -> Self {
  114. Self {
  115. traversal: Traversal::new(),
  116. next_temporary: 0,
  117. forcing_new_listeners: false,
  118. emitter: EditList::default(),
  119. }
  120. }
  121. }
  122. // ===================================
  123. // Traversal Methods
  124. // ===================================
  125. impl<'b> EditMachine<'b> {
  126. pub fn go_down(&mut self) {
  127. self.traversal.down();
  128. }
  129. pub fn go_down_to_child(&mut self, index: usize) {
  130. self.traversal.down();
  131. self.traversal.sibling(index);
  132. }
  133. pub fn go_down_to_reverse_child(&mut self, index: usize) {
  134. self.traversal.down();
  135. self.traversal.reverse_sibling(index);
  136. }
  137. pub fn go_up(&mut self) {
  138. self.traversal.up();
  139. }
  140. pub fn go_to_sibling(&mut self, index: usize) {
  141. self.traversal.sibling(index);
  142. }
  143. pub fn go_to_temp_sibling(&mut self, temp: u32) {
  144. self.traversal.up();
  145. self.traversal.down_to_temp(temp);
  146. }
  147. pub fn go_down_to_temp_child(&mut self, temp: u32) {
  148. self.traversal.down_to_temp(temp);
  149. }
  150. pub fn commit_traversal(&mut self) {
  151. if self.traversal.is_committed() {
  152. log::debug!("Traversal already committed");
  153. return;
  154. }
  155. for mv in self.traversal.commit() {
  156. match mv {
  157. MoveTo::Parent => {
  158. log::debug!("emit: pop");
  159. self.emitter.push(Edit::Pop {});
  160. // self.emitter.pop();
  161. }
  162. MoveTo::Child(n) => {
  163. log::debug!("emit: push_child({})", n);
  164. self.emitter.push(Edit::PushChild { n });
  165. }
  166. MoveTo::ReverseChild(n) => {
  167. log::debug!("emit: push_reverse_child({})", n);
  168. self.emitter.push(Edit::PushReverseChild { n });
  169. // self.emitter.push_reverse_child(n);
  170. }
  171. MoveTo::Sibling(n) => {
  172. log::debug!("emit: pop_push_child({})", n);
  173. self.emitter.push(Edit::PopPushChild { n });
  174. // self.emitter.pop_push_child(n);
  175. }
  176. MoveTo::ReverseSibling(n) => {
  177. log::debug!("emit: pop_push_reverse_child({})", n);
  178. self.emitter.push(Edit::PopPushReverseChild { n });
  179. }
  180. MoveTo::TempChild(temp) => {
  181. log::debug!("emit: push_temporary({})", temp);
  182. self.emitter.push(Edit::PushTemporary { temp });
  183. // self.emitter.push_temporary(temp);
  184. }
  185. }
  186. }
  187. }
  188. pub fn traversal_is_committed(&self) -> bool {
  189. self.traversal.is_committed()
  190. }
  191. }
  192. // ===================================
  193. // Stack methods
  194. // ===================================
  195. impl<'a> EditMachine<'a> {
  196. pub fn next_temporary(&self) -> u32 {
  197. self.next_temporary
  198. }
  199. pub fn set_next_temporary(&mut self, next_temporary: u32) {
  200. self.next_temporary = next_temporary;
  201. }
  202. pub fn save_children_to_temporaries(&mut self, start: usize, end: usize) -> u32 {
  203. debug_assert!(self.traversal_is_committed());
  204. debug_assert!(start < end);
  205. let temp_base = self.next_temporary;
  206. // debug!(
  207. // "emit: save_children_to_temporaries({}, {}, {})",
  208. // temp_base, start, end
  209. // );
  210. self.next_temporary = temp_base + (end - start) as u32;
  211. self.emitter.push(Edit::SaveChildrenToTemporaries {
  212. temp: temp_base,
  213. start: start as u32,
  214. end: end as u32,
  215. });
  216. temp_base
  217. }
  218. pub fn push_temporary(&mut self, temp: u32) {
  219. debug_assert!(self.traversal_is_committed());
  220. // debug!("emit: push_temporary({})", temp);
  221. self.emitter.push(Edit::PushTemporary { temp });
  222. // self.emitter.push_temporary(temp);
  223. }
  224. pub fn remove_child(&mut self, child: usize) {
  225. debug_assert!(self.traversal_is_committed());
  226. // debug!("emit: remove_child({})", child);
  227. // self.emitter.remove_child(child as u32);
  228. self.emitter.push(Edit::RemoveChild { n: child as u32 })
  229. }
  230. pub fn insert_before(&mut self) {
  231. debug_assert!(self.traversal_is_committed());
  232. // debug!("emit: insert_before()");
  233. // self.emitter.insert_before();
  234. self.emitter.push(Edit::InsertBefore {})
  235. }
  236. pub fn set_text(&mut self, text: &'a str) {
  237. debug_assert!(self.traversal_is_committed());
  238. // debug!("emit: set_text({:?})", text);
  239. // self.emitter.set_text(text);
  240. self.emitter.push(Edit::SetText { text });
  241. // .set_text(text.as_ptr() as u32, text.len() as u32);
  242. }
  243. pub fn remove_self_and_next_siblings(&mut self) {
  244. debug_assert!(self.traversal_is_committed());
  245. // debug!("emit: remove_self_and_next_siblings()");
  246. self.emitter.push(Edit::RemoveSelfAndNextSiblings {});
  247. // self.emitter.remove_self_and_next_siblings();
  248. }
  249. pub fn replace_with(&mut self) {
  250. debug_assert!(self.traversal_is_committed());
  251. // debug!("emit: replace_with()");
  252. self.emitter.push(Edit::ReplaceWith {});
  253. // self.emitter.replace_with();
  254. }
  255. pub fn set_attribute(&mut self, name: &'a str, value: &'a str, is_namespaced: bool) {
  256. debug_assert!(self.traversal_is_committed());
  257. // todo!()
  258. if name == "class" && !is_namespaced {
  259. // let class_id = self.ensure_string(value);
  260. // let class_id = self.ensure_string(value);
  261. // debug!("emit: set_class({:?})", value);
  262. // self.emitter.set_class(class_id.into());
  263. self.emitter.push(Edit::SetClass { class_name: value });
  264. } else {
  265. self.emitter.push(Edit::SetAttribute { name, value });
  266. // let name_id = self.ensure_string(name);
  267. // let value_id = self.ensure_string(value);
  268. // debug!("emit: set_attribute({:?}, {:?})", name, value);
  269. // self.state
  270. // .emitter
  271. // .set_attribute(name_id.into(), value_id.into());
  272. }
  273. }
  274. pub fn remove_attribute(&mut self, name: &'a str) {
  275. // todo!("figure out how to get this working with ensure string");
  276. self.emitter.push(Edit::RemoveAttribute { name });
  277. // self.emitter.remove_attribute(name);
  278. // debug_assert!(self.traversal_is_committed());
  279. // // debug!("emit: remove_attribute({:?})", name);
  280. // let name_id = self.ensure_string(name);
  281. // self.emitter.remove_attribute(name_id.into());
  282. }
  283. pub fn append_child(&mut self) {
  284. debug_assert!(self.traversal_is_committed());
  285. // debug!("emit: append_child()");
  286. self.emitter.push(Edit::AppendChild {});
  287. // self.emitter.append_child();
  288. }
  289. pub fn create_text_node(&mut self, text: &'a str) {
  290. debug_assert!(self.traversal_is_committed());
  291. // debug!("emit: create_text_node({:?})", text);
  292. // self.emitter.create_text_node(text);
  293. self.emitter.push(Edit::CreateTextNode { text });
  294. }
  295. pub fn create_element(&mut self, tag_name: &'a str) {
  296. // debug_assert!(self.traversal_is_committed());
  297. // debug!("emit: create_element({:?})", tag_name);
  298. // let tag_name_id = self.ensure_string(tag_name);
  299. self.emitter.push(Edit::CreateElement { tag_name });
  300. // self.emitter.create_element(tag_name);
  301. // self.emitter.create_element(tag_name_id.into());
  302. }
  303. pub fn create_element_ns(&mut self, tag_name: &'a str, ns: &'a str) {
  304. debug_assert!(self.traversal_is_committed());
  305. // debug!("emit: create_element_ns({:?}, {:?})", tag_name, ns);
  306. // let tag_name_id = self.ensure_string(tag_name);
  307. // let ns_id = self.ensure_string(ns);
  308. // self.emitter.create_element_ns(tag_name, ns);
  309. self.emitter.push(Edit::CreateElementNs { tag_name, ns });
  310. // self.emitter
  311. // .create_element_ns(tag_name_id.into(), ns_id.into());
  312. }
  313. pub fn push_force_new_listeners(&mut self) -> bool {
  314. let old = self.forcing_new_listeners;
  315. self.forcing_new_listeners = true;
  316. old
  317. }
  318. pub fn pop_force_new_listeners(&mut self, previous: bool) {
  319. debug_assert!(self.forcing_new_listeners);
  320. self.forcing_new_listeners = previous;
  321. }
  322. pub fn new_event_listener(&mut self, event: &'a str, scope: ScopeIdx, id: usize) {
  323. debug_assert!(self.traversal_is_committed());
  324. self.emitter.push(Edit::NewListener { event, scope, id });
  325. // log::debug!("emit: new_event_listener({:?})", listener);
  326. }
  327. pub fn update_event_listener(&mut self, event: &'a str, scope: ScopeIdx, id: usize) {
  328. debug_assert!(self.traversal_is_committed());
  329. if self.forcing_new_listeners {
  330. self.new_event_listener(event, scope, id);
  331. return;
  332. }
  333. self.emitter.push(Edit::NewListener { event, scope, id });
  334. }
  335. pub fn remove_event_listener(&mut self, event: &'a str) {
  336. debug_assert!(self.traversal_is_committed());
  337. self.emitter.push(Edit::RemoveListener { event });
  338. // debug!("emit: remove_event_listener({:?})", event);
  339. }
  340. // pub fn save_template(&mut self, id: CacheId) {
  341. // debug_assert!(self.traversal_is_committed());
  342. // debug_assert!(!self.has_template(id));
  343. // // debug!("emit: save_template({:?})", id);
  344. // self.templates.insert(id);
  345. // self.emitter.save_template(id.into());
  346. // }
  347. // pub fn push_template(&mut self, id: CacheId) {
  348. // debug_assert!(self.traversal_is_committed());
  349. // debug_assert!(self.has_template(id));
  350. // // debug!("emit: push_template({:?})", id);
  351. // self.emitter.push_template(id.into());
  352. // }
  353. }
  354. // Keeps track of where we are moving in a DOM tree, and shortens traversal
  355. // paths between mutations to their minimal number of operations.
  356. #[derive(Clone, Copy, Debug, PartialEq, Eq)]
  357. pub enum MoveTo {
  358. /// Move from the current node up to its parent.
  359. Parent,
  360. /// Move to the current node's n^th child.
  361. Child(u32),
  362. /// Move to the current node's n^th from last child.
  363. ReverseChild(u32),
  364. /// Move to the n^th sibling. Not relative from the current
  365. /// location. Absolute indexed within all of the current siblings.
  366. Sibling(u32),
  367. /// Move to the n^th from last sibling. Not relative from the current
  368. /// location. Absolute indexed within all of the current siblings.
  369. ReverseSibling(u32),
  370. /// Move down to the given saved temporary child.
  371. TempChild(u32),
  372. }
  373. #[derive(Debug)]
  374. pub struct Traversal {
  375. uncommitted: Vec<MoveTo>,
  376. }
  377. impl Traversal {
  378. /// Construct a new `Traversal` with its internal storage backed by the
  379. /// given bump arena.
  380. pub fn new() -> Traversal {
  381. Traversal {
  382. uncommitted: Vec::with_capacity(32),
  383. }
  384. }
  385. /// Move the traversal up in the tree.
  386. pub fn up(&mut self) {
  387. match self.uncommitted.last() {
  388. Some(MoveTo::Sibling(_)) | Some(MoveTo::ReverseSibling(_)) => {
  389. self.uncommitted.pop();
  390. self.uncommitted.push(MoveTo::Parent);
  391. }
  392. Some(MoveTo::TempChild(_)) | Some(MoveTo::Child(_)) | Some(MoveTo::ReverseChild(_)) => {
  393. self.uncommitted.pop();
  394. // And we're back at the parent.
  395. }
  396. _ => {
  397. self.uncommitted.push(MoveTo::Parent);
  398. }
  399. }
  400. }
  401. /// Move the traversal down in the tree to the first child of the current
  402. /// node.
  403. pub fn down(&mut self) {
  404. if let Some(&MoveTo::Parent) = self.uncommitted.last() {
  405. self.uncommitted.pop();
  406. self.sibling(0);
  407. } else {
  408. self.uncommitted.push(MoveTo::Child(0));
  409. }
  410. }
  411. /// Move the traversal to the n^th sibling.
  412. pub fn sibling(&mut self, index: usize) {
  413. let index = index as u32;
  414. match self.uncommitted.last_mut() {
  415. Some(MoveTo::Sibling(ref mut n)) | Some(MoveTo::Child(ref mut n)) => {
  416. *n = index;
  417. }
  418. Some(MoveTo::ReverseSibling(_)) => {
  419. self.uncommitted.pop();
  420. self.uncommitted.push(MoveTo::Sibling(index));
  421. }
  422. Some(MoveTo::TempChild(_)) | Some(MoveTo::ReverseChild(_)) => {
  423. self.uncommitted.pop();
  424. self.uncommitted.push(MoveTo::Child(index))
  425. }
  426. _ => {
  427. self.uncommitted.push(MoveTo::Sibling(index));
  428. }
  429. }
  430. }
  431. /// Move the the n^th from last sibling.
  432. pub fn reverse_sibling(&mut self, index: usize) {
  433. let index = index as u32;
  434. match self.uncommitted.last_mut() {
  435. Some(MoveTo::ReverseSibling(ref mut n)) | Some(MoveTo::ReverseChild(ref mut n)) => {
  436. *n = index;
  437. }
  438. Some(MoveTo::Sibling(_)) => {
  439. self.uncommitted.pop();
  440. self.uncommitted.push(MoveTo::ReverseSibling(index));
  441. }
  442. Some(MoveTo::TempChild(_)) | Some(MoveTo::Child(_)) => {
  443. self.uncommitted.pop();
  444. self.uncommitted.push(MoveTo::ReverseChild(index))
  445. }
  446. _ => {
  447. self.uncommitted.push(MoveTo::ReverseSibling(index));
  448. }
  449. }
  450. }
  451. /// Go to the given saved temporary.
  452. pub fn down_to_temp(&mut self, temp: u32) {
  453. match self.uncommitted.last() {
  454. Some(MoveTo::Sibling(_)) | Some(MoveTo::ReverseSibling(_)) => {
  455. self.uncommitted.pop();
  456. }
  457. Some(MoveTo::Parent)
  458. | Some(MoveTo::TempChild(_))
  459. | Some(MoveTo::Child(_))
  460. | Some(MoveTo::ReverseChild(_))
  461. | None => {
  462. // Can't remove moves to parents since we rely on their stack
  463. // pops.
  464. }
  465. }
  466. self.uncommitted.push(MoveTo::TempChild(temp));
  467. }
  468. /// Are all the traversal's moves committed? That is, are there no moves
  469. /// that have *not* been committed yet?
  470. #[inline]
  471. pub fn is_committed(&self) -> bool {
  472. // is_empty is not inlined?
  473. self.uncommitted.is_empty()
  474. // self.uncommitted.len() == 0
  475. }
  476. /// Commit this traversals moves and return the optimized path from the last
  477. /// commit.
  478. #[inline]
  479. pub fn commit(&mut self) -> std::vec::Drain<'_, MoveTo> {
  480. self.uncommitted.drain(..)
  481. }
  482. #[inline]
  483. pub fn reset(&mut self) {
  484. self.uncommitted.clear();
  485. }
  486. }
  487. // pub struct Moves<'a> {
  488. // inner: std::vec::Drain<'a, MoveTo>,
  489. // }
  490. // impl Iterator for Moves<'_> {
  491. // type Item = MoveTo;
  492. // #[inline]
  493. // fn next(&mut self) -> Option<MoveTo> {
  494. // self.inner.next()
  495. // }
  496. // }
  497. #[cfg(test)]
  498. mod tests {
  499. use super::*;
  500. #[test]
  501. fn test_traversal() {
  502. fn t<F>(f: F) -> Box<dyn FnMut(&mut Traversal)>
  503. where
  504. F: 'static + FnMut(&mut Traversal),
  505. {
  506. Box::new(f) as _
  507. }
  508. for (mut traverse, expected_moves) in vec![
  509. (
  510. t(|t| {
  511. t.down();
  512. }),
  513. vec![MoveTo::Child(0)],
  514. ),
  515. (
  516. t(|t| {
  517. t.up();
  518. }),
  519. vec![MoveTo::Parent],
  520. ),
  521. (
  522. t(|t| {
  523. t.sibling(42);
  524. }),
  525. vec![MoveTo::Sibling(42)],
  526. ),
  527. (
  528. t(|t| {
  529. t.down();
  530. t.up();
  531. }),
  532. vec![],
  533. ),
  534. (
  535. t(|t| {
  536. t.down();
  537. t.sibling(2);
  538. t.up();
  539. }),
  540. vec![],
  541. ),
  542. (
  543. t(|t| {
  544. t.down();
  545. t.sibling(3);
  546. }),
  547. vec![MoveTo::Child(3)],
  548. ),
  549. (
  550. t(|t| {
  551. t.down();
  552. t.sibling(4);
  553. t.sibling(8);
  554. }),
  555. vec![MoveTo::Child(8)],
  556. ),
  557. (
  558. t(|t| {
  559. t.sibling(1);
  560. t.sibling(1);
  561. }),
  562. vec![MoveTo::Sibling(1)],
  563. ),
  564. (
  565. t(|t| {
  566. t.reverse_sibling(3);
  567. }),
  568. vec![MoveTo::ReverseSibling(3)],
  569. ),
  570. (
  571. t(|t| {
  572. t.down();
  573. t.reverse_sibling(3);
  574. }),
  575. vec![MoveTo::ReverseChild(3)],
  576. ),
  577. (
  578. t(|t| {
  579. t.down();
  580. t.reverse_sibling(3);
  581. t.up();
  582. }),
  583. vec![],
  584. ),
  585. (
  586. t(|t| {
  587. t.down();
  588. t.reverse_sibling(3);
  589. t.reverse_sibling(6);
  590. }),
  591. vec![MoveTo::ReverseChild(6)],
  592. ),
  593. (
  594. t(|t| {
  595. t.up();
  596. t.reverse_sibling(3);
  597. t.reverse_sibling(6);
  598. }),
  599. vec![MoveTo::Parent, MoveTo::ReverseSibling(6)],
  600. ),
  601. (
  602. t(|t| {
  603. t.up();
  604. t.sibling(3);
  605. t.sibling(6);
  606. }),
  607. vec![MoveTo::Parent, MoveTo::Sibling(6)],
  608. ),
  609. (
  610. t(|t| {
  611. t.sibling(3);
  612. t.sibling(6);
  613. t.up();
  614. }),
  615. vec![MoveTo::Parent],
  616. ),
  617. (
  618. t(|t| {
  619. t.reverse_sibling(3);
  620. t.reverse_sibling(6);
  621. t.up();
  622. }),
  623. vec![MoveTo::Parent],
  624. ),
  625. (
  626. t(|t| {
  627. t.down();
  628. t.down_to_temp(3);
  629. }),
  630. vec![MoveTo::Child(0), MoveTo::TempChild(3)],
  631. ),
  632. (
  633. t(|t| {
  634. t.down_to_temp(3);
  635. t.sibling(5);
  636. }),
  637. vec![MoveTo::Child(5)],
  638. ),
  639. (
  640. t(|t| {
  641. t.down_to_temp(3);
  642. t.reverse_sibling(5);
  643. }),
  644. vec![MoveTo::ReverseChild(5)],
  645. ),
  646. (
  647. t(|t| {
  648. t.down_to_temp(3);
  649. t.up();
  650. }),
  651. vec![],
  652. ),
  653. (
  654. t(|t| {
  655. t.sibling(2);
  656. t.up();
  657. t.down_to_temp(3);
  658. }),
  659. vec![MoveTo::Parent, MoveTo::TempChild(3)],
  660. ),
  661. (
  662. t(|t| {
  663. t.up();
  664. t.down_to_temp(3);
  665. }),
  666. vec![MoveTo::Parent, MoveTo::TempChild(3)],
  667. ),
  668. ] {
  669. let mut traversal = Traversal::new();
  670. traverse(&mut traversal);
  671. let actual_moves: Vec<_> = traversal.commit().collect();
  672. assert_eq!(actual_moves, expected_moves);
  673. }
  674. }
  675. }
  676. #[derive(Clone, Copy, Debug, PartialEq, Eq)]
  677. pub struct StringKey(u32);
  678. impl From<StringKey> for u32 {
  679. #[inline]
  680. fn from(key: StringKey) -> u32 {
  681. key.0
  682. }
  683. }