1use std::{
36 fmt::{Debug, Display, Formatter},
37 mem::{replace, take, transmute_copy},
38};
39
40use crate::{
41 arena::{Entry, EntryIndex, Id, Identifiable},
42 format::SnippetFormatter,
43 lexis::{
44 Length,
45 LineIndex,
46 Site,
47 SiteRef,
48 SiteSpan,
49 SourceCode,
50 ToSpan,
51 Token,
52 TokenBuffer,
53 TokenCount,
54 CHUNK_SIZE,
55 },
56 report::{ld_assert, ld_assert_eq, ld_unreachable, system_panic},
57 syntax::{
58 is_void_syntax,
59 Node,
60 NodeRef,
61 SyntaxError,
62 SyntaxTree,
63 VoidSyntax,
64 NON_RULE,
65 ROOT_RULE,
66 },
67 units::{
68 mutable::{
69 cursor::MutableCursor,
70 iters::{MutableCharIter, MutableErrorIter, MutableNodeIter},
71 lexis::{MutableLexisSession, SessionOutput},
72 syntax::MutableSyntaxSession,
73 watcher::VoidWatcher,
74 },
75 storage::{Cache, ChildCursor, Tree, TreeRefs},
76 CompilationUnit,
77 Watcher,
78 },
79};
80
81pub struct MutableUnit<N: Node> {
93 root: Option<Cache>,
94 tree: Tree<N>,
95 refs: TreeRefs<N>,
96 lines: LineIndex,
97 tokens: TokenCount,
98}
99
100unsafe impl<N: Node> Send for MutableUnit<N> {}
103
104unsafe impl<N: Node> Sync for MutableUnit<N> {}
110
111impl<N: Node> Drop for MutableUnit<N> {
112 fn drop(&mut self) {
113 unsafe { self.tree.free() };
114
115 self.id().clear_name();
116 }
117}
118
119impl<N: Node> Debug for MutableUnit<N> {
120 #[inline]
121 fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
122 formatter
123 .debug_struct("MutableUnit")
124 .field("id", &self.id())
125 .field("length", &self.length())
126 .finish_non_exhaustive()
127 }
128}
129
130impl<N: Node> Display for MutableUnit<N> {
131 #[inline(always)]
132 fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
133 formatter
134 .snippet(self)
135 .set_caption(format!("MutableUnit({})", self.id()))
136 .finish()
137 }
138}
139
140impl<N: Node> Identifiable for MutableUnit<N> {
141 #[inline(always)]
142 fn id(&self) -> Id {
143 self.refs.id
144 }
145}
146
147impl<N: Node> SourceCode for MutableUnit<N> {
148 type Token = N::Token;
149
150 type Cursor<'code> = MutableCursor<'code, N>;
151
152 type CharIterator<'code> = MutableCharIter<'code, N>;
153
154 fn chars(&self, span: impl ToSpan) -> Self::CharIterator<'_> {
155 let span = match span.to_site_span(self) {
156 None => panic!("Specified span is invalid."),
157
158 Some(span) => span,
159 };
160
161 unsafe { MutableCharIter::new(self, span) }
162 }
163
164 #[inline(always)]
165 fn has_chunk(&self, chunk_entry: &Entry) -> bool {
166 self.refs.chunks.contains(chunk_entry)
167 }
168
169 #[inline(always)]
170 fn get_token(&self, chunk_entry: &Entry) -> Option<Self::Token> {
171 let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
172
173 ld_assert!(
174 !chunk_cursor.is_dangling(),
175 "Dangling chunk ref in the TreeRefs repository."
176 );
177
178 Some(unsafe { chunk_cursor.token() })
179 }
180
181 #[inline(always)]
182 fn get_site(&self, chunk_entry: &Entry) -> Option<Site> {
183 let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
184
185 Some(unsafe { self.tree.site_of(chunk_cursor) })
186 }
187
188 #[inline(always)]
189 fn get_string(&self, chunk_entry: &Entry) -> Option<&str> {
190 let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
191
192 ld_assert!(
193 !chunk_cursor.is_dangling(),
194 "Dangling chunk ref in the TreeRefs repository."
195 );
196
197 Some(unsafe { chunk_cursor.string() })
198 }
199
200 #[inline(always)]
201 fn get_length(&self, chunk_entry: &Entry) -> Option<Length> {
202 let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
203
204 ld_assert!(
205 !chunk_cursor.is_dangling(),
206 "Dangling chunk ref in the References repository."
207 );
208
209 Some(*unsafe { chunk_cursor.span() })
210 }
211
212 #[inline(always)]
213 fn cursor(&self, span: impl ToSpan) -> Self::Cursor<'_> {
214 let span = match span.to_site_span(self) {
215 None => panic!("Specified span is invalid."),
216
217 Some(span) => span,
218 };
219
220 Self::Cursor::new(self, span)
221 }
222
223 #[inline(always)]
224 fn length(&self) -> Length {
225 ld_assert_eq!(
226 self.tree.code_length(),
227 self.lines.code_length(),
228 "LineIndex and Tree resynchronization.",
229 );
230
231 self.tree.code_length()
232 }
233
234 #[inline(always)]
235 fn tokens(&self) -> TokenCount {
236 self.tokens
237 }
238
239 #[inline(always)]
240 fn lines(&self) -> &LineIndex {
241 &self.lines
242 }
243}
244
245impl<N: Node> SyntaxTree for MutableUnit<N> {
246 type Node = N;
247
248 type NodeIterator<'tree> = MutableNodeIter<'tree, N>;
249
250 type ErrorIterator<'tree> = MutableErrorIter<'tree>;
251
252 #[inline(always)]
253 fn root_node_ref(&self) -> NodeRef {
254 let Some(root) = &self.root else {
255 unsafe { ld_unreachable!("Root cache unset.") };
256 };
257
258 #[cfg(debug_assertions)]
259 if root.primary_node != 0 {
260 system_panic!("Root node moved.");
261 }
262
263 let entry = unsafe { self.refs.nodes.entry_of_unchecked(root.primary_node) };
264
265 #[cfg(debug_assertions)]
266 if entry.version != 1 {
267 system_panic!("Root node moved.");
268 }
269
270 NodeRef {
271 id: self.id(),
272 entry,
273 }
274 }
275
276 #[inline(always)]
277 fn node_refs(&self) -> Self::NodeIterator<'_> {
278 MutableNodeIter {
279 id: self.id(),
280 inner: self.refs.nodes.entries(),
281 }
282 }
283
284 #[inline(always)]
285 fn error_refs(&self) -> Self::ErrorIterator<'_> {
286 MutableErrorIter {
287 id: self.id(),
288 inner: self.refs.errors.entries(),
289 }
290 }
291
292 #[inline(always)]
293 fn has_node(&self, entry: &Entry) -> bool {
294 self.refs.nodes.contains(entry)
295 }
296
297 #[inline(always)]
298 fn get_node(&self, entry: &Entry) -> Option<&Self::Node> {
299 self.refs.nodes.get(entry)
300 }
301
302 #[inline(always)]
303 fn get_node_mut(&mut self, entry: &Entry) -> Option<&mut Self::Node> {
304 self.refs.nodes.get_mut(entry)
305 }
306
307 #[inline(always)]
308 fn has_error(&self, entry: &Entry) -> bool {
309 self.refs.errors.contains(entry)
310 }
311
312 #[inline(always)]
313 fn get_error(&self, entry: &Entry) -> Option<&SyntaxError> {
314 self.refs.errors.get(entry)
315 }
316}
317
318impl<N: Node> Default for MutableUnit<N> {
319 #[inline(always)]
320 fn default() -> Self {
321 let mut tree = Tree::default();
322 let mut refs = TreeRefs::new(Id::new());
323
324 let root = Self::initial_parse(&mut tree, &mut refs);
325
326 Self {
327 root: Some(root),
328 tree,
329 refs,
330 lines: LineIndex::new(),
331 tokens: 0,
332 }
333 }
334}
335
336impl<N: Node, S: AsRef<str>> From<S> for MutableUnit<N> {
337 #[inline(always)]
338 fn from(string: S) -> Self {
339 Self::new(string)
340 }
341}
342
343impl<N: Node> CompilationUnit for MutableUnit<N> {
344 #[inline(always)]
345 fn is_mutable(&self) -> bool {
346 true
347 }
348
349 fn into_token_buffer(self) -> TokenBuffer<N::Token> {
350 let mut buffer = TokenBuffer::with_capacity(self.tokens, self.length());
351
352 let mut chunk_cursor = self.tree.first();
353
354 while !chunk_cursor.is_dangling() {
355 unsafe {
356 chunk_cursor.take_lexis(
357 &mut buffer.spans,
358 &mut buffer.tokens,
359 &mut buffer.indices,
360 &mut buffer.text,
361 )
362 };
363
364 unsafe { chunk_cursor.next() }
365 }
366
367 buffer.update_line_index();
368
369 let _ = self;
370
371 buffer
372 }
373
374 #[inline(always)]
375 fn into_mutable_unit(self) -> MutableUnit<N> {
376 self
377 }
378}
379
380impl<N: Node> MutableUnit<N> {
381 #[inline(always)]
385 pub fn new(text: impl Into<TokenBuffer<N::Token>>) -> Self {
386 let mut buffer = text.into();
387
388 let count = buffer.tokens();
389 let spans = take(&mut buffer.spans).into_iter();
390 let indices = take(&mut buffer.indices).into_iter();
391 let tokens = take(&mut buffer.tokens).into_iter();
392 let lines = take(&mut buffer.lines);
393 let mut refs = TreeRefs::with_capacity(Id::new(), count);
394
395 let mut tree = unsafe {
396 Tree::from_chunks(
397 &mut refs,
398 count,
399 spans,
400 indices,
401 tokens,
402 buffer.text.as_str(),
403 )
404 };
405
406 let root = MutableUnit::initial_parse(&mut tree, &mut refs);
407
408 Self {
409 root: Some(root),
410 tree,
411 refs,
412 lines,
413 tokens: count,
414 }
415 }
416
417 #[inline(always)]
425 pub fn write(&mut self, span: impl ToSpan, text: impl AsRef<str>) {
426 self.write_and_watch(span, text, &mut VoidWatcher)
427 }
428
429 #[inline(never)]
439 pub fn write_and_watch(
440 &mut self,
441 span: impl ToSpan,
442 text: impl AsRef<str>,
443 watcher: &mut impl Watcher,
444 ) {
445 let span = match span.to_site_span(self) {
446 None => panic!("Specified span is invalid."),
447
448 Some(span) => span,
449 };
450
451 let text = text.as_ref();
452
453 if span.is_empty() && text.is_empty() {
454 return;
455 }
456
457 unsafe { self.lines.write_unchecked(span.clone(), text) };
458
459 let cover = self.update_lexis(watcher, span, text);
460
461 ld_assert_eq!(
462 self.tree.code_length(),
463 self.lines.code_length(),
464 "LineIndex and Tree resynchronization.",
465 );
466
467 if is_void_syntax::<N>() {
468 return;
469 }
470
471 let _entry = self.update_syntax(watcher, cover);
473 }
474
475 #[inline(always)]
476 pub(super) fn tree(&self) -> &Tree<N> {
477 &self.tree
478 }
479
480 #[inline(always)]
481 pub(super) fn refs(&self) -> &TreeRefs<N> {
482 &self.refs
483 }
484
485 fn update_lexis(
486 &mut self,
487 watcher: &mut impl Watcher,
488 mut span: SiteSpan,
489 text: &str,
490 ) -> Cover<N> {
491 let mut head;
492 let mut lookback;
493 let mut tail;
494 let mut tail_offset;
495
496 match span.start == span.end {
497 false => {
498 lookback = span.start;
499 head = self.tree.lookup(&mut lookback);
500 tail_offset = span.end;
501 tail = self.tree.lookup(&mut tail_offset);
502 }
503
504 true => {
505 lookback = span.start;
506 head = self.tree.lookup(&mut lookback);
507 tail_offset = lookback;
508 tail = head;
509 }
510 }
511
512 let mut input = Vec::with_capacity(3);
513
514 match lookback > 0 {
515 true => {
516 ld_assert!(
517 !head.is_dangling(),
518 "Dangling reference with non-zero offset.",
519 );
520
521 input.push(split_left(unsafe { head.string() }, lookback));
522
523 span.start -= lookback;
524 }
525
526 false => {
527 if head.is_dangling() {
528 head = self.tree.last();
529
530 if !head.is_dangling() {
531 let head_string = unsafe { head.string() };
532 let head_span = unsafe { *head.span() };
533
534 input.push(head_string);
535
536 span.start -= head_span;
537 lookback = head_span;
538 }
539 }
540 }
541 }
542
543 if !head.is_dangling() {
544 while lookback < <N::Token as Token>::LOOKBACK {
545 ld_assert!(!head.is_dangling(), "Dangling head.",);
546
547 if unsafe { head.is_first() } {
548 break;
549 }
550
551 unsafe { head.back() };
552
553 let head_string = unsafe { head.string() };
554 let head_span = unsafe { *head.span() };
555
556 input.insert(0, head_string);
557
558 span.start -= head_span;
559 lookback += head_span;
560 }
561 }
562
563 if !text.is_empty() {
564 input.push(text);
565 }
566
567 if tail_offset > 0 {
568 ld_assert!(
569 !tail.is_dangling(),
570 "Dangling reference with non-zero offset.",
571 );
572
573 let length = unsafe { *tail.span() };
574
575 input.push(split_right(unsafe { tail.string() }, tail_offset));
576
577 span.end += length - tail_offset;
578
579 unsafe { tail.next() }
580 }
581
582 let mut product = match input.is_empty() {
583 false => unsafe { MutableLexisSession::run(text.len() / CHUNK_SIZE + 2, &input, tail) },
584
585 true => SessionOutput {
586 length: 0,
587 spans: Vec::new(),
588 indices: Vec::new(),
589 tokens: Vec::new(),
590 text: String::new(),
591 tail,
592 overlap: 0,
593 },
594 };
595
596 span.end += product.overlap;
597
598 let mut skip = 0;
599
600 loop {
601 if head.is_dangling() {
602 break;
603 }
604
605 if unsafe { head.same_chunk_as(&product.tail) } {
606 break;
607 }
608
609 let product_string = match product.indices.get(skip) {
610 Some(start_byte) => {
611 let next_index = skip + 1;
612
613 match next_index < product.indices.len() {
614 true => {
615 let end_byte = unsafe { product.indices.get_unchecked(next_index) };
616
617 unsafe { product.text.get_unchecked(*start_byte..*end_byte) }
618 }
619
620 false => unsafe { product.text.get_unchecked(*start_byte..) },
621 }
622 }
623 None => break,
624 };
625
626 let head_string = unsafe { head.string() };
627
628 if product_string == head_string {
629 let head_span = unsafe { *head.span() };
630
631 span.start += head_span;
632 product.length -= head_span;
633 skip += 1;
634
635 unsafe { head.next() };
636
637 continue;
638 }
639
640 break;
641 }
642
643 loop {
644 if product.count() == skip {
645 break;
646 }
647
648 if unsafe { head.same_chunk_as(&product.tail) } {
649 break;
650 }
651
652 let last = match product.tail.is_dangling() {
653 false => {
654 let mut previous = product.tail;
655
656 unsafe { previous.back() };
657
658 previous
659 }
660
661 true => self.tree.last(),
662 };
663
664 if last.is_dangling() {
665 break;
666 }
667
668 let product_string = match product.indices.last() {
669 Some(start_byte) => unsafe { product.text.as_str().get_unchecked(*start_byte..) },
670 None => break,
671 };
672
673 let last_string = unsafe { last.string() };
674
675 if product_string == last_string {
676 let last_span = unsafe { *last.span() };
677
678 span.end -= last_span;
679
680 let _ = product.spans.pop();
681 let index = product.indices.pop();
682 let _ = product.tokens.pop();
683
684 if let Some(index) = index {
685 unsafe { product.text.as_mut_vec().set_len(index) };
686 }
687 product.length -= last_span;
688 product.tail = last;
689
690 continue;
691 }
692
693 break;
694 }
695
696 if head.is_dangling() {
697 ld_assert!(
698 product.tail.is_dangling(),
699 "Dangling head and non-dangling tail.",
700 );
701
702 let token_count = product.count() - skip;
703
704 let tail_tree = unsafe {
705 Tree::from_chunks(
706 &mut self.refs,
707 token_count,
708 product.spans.into_iter().skip(skip),
709 product.indices.into_iter().skip(skip),
710 product.tokens.into_iter().skip(skip),
711 product.text.as_str(),
712 )
713 };
714
715 let insert_span = tail_tree.code_length();
716
717 unsafe { self.tree.join(&mut self.refs, tail_tree) };
718
719 self.tokens += token_count;
720
721 let chunk_cursor = {
722 let mut point = span.start;
723
724 let chunk_cursor = self.tree.lookup(&mut point);
725
726 ld_assert_eq!(point, 0, "Bad span alignment.");
727
728 chunk_cursor
729 };
730
731 return Cover {
732 chunk_cursor,
733 span: span.start..(span.start + insert_span),
734 };
735 }
736
737 let insert_count = product.count() - skip;
738
739 if let Some(remove_count) = unsafe { head.continuous_to(&product.tail) } {
740 if unsafe { self.tree.is_writeable(&head, remove_count, insert_count) } {
741 let (chunk_cursor, insert_span) = unsafe {
742 self.tree.write(
743 &mut self.refs,
744 watcher,
745 head,
746 remove_count,
747 insert_count,
748 product.spans.into_iter().skip(skip),
749 unsafe { product.indices.get_unchecked(skip..) },
750 product.tokens.into_iter().skip(skip),
751 product.text.as_str(),
752 )
753 };
754
755 self.tokens += insert_count;
756 self.tokens -= remove_count;
757
758 return Cover {
759 chunk_cursor,
760 span: span.start..(span.start + insert_span),
761 };
762 }
763 }
764
765 let mut middle = unsafe { self.tree.split(&mut self.refs, head) };
766
767 let middle_split_point = {
768 let mut point = span.end - span.start;
769
770 let chunk_cursor = middle.lookup(&mut point);
771
772 ld_assert_eq!(point, 0, "Bad span alignment.");
773
774 chunk_cursor
775 };
776
777 let right = unsafe { middle.split(&mut self.refs, middle_split_point) };
778
779 let remove_count;
780 let insert_span;
781
782 {
783 let replacement = unsafe {
784 Tree::from_chunks(
785 &mut self.refs,
786 insert_count,
787 product.spans.into_iter().skip(skip),
788 product.indices.into_iter().skip(skip),
789 product.tokens.into_iter().skip(skip),
790 product.text.as_str(),
791 )
792 };
793
794 insert_span = replacement.code_length();
795
796 remove_count = unsafe {
797 replace(&mut middle, replacement).free_as_subtree(&mut self.refs, watcher)
798 };
799 };
800
801 unsafe { self.tree.join(&mut self.refs, middle) };
802 unsafe { self.tree.join(&mut self.refs, right) };
803
804 self.tokens += insert_count;
805 self.tokens -= remove_count;
806
807 head = {
808 let mut point = span.start;
809
810 let chunk_cursor = self.tree.lookup(&mut point);
811
812 ld_assert_eq!(point, 0, "Bad span alignment.");
813
814 chunk_cursor
815 };
816
817 Cover {
818 chunk_cursor: head,
819 span: span.start..(span.start + insert_span),
820 }
821 }
822
823 fn update_syntax(&mut self, watcher: &mut impl Watcher, mut cover: Cover<N>) -> EntryIndex {
824 #[allow(unused_variables)]
825 let mut cover_lookahead = 0;
826
827 loop {
828 let mut shift;
829 let mut rule;
830
831 match cover.chunk_cursor.is_dangling() {
832 false => match unsafe { cover.chunk_cursor.is_first() } {
833 true => match unsafe { cover.chunk_cursor.cache().is_some() } {
834 false => {
835 shift = 0;
836 rule = ROOT_RULE;
837 }
838
839 true => {
840 shift = 0;
841 rule = NON_RULE
842 }
843 },
844
845 false => {
846 unsafe { cover.chunk_cursor.back() };
847
848 shift = unsafe { *cover.chunk_cursor.span() };
849
850 rule = NON_RULE;
851 }
852 },
853
854 true => match self.tree.code_length() == 0 {
855 true => {
856 shift = 0;
857 rule = ROOT_RULE;
858 }
859
860 false => {
861 cover.chunk_cursor = self.tree.last();
862
863 shift = unsafe { *cover.chunk_cursor.span() };
864
865 rule = NON_RULE;
866 }
867 },
868 }
869
870 if rule != ROOT_RULE {
871 loop {
872 {
873 match unsafe { cover.chunk_cursor.cache() } {
874 None => {
875 unsafe { cover.chunk_cursor.back() };
876
877 match cover.chunk_cursor.is_dangling() {
878 false => {
879 shift += unsafe { *cover.chunk_cursor.span() };
880 continue;
881 }
882
883 true => {
884 rule = ROOT_RULE;
885 break;
886 }
887 }
888 }
889
890 Some(cache) => {
891 let parse_end_site =
892 unsafe { cache.end_site(&self.tree, &self.refs) };
893
894 if let Some(parse_end_site) = parse_end_site {
895 if parse_end_site + cache.lookahead < cover.span.start {
896 unsafe { cover.chunk_cursor.back() };
897
898 match cover.chunk_cursor.is_dangling() {
899 false => {
900 shift += unsafe { *cover.chunk_cursor.span() };
901 continue;
902 }
903
904 true => {
905 rule = ROOT_RULE;
906 break;
907 }
908 }
909 }
910
911 if parse_end_site >= cover.span.end {
912 cover.span.start -= shift;
913 cover.span.end = parse_end_site;
914
915 #[allow(unused_assignments)]
916 {
917 cover_lookahead = cache.lookahead;
918 }
919
920 rule = cache.rule;
921 break;
922 }
923 }
924 }
925 }
926 }
927
928 let cache = unsafe { cover.chunk_cursor.release_cache() };
929
930 cache.free(&mut self.refs, watcher);
931 }
932 }
933
934 if rule == ROOT_RULE {
935 let head = self.tree.first();
936
937 let Some(root_cache) = take(&mut self.root) else {
938 unsafe { ld_unreachable!("Missing root cache.") }
939 };
940
941 let (rule, primary_node) = root_cache.free_inner(&mut self.refs, watcher);
942
943 #[cfg(debug_assertions)]
944 if rule != ROOT_RULE {
945 system_panic!("Root cache refers non-root rule.");
946 }
947
948 let (root_cache, mut parse_end_site) = unsafe {
949 MutableSyntaxSession::run(
950 &mut self.tree,
951 &mut self.refs,
952 watcher,
953 0,
954 head,
955 rule,
956 primary_node,
957 )
958 };
959
960 self.root = Some(root_cache);
961
962 if self.tree.code_length() > 0 {
963 let mut tail = self.tree.lookup(&mut parse_end_site);
964
965 ld_assert_eq!(parse_end_site, 0, "Incorrect span alignment.");
966
967 while !tail.is_dangling() {
968 let has_cache = unsafe { tail.cache().is_some() };
969
970 if has_cache {
971 unsafe { tail.release_cache() }.free(&mut self.refs, watcher);
972 }
973
974 unsafe { tail.next() }
975 }
976 }
977
978 return primary_node;
979 }
980
981 let cache = unsafe { cover.chunk_cursor.release_cache() };
982
983 let (rule, primary_node) = cache.free_inner(&mut self.refs, watcher);
984
985 let (cache, parse_end_site) = unsafe {
986 MutableSyntaxSession::run(
987 &mut self.tree,
988 &mut self.refs,
989 watcher,
990 cover.span.start,
991 cover.chunk_cursor,
992 rule,
993 primary_node,
994 )
995 };
996
997 unsafe { cover.chunk_cursor.install_cache(cache) }
998
999 if cover.span.end == parse_end_site {
1001 return primary_node;
1002 }
1003
1004 cover.span.end = cover.span.end.max(parse_end_site);
1005 }
1006 }
1007
1008 #[inline(always)]
1011 fn initial_parse<'unit>(tree: &'unit mut Tree<N>, refs: &'unit mut TreeRefs<N>) -> Cache {
1012 if is_void_syntax::<N>() {
1013 let primary_node = refs.nodes.insert_raw(unsafe {
1014 transmute_copy::<VoidSyntax<<N as Node>::Token>, N>(&VoidSyntax::default())
1015 });
1016
1017 return Cache {
1018 rule: ROOT_RULE,
1019 parse_end: SiteRef::nil(),
1020 lookahead: 0,
1021 primary_node,
1022 secondary_nodes: Vec::new(),
1023 errors: Vec::new(),
1024 };
1025 }
1026
1027 let head = tree.first();
1028
1029 let primary_node = refs.nodes.reserve_entry();
1030
1031 let (root_cache, _parsed_end_site) = unsafe {
1032 MutableSyntaxSession::run(
1033 tree,
1034 refs,
1035 &mut VoidWatcher,
1036 0,
1037 head,
1038 ROOT_RULE,
1039 primary_node,
1040 )
1041 };
1042
1043 root_cache
1044 }
1045}
1046
1047impl<T: Token> TokenBuffer<T> {
1048 #[inline(always)]
1053 pub fn into_mutable_unit<N>(self) -> MutableUnit<N>
1054 where
1055 N: Node<Token = T>,
1056 {
1057 MutableUnit::new(self)
1058 }
1059}
1060
1061struct Cover<N: Node> {
1062 chunk_cursor: ChildCursor<N>,
1063 span: SiteSpan,
1064}
1065
1066#[inline]
1067fn split_left(string: &str, mut site: Site) -> &str {
1068 if site == 0 {
1069 return "";
1070 }
1071
1072 for (index, _) in string.char_indices() {
1073 if site == 0 {
1074 return unsafe { string.get_unchecked(0..index) };
1075 }
1076
1077 site -= 1;
1078 }
1079
1080 string
1081}
1082
1083#[inline]
1084fn split_right(string: &str, mut site: Site) -> &str {
1085 if site == 0 {
1086 return string;
1087 }
1088
1089 for (index, _) in string.char_indices() {
1090 if site == 0 {
1091 return unsafe { string.get_unchecked(index..string.len()) };
1092 }
1093
1094 site -= 1;
1095 }
1096
1097 ""
1098}