1use std::collections::{BTreeMap, BTreeSet};
2use std::fmt;
3use std::sync::Arc;
4
5use crate::configuration::ParseConfiguration;
6use crate::embedded_region_parser;
7use crate::language_catalog::{GrammarProvenance, grammar_provenance};
8use crate::language_parser::{BuiltInLanguageParser, LanguageParser};
9use crate::language_profile::LanguageProfile;
10use crate::link_flags::LinkFlags;
11use crate::mixed_regions::EmbeddedRegion;
12use crate::natural_language::annotate_natural_language;
13pub use crate::network_projection::NetworkProjection;
14use crate::query::{LinkQuery, QueryMatch, QueryPredicateHost, RejectPredicateHost};
15use crate::self_description::{SELF_DESCRIPTION_ROOTS, definition_expression};
16use crate::source::{ByteRange, Point, SourceSpan};
17use crate::substitution::{
18 SubstitutionBindings, SubstitutionReport, SubstitutionRule, VariableSubstitutionRule,
19};
20
21mod trivia;
22mod verification;
23#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub struct LinkId(pub(crate) u64);
26
27impl LinkId {
28 #[must_use]
30 pub const fn from_u64(value: u64) -> Self {
31 Self(value)
32 }
33
34 #[must_use]
36 pub const fn as_u64(self) -> u64 {
37 self.0
38 }
39}
40
41impl fmt::Display for LinkId {
42 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(formatter, "{}", self.0)
44 }
45}
46
47#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
49pub enum LinkType {
50 Link,
51 Reference,
52 Relation,
53 Language,
54 Grammar,
55 Type,
56 Concept,
57 Syntax,
58 Field,
59 Trivia,
60 Token,
61 Document,
62 Semantic,
63 Region,
64 Object,
65}
66
67impl fmt::Display for LinkType {
68 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
69 let name = match self {
70 Self::Link => "link",
71 Self::Reference => "reference",
72 Self::Relation => "relation",
73 Self::Language => "language",
74 Self::Grammar => "grammar",
75 Self::Type => "type",
76 Self::Concept => "concept",
77 Self::Syntax => "syntax",
78 Self::Field => "field",
79 Self::Trivia => "trivia",
80 Self::Token => "token",
81 Self::Document => "document",
82 Self::Semantic => "semantic",
83 Self::Region => "region",
84 Self::Object => "object",
85 };
86 formatter.write_str(name)
87 }
88}
89
90#[derive(Clone, Debug, Default, PartialEq, Eq)]
92pub struct LinkMetadata {
93 link_type: Option<LinkType>,
94 named: bool,
95 term: Option<Arc<str>>,
96 definition: Option<Arc<str>>,
97 language: Option<Arc<str>>,
98 span: Option<SourceSpan>,
99 flags: LinkFlags,
100}
101
102impl LinkMetadata {
103 #[must_use]
105 pub fn new() -> Self {
106 Self::default()
107 }
108
109 #[must_use]
111 pub const fn with_link_type(mut self, link_type: LinkType) -> Self {
112 self.link_type = Some(link_type);
113 self
114 }
115
116 #[must_use]
118 pub const fn with_named(mut self, named: bool) -> Self {
119 self.named = named;
120 self
121 }
122
123 #[must_use]
125 pub fn with_term(mut self, term: impl Into<String>) -> Self {
126 self.term = Some(Arc::from(term.into()));
127 self
128 }
129
130 #[must_use]
132 pub fn with_definition(mut self, definition: impl Into<String>) -> Self {
133 self.definition = Some(Arc::from(definition.into()));
134 self
135 }
136
137 #[must_use]
139 pub fn with_language(mut self, language: impl Into<String>) -> Self {
140 self.language = Some(Arc::from(language.into()));
141 self
142 }
143
144 #[must_use]
146 pub const fn with_span(mut self, span: SourceSpan) -> Self {
147 self.span = Some(span);
148 self
149 }
150
151 #[must_use]
153 pub const fn with_flags(mut self, flags: LinkFlags) -> Self {
154 self.flags = flags;
155 self
156 }
157
158 #[must_use]
160 pub const fn link_type(&self) -> Option<LinkType> {
161 self.link_type
162 }
163
164 #[must_use]
166 pub const fn is_named(&self) -> bool {
167 self.named
168 }
169
170 #[must_use]
172 pub fn term(&self) -> Option<&str> {
173 self.term.as_deref()
174 }
175
176 #[must_use]
178 pub fn definition(&self) -> Option<&str> {
179 self.definition.as_deref()
180 }
181
182 #[must_use]
184 pub fn language(&self) -> Option<&str> {
185 self.language.as_deref()
186 }
187
188 #[must_use]
190 pub const fn span(&self) -> Option<SourceSpan> {
191 self.span
192 }
193
194 #[must_use]
196 pub const fn flags(&self) -> LinkFlags {
197 self.flags
198 }
199}
200
201#[derive(Clone, Debug, PartialEq, Eq)]
203pub struct Link {
204 pub(crate) id: LinkId,
205 pub(crate) references: Arc<[LinkId]>,
206 pub(crate) metadata: LinkMetadata,
207}
208
209impl Link {
210 #[must_use]
212 pub const fn id(&self) -> LinkId {
213 self.id
214 }
215
216 #[must_use]
218 pub fn references(&self) -> &[LinkId] {
219 &self.references
220 }
221
222 #[must_use]
224 pub const fn metadata(&self) -> &LinkMetadata {
225 &self.metadata
226 }
227
228 const fn metadata_mut(&mut self) -> &mut LinkMetadata {
229 &mut self.metadata
230 }
231}
232
233#[derive(Clone, Debug, Default, PartialEq, Eq)]
235pub struct LinkNetwork {
236 pub(crate) next_id: u64,
237 pub(crate) links: BTreeMap<LinkId, Arc<Link>>,
238 pub(crate) terms: BTreeMap<Arc<str>, LinkId>,
239 pub(crate) concept_syntax: BTreeMap<(Arc<str>, Arc<str>), Arc<str>>,
240 pub(crate) strings: BTreeSet<Arc<str>>,
241}
242
243impl LinkNetwork {
244 #[must_use]
246 pub const fn new() -> Self {
247 Self {
248 next_id: 1,
249 links: BTreeMap::new(),
250 terms: BTreeMap::new(),
251 concept_syntax: BTreeMap::new(),
252 strings: BTreeSet::new(),
253 }
254 }
255
256 #[must_use]
258 pub fn self_describing() -> Self {
259 let mut network = Self::new();
260 for root in SELF_DESCRIPTION_ROOTS {
261 let definition = definition_expression(root.term, root.references);
262 network.insert_typed_point(root.term, root.link_type, Some(&definition));
263 }
264
265 for root in SELF_DESCRIPTION_ROOTS {
266 let mut references = Vec::with_capacity(root.references.len() + 1);
267 references.push(
268 network
269 .find_term(root.term)
270 .expect("seeded self-description root exists"),
271 );
272 for reference in root.references {
273 references.push(
274 network
275 .find_term(reference)
276 .expect("seeded self-description reference exists"),
277 );
278 }
279
280 network.insert_dynamic_link(
281 &references,
282 LinkMetadata::new().with_link_type(LinkType::Relation),
283 );
284 }
285
286 network
287 }
288
289 #[must_use]
291 pub fn self_description_text(&self) -> String {
292 let mut output = String::new();
293 for root in SELF_DESCRIPTION_ROOTS {
294 let Some(id) = self.find_term(root.term) else {
295 continue;
296 };
297 let Some(definition) = self.definition_for(id) else {
298 continue;
299 };
300 output.push_str(definition);
301 output.push('\n');
302 }
303 output
304 }
305
306 #[must_use]
312 pub fn parse(text: &str, language: &str, configuration: ParseConfiguration) -> Self {
313 let mut network = BuiltInLanguageParser.parse_source(text, language, configuration);
314 if text.contains('\0') {
315 let retained = network.reconstruct_text();
316 if text.starts_with(&retained) && retained.len() < text.len() {
317 let span = SourceSpan::new(
318 ByteRange::new(retained.len(), text.len()),
319 end_point_for_text(&retained),
320 end_point_for_text(text),
321 );
322 network.insert_link(
323 [],
324 LinkMetadata::new()
325 .with_link_type(LinkType::Token)
326 .with_named(false)
327 .with_term(&text[retained.len()..])
328 .with_language(language)
329 .with_span(span)
330 .with_flags(LinkFlags::error()),
331 );
332 }
333 let malformed_root = network
334 .links()
335 .filter(|link| {
336 link.metadata().link_type() == Some(LinkType::Syntax)
337 && link
338 .metadata()
339 .span()
340 .is_some_and(|span| span.byte_range().start() == 0)
341 })
342 .max_by_key(|link| {
343 link.metadata()
344 .span()
345 .map_or(0, |span| span.byte_range().end())
346 })
347 .map(Link::id);
348 if let Some(root) = malformed_root {
349 let flags = network
352 .link(root)
353 .map_or_else(LinkFlags::clean, |link| link.metadata().flags());
354 network.set_flags(root, flags.with_containing_error());
355 network.set_span(
356 root,
357 SourceSpan::new(
358 ByteRange::new(0, text.len()),
359 Point::new(0, 0),
360 end_point_for_text(text),
361 ),
362 );
363 }
364 }
365 if let Some(profile) = configuration.profile().and_then(LanguageProfile::builtin) {
366 profile.declare_in(&mut network);
367 }
368 network
369 }
370
371 #[must_use]
377 pub fn parse_lossless_text(
378 text: &str,
379 language: &str,
380 configuration: ParseConfiguration,
381 ) -> Self {
382 let (mut network, document) = Self::new_parse_document(text, language);
383
384 let mut row = 0;
385 let mut column = 0;
386 let mut open_parentheses = Vec::new();
387 for (start, character) in text.char_indices() {
388 let start_point = Point::new(row, column);
389 let end = start + character.len_utf8();
390 if character == '\n' {
391 row += 1;
392 column = 0;
393 } else {
394 column += character.len_utf8();
396 }
397 let end_point = Point::new(row, column);
398 let span = SourceSpan::new(ByteRange::new(start, end), start_point, end_point);
399 let mut metadata = LinkMetadata::new()
400 .with_link_type(LinkType::Token)
401 .with_named(!character.is_whitespace())
402 .with_term(character.to_string())
403 .with_language(language)
404 .with_span(span);
405
406 if character.is_whitespace() {
407 metadata = metadata.with_flags(LinkFlags::extra());
408 }
409
410 let token = network.insert_link([document], metadata);
411 match character {
412 '(' => open_parentheses.push(token),
413 ')' if open_parentheses.pop().is_none() => {
414 network.set_flags(token, LinkFlags::error());
415 }
416 _ => {}
417 }
418 if character.is_whitespace() {
419 network.attach_trivia(
420 document,
421 token,
422 span,
423 configuration.trivia_attachment_policy(),
424 );
425 }
426 }
427
428 let missing_span = SourceSpan::new(
429 ByteRange::new(text.len(), text.len()),
430 end_point_for_text(text),
431 end_point_for_text(text),
432 );
433 for open_parenthesis in open_parentheses {
434 network.set_flags(open_parenthesis, LinkFlags::containing_error());
435 network.insert_link(
436 [document],
437 LinkMetadata::new()
438 .with_link_type(LinkType::Token)
439 .with_named(false)
440 .with_term(")")
441 .with_language(language)
442 .with_span(missing_span)
443 .with_flags(LinkFlags::missing()),
444 );
445 }
446
447 network.attach_embedded_regions(document, text, language, configuration);
448 annotate_natural_language(&mut network, document, text, language, configuration);
449
450 network
451 }
452
453 pub(crate) fn new_parse_document(text: &str, language: &str) -> (Self, LinkId) {
454 let mut network = Self::self_describing();
455 let language_link = network.insert_typed_point(language, LinkType::Language, None);
456 network.record_grammars(language_link, language);
457 let document_span = SourceSpan::new(
458 ByteRange::new(0, text.len()),
459 Point::new(0, 0),
460 end_point_for_text(text),
461 );
462 let document = network.insert_link(
463 [language_link],
464 LinkMetadata::new()
465 .with_link_type(LinkType::Document)
466 .with_named(true)
467 .with_term(format!("{language} document"))
468 .with_language(language)
469 .with_span(document_span),
470 );
471 (network, document)
472 }
473
474 #[must_use]
476 pub fn len(&self) -> usize {
477 self.links.len()
478 }
479
480 #[must_use]
482 pub fn is_empty(&self) -> bool {
483 self.links.is_empty()
484 }
485
486 #[must_use]
488 pub fn shared_link_count(&self, id: LinkId) -> Option<usize> {
489 self.links.get(&id).map(Arc::strong_count)
490 }
491
492 #[must_use]
494 pub fn interned_string_count(&self, value: &str) -> Option<usize> {
495 self.strings.get(value).map(Arc::strong_count)
496 }
497
498 pub fn links(&self) -> impl Iterator<Item = &Link> {
500 self.links.values().map(Arc::as_ref)
501 }
502
503 pub fn projected_links(&self, projection: NetworkProjection) -> impl Iterator<Item = &Link> {
505 self.links().filter(move |link| projection.includes(link))
506 }
507
508 #[must_use]
510 pub fn reconstruct_text(&self) -> String {
511 let mut tokens = self
512 .links()
513 .filter(|link| link.metadata().link_type() == Some(LinkType::Token))
514 .filter(|link| !link.metadata().flags().is_missing())
515 .filter_map(|link| {
516 Some((
517 link.metadata().span()?.byte_range(),
518 link.id().as_u64(),
519 link.metadata().term()?.to_string(),
520 ))
521 })
522 .collect::<Vec<_>>();
523
524 tokens.sort_by_key(|(range, id, _term)| (range.start(), *id));
525 let mut reconstructed = String::new();
526 let mut covered_until = 0;
527 for (range, _id, term) in tokens {
528 if range.start() < covered_until {
529 continue;
530 }
531 reconstructed.push_str(&term);
532 covered_until = range.end();
533 }
534 reconstructed
535 }
536
537 #[must_use]
539 pub fn embedded_regions(&self) -> Vec<EmbeddedRegion> {
540 self.links()
541 .filter(|link| link.metadata().link_type() == Some(LinkType::Region))
542 .filter_map(|link| {
543 Some(EmbeddedRegion::new(
544 link.metadata().language()?.to_string(),
545 link.metadata().span()?,
546 ))
547 })
548 .collect()
549 }
550
551 #[must_use]
553 pub fn query_links(&self, query: &LinkQuery) -> Vec<&Link> {
554 self.query_matches(query)
555 .into_iter()
556 .filter_map(|query_match| self.link(query_match.link_id()))
557 .collect()
558 }
559
560 #[must_use]
562 pub fn query_matches(&self, query: &LinkQuery) -> Vec<QueryMatch> {
563 self.query_matches_with(query, &RejectPredicateHost)
564 }
565
566 #[must_use]
568 pub fn query_matches_with(
569 &self,
570 query: &LinkQuery,
571 predicate_host: &impl QueryPredicateHost,
572 ) -> Vec<QueryMatch> {
573 self.links()
574 .flat_map(|link| query.matches_in_network(self, link, predicate_host))
575 .collect()
576 }
577
578 pub fn insert_point(&mut self, term: &str) -> LinkId {
580 self.insert_typed_point(term, LinkType::Concept, None)
581 }
582
583 pub fn insert_object(&mut self, term: &str) -> LinkId {
585 self.insert_typed_point(term, LinkType::Object, None)
586 }
587
588 pub fn insert_relation<const N: usize>(
590 &mut self,
591 references: [LinkId; N],
592 link_type: LinkType,
593 span: SourceSpan,
594 ) -> LinkId {
595 self.insert_link(
596 references,
597 LinkMetadata::new()
598 .with_link_type(link_type)
599 .with_span(span),
600 )
601 }
602
603 pub fn insert_field(&mut self, parent: LinkId, label: &str, child: LinkId) -> LinkId {
605 let label_link = self.insert_typed_point(
606 label,
607 LinkType::Field,
608 Some("A field label names a relation between links."),
609 );
610 self.insert_link(
611 [parent, label_link, child],
612 LinkMetadata::new().with_link_type(LinkType::Field),
613 )
614 }
615
616 pub fn insert_link<const N: usize>(
618 &mut self,
619 references: [LinkId; N],
620 metadata: LinkMetadata,
621 ) -> LinkId {
622 let id = self.allocate_id();
623 let metadata = self.intern_metadata(metadata);
624 self.links.insert(
625 id,
626 Arc::new(Link {
627 id,
628 references: Arc::from(references.to_vec()),
629 metadata,
630 }),
631 );
632 id
633 }
634
635 #[must_use]
637 pub fn reconstruct_concept(&self, concept: &str, language: &str) -> Option<&str> {
638 let key = (Arc::<str>::from(concept), Arc::<str>::from(language));
639 self.concept_syntax.get(&key).map(Arc::as_ref)
640 }
641
642 pub fn apply_substitution(&mut self, rule: &SubstitutionRule) -> SubstitutionReport {
644 let mut report = SubstitutionReport::default();
645
646 if rule.pattern().is_empty() {
647 if !rule.replacement().is_empty() {
648 let created = self.insert_dynamic_link(
649 rule.replacement(),
650 LinkMetadata::new().with_link_type(LinkType::Relation),
651 );
652 report.created.push(created);
653 }
654 return report;
655 }
656
657 let matched = self
658 .links()
659 .filter(|link| link.references() == rule.pattern())
660 .map(Link::id)
661 .collect::<Vec<_>>();
662
663 if rule.replacement().is_empty() {
664 for id in matched {
665 if self.links.remove(&id).is_some() {
666 report.deleted.push(id);
667 }
668 }
669 return report;
670 }
671
672 for id in matched {
673 if let Some(link) = self.links.get_mut(&id) {
674 Arc::make_mut(link).references = Arc::from(rule.replacement().to_vec());
675 report.updated.push(id);
676 }
677 }
678
679 report
680 }
681
682 pub fn apply_variable_substitution(
684 &mut self,
685 rule: &VariableSubstitutionRule,
686 ) -> SubstitutionReport {
687 let mut report = SubstitutionReport::default();
688
689 if rule.pattern().is_empty() {
690 let bindings = SubstitutionBindings::default();
691 if let Some(references) = bindings.resolve_values(rule.replacement())
692 && !references.is_empty()
693 {
694 let created = self.insert_dynamic_link(
695 &references,
696 LinkMetadata::new().with_link_type(LinkType::Relation),
697 );
698 report.created.push(created);
699 report.bindings.push(bindings);
700 }
701 return report;
702 }
703
704 let matched = self
705 .links()
706 .filter_map(|link| rule.match_link(link).map(|bindings| (link.id(), bindings)))
707 .collect::<Vec<_>>();
708
709 if rule.replacement().is_empty() {
710 for (id, bindings) in matched {
711 if self.links.remove(&id).is_some() {
712 report.deleted.push(id);
713 report.bindings.push(bindings);
714 }
715 }
716 return report;
717 }
718
719 for (id, bindings) in matched {
720 let Some(references) = bindings.resolve_values(rule.replacement()) else {
721 continue;
722 };
723 if let Some(link) = self.links.get_mut(&id) {
724 Arc::make_mut(link).references = Arc::from(references);
725 report.updated.push(id);
726 report.bindings.push(bindings);
727 }
728 }
729
730 report
731 }
732
733 #[must_use]
735 pub fn link(&self, id: LinkId) -> Option<&Link> {
736 self.links.get(&id).map(Arc::as_ref)
737 }
738
739 pub(crate) fn record_grammars(&mut self, language_link: LinkId, language: &str) {
743 for grammar in grammar_provenance(language) {
744 let term = format!("{}@{}", grammar.id, grammar.version);
745 let recorded = self.links().any(|link| {
746 link.metadata().link_type() == Some(LinkType::Grammar)
747 && link.references() == [language_link]
748 && link.metadata().term() == Some(term.as_str())
749 });
750 if !recorded {
751 self.insert_link(
752 [language_link],
753 LinkMetadata::new()
754 .with_link_type(LinkType::Grammar)
755 .with_named(true)
756 .with_term(term)
757 .with_definition(format!("sha256:{}", grammar.parser_sha256))
758 .with_language(language),
759 );
760 }
761 }
762 }
763
764 #[must_use]
767 pub fn parse_grammars(&self) -> Vec<(String, GrammarProvenance)> {
768 self.links()
769 .filter(|link| link.metadata().link_type() == Some(LinkType::Grammar))
770 .filter_map(|link| {
771 let [language_link] = link.references() else {
772 return None;
773 };
774 let language = self.link(*language_link)?;
775 if language.metadata().link_type() != Some(LinkType::Language) {
776 return None;
777 }
778 let (id, version) = link.metadata().term()?.split_once('@')?;
779 let parser_sha256 = link.metadata().definition()?.strip_prefix("sha256:")?;
780 Some((
781 language.metadata().term()?.to_string(),
782 GrammarProvenance {
783 id: id.to_string(),
784 version: version.to_string(),
785 parser_sha256: parser_sha256.to_string(),
786 },
787 ))
788 })
789 .collect()
790 }
791
792 #[must_use]
794 pub fn find_term(&self, term: &str) -> Option<LinkId> {
795 self.terms.get(term).copied()
796 }
797
798 #[must_use]
800 pub fn definition_for(&self, id: LinkId) -> Option<&str> {
801 self.link(id).and_then(|link| link.metadata().definition())
802 }
803
804 pub fn set_span(&mut self, id: LinkId, span: SourceSpan) -> bool {
806 let Some(link) = self.links.get_mut(&id) else {
807 return false;
808 };
809 Arc::make_mut(link).metadata_mut().span = Some(span);
810 true
811 }
812
813 pub fn set_flags(&mut self, id: LinkId, flags: LinkFlags) -> bool {
815 let Some(link) = self.links.get_mut(&id) else {
816 return false;
817 };
818 Arc::make_mut(link).metadata_mut().flags = flags;
819 true
820 }
821
822 pub(crate) fn set_term(&mut self, id: LinkId, term: impl Into<String>) -> bool {
823 let term = self.intern_arc(Arc::from(term.into()));
824 let Some(link) = self.links.get_mut(&id) else {
825 return false;
826 };
827 Arc::make_mut(link).metadata_mut().term = Some(term);
828 true
829 }
830
831 pub(crate) fn insert_typed_point(
832 &mut self,
833 term: &str,
834 link_type: LinkType,
835 definition: Option<&str>,
836 ) -> LinkId {
837 let definition = definition.map(|definition| self.intern_arc(Arc::from(definition)));
838 if let Some(id) = self.terms.get(term).copied() {
839 if let Some(definition) = definition
840 && let Some(link) = self.links.get_mut(&id)
841 {
842 Arc::make_mut(link).metadata_mut().definition = Some(definition);
843 }
844 return id;
845 }
846
847 let id = self.allocate_id();
848 let term = self.intern_arc(Arc::from(term));
849 let mut metadata = LinkMetadata::new()
850 .with_link_type(link_type)
851 .with_named(true);
852 metadata.term = Some(Arc::clone(&term));
853 if let Some(definition) = definition {
854 metadata.definition = Some(definition);
855 }
856 self.links.insert(
857 id,
858 Arc::new(Link {
859 id,
860 references: Arc::from(vec![id]),
861 metadata,
862 }),
863 );
864 self.terms.insert(term, id);
865 id
866 }
867
868 pub(crate) fn cache_concept_syntax(
869 &mut self,
870 concept: &str,
871 language: &str,
872 syntax: &str,
873 update_reconstruction: bool,
874 ) {
875 let concept = self.intern_arc(Arc::from(concept));
876 let language = self.intern_arc(Arc::from(language));
877 let syntax = self.intern_arc(Arc::from(syntax));
878
879 if update_reconstruction
880 || !self
881 .concept_syntax
882 .contains_key(&(Arc::clone(&concept), Arc::clone(&language)))
883 {
884 self.concept_syntax.insert((concept, language), syntax);
885 }
886 }
887
888 pub fn insert_dynamic_link(&mut self, references: &[LinkId], metadata: LinkMetadata) -> LinkId {
893 let id = self.allocate_id();
894 let metadata = self.intern_metadata(metadata);
895 let term = metadata.term.clone();
896 self.links.insert(
897 id,
898 Arc::new(Link {
899 id,
900 references: Arc::from(references.to_vec()),
901 metadata,
902 }),
903 );
904 if let Some(term) = term {
905 self.terms.insert(term, id);
906 }
907 id
908 }
909
910 pub(crate) fn set_references(&mut self, id: LinkId, references: &[LinkId]) -> bool {
911 let Some(link) = self.links.get_mut(&id) else {
912 return false;
913 };
914 Arc::make_mut(link).references = Arc::from(references.to_vec());
915 true
916 }
917
918 pub(crate) fn attach_embedded_regions(
919 &mut self,
920 document: LinkId,
921 text: &str,
922 language: &str,
923 configuration: ParseConfiguration,
924 ) {
925 embedded_region_parser::attach_embedded_regions(
926 self,
927 document,
928 text,
929 language,
930 configuration,
931 );
932 }
933
934 fn intern_metadata(&mut self, mut metadata: LinkMetadata) -> LinkMetadata {
935 metadata.term = metadata.term.map(|value| self.intern_arc(value));
936 metadata.definition = metadata.definition.map(|value| self.intern_arc(value));
937 metadata.language = metadata.language.map(|value| self.intern_arc(value));
938 metadata
939 }
940
941 fn intern_arc(&mut self, value: Arc<str>) -> Arc<str> {
942 if let Some(interned) = self.strings.get(value.as_ref()) {
943 return Arc::clone(interned);
944 }
945
946 self.strings.insert(Arc::clone(&value));
947 value
948 }
949
950 const fn allocate_id(&mut self) -> LinkId {
951 let id = LinkId(self.next_id);
952 self.next_id += 1;
953 id
954 }
955}
956
957fn end_point_for_text(text: &str) -> Point {
958 let mut row = 0;
959 let mut column = 0;
960 for character in text.chars() {
961 if character == '\n' {
962 row += 1;
963 column = 0;
964 } else {
965 column += character.len_utf8();
966 }
967 }
968 Point::new(row, column)
969}