1use crate::api::{
12 parse_batch as run_parse_batch, parse_source as run_parse_source, BatchParseOptions,
13 BatchParseResult, ParseInput, ParseOptions, ParseResult, ParseSessionResult,
14};
15use crate::diagnostic::{Diagnostic, DiagnosticCode, MESSAGE_REF_CATALOG};
16use crate::snapshot::error::SnapshotWriteError;
17use crate::snapshot::format::{
18 checked_u32, write_u16_le, write_u32_le, write_u8, RootId, SectionKind, StringId,
19 DIAGNOSTIC_LABEL_RECORD_SIZE, DIAGNOSTIC_RECORD_SIZE, EDGE_KIND_NODE, EDGE_KIND_TOKEN,
20 EDGE_RECORD_SIZE, NODE_RECORD_SIZE, NONE_REF, TOKEN_RECORD_SIZE, TRIVIA_RECORD_SIZE,
21};
22use crate::snapshot::sections::{EmittedSection, SnapshotAssembler};
23use crate::snapshot::string_table::StringTableBuilder;
24use crate::source::{SourceFileInput, SourceStore};
25use crate::span::SourceId as PhaseOneSourceId;
26use crate::tables::CstTables;
27
28#[derive(Debug, Clone, Copy)]
35pub struct SnapshotOptions {
36 pub include_diagnostics: bool,
41 pub include_source_text: bool,
45 pub include_trivia: bool,
49}
50
51impl Default for SnapshotOptions {
52 fn default() -> Self {
53 Self {
54 include_diagnostics: true,
55 include_source_text: false,
56 include_trivia: true,
57 }
58 }
59}
60
61#[derive(Debug, Clone)]
63pub struct SnapshotResult {
64 pub bytes: Vec<u8>,
66 pub root: RootId,
69 pub diagnostics: Vec<Diagnostic>,
72}
73
74#[derive(Debug, Clone)]
76pub struct BatchSnapshotResult {
77 pub bytes: Vec<u8>,
78 pub roots: Vec<RootId>,
79 pub diagnostics: Vec<Diagnostic>,
80 pub execution: crate::api::BatchExecution,
81 pub degraded: bool,
82}
83
84pub fn parse_result_to_snapshot(
104 sources: &SourceStore,
105 result: &ParseResult,
106 options: SnapshotOptions,
107) -> Result<SnapshotResult, SnapshotWriteError> {
108 let diagnostics = result.diagnostics.clone();
112 encode_single(sources, result.source, &result.cst, diagnostics, options)
113}
114
115#[derive(Debug, Default, Clone, Copy)]
125pub struct SnapshotSourceMetadata<'a> {
126 pub path: Option<&'a str>,
128 pub locale: Option<&'a str>,
130 pub message_id: Option<&'a str>,
132 pub base_offset: Option<u32>,
135}
136
137pub fn parse_message_to_snapshot(
148 source: &str,
149 metadata: Option<SnapshotSourceMetadata<'_>>,
150 parse_options: ParseOptions,
151 snapshot_options: SnapshotOptions,
152) -> Result<SnapshotResult, SnapshotWriteError> {
153 let mut sources = SourceStore::with_capacity(1);
154 let metadata = metadata.unwrap_or_default();
155 let input = SourceFileInput {
156 source,
157 path: metadata.path,
158 locale: metadata.locale,
159 message_id: metadata.message_id,
160 base_offset: metadata.base_offset,
161 };
162 let id = sources
168 .try_add(input)
169 .map_err(|_| SnapshotWriteError::SourceTooLarge)?;
170 let result = run_parse_source(&sources, id, parse_options);
171 parse_result_to_snapshot(&sources, &result, snapshot_options)
172}
173
174pub fn parse_source_to_snapshot(
177 sources: &SourceStore,
178 source_id: PhaseOneSourceId,
179 parse_options: ParseOptions,
180 snapshot_options: SnapshotOptions,
181) -> Result<SnapshotResult, SnapshotWriteError> {
182 let result = run_parse_source(sources, source_id, parse_options);
183 parse_result_to_snapshot(sources, &result, snapshot_options)
184}
185
186pub fn parse_session_to_snapshot(
192 session: &ParseSessionResult<'_>,
193 options: SnapshotOptions,
194) -> Result<SnapshotResult, SnapshotWriteError> {
195 let diagnostics: Vec<Diagnostic> = session.diagnostics.iter().collect();
200 encode_single(
201 session.cst.sources(),
202 session.source,
203 session.cst.tables(),
204 diagnostics,
205 options,
206 )
207}
208
209pub fn parse_batch_to_snapshot(
212 inputs: &[ParseInput<'_>],
213 batch_options: BatchParseOptions,
214 snapshot_options: SnapshotOptions,
215) -> Result<BatchSnapshotResult, SnapshotWriteError> {
216 for input in inputs {
222 if u32::try_from(input.source.len()).is_err() {
223 return Err(SnapshotWriteError::SourceTooLarge);
224 }
225 }
226 let batch = run_parse_batch(inputs, batch_options);
227 parse_batch_result_to_snapshot(&batch, snapshot_options)
228}
229
230pub fn parse_batch_result_to_snapshot(
233 result: &BatchParseResult,
234 options: SnapshotOptions,
235) -> Result<BatchSnapshotResult, SnapshotWriteError> {
236 for item in &result.items {
245 if item.source != item.result.source {
246 return Err(SnapshotWriteError::InconsistentSourceId);
247 }
248 }
249 let mut writer = SnapshotWriter::with_root_hint(options, result.items.len());
252 writer.pre_intern_root_sources(&result.sources, result.items.iter().map(|item| item.source))?;
257 for item in &result.items {
258 writer.add_root(
259 &result.sources,
260 item.source,
261 &item.result.cst,
262 &item.result.diagnostics,
263 )?;
264 }
265 let bytes = writer.finish(&result.sources)?;
266 let roots_count = checked_u32(result.items.len()).ok_or(SnapshotWriteError::TooManyRoots)?;
267 let roots = (0..roots_count).map(RootId::new).collect();
268 let diagnostic_total: usize = result
275 .items
276 .iter()
277 .map(|item| item.result.diagnostics.len())
278 .sum();
279 let mut diagnostics = Vec::with_capacity(diagnostic_total);
280 for item in &result.items {
281 diagnostics.extend(item.result.diagnostics.iter().cloned());
282 }
283 Ok(BatchSnapshotResult {
284 bytes,
285 roots,
286 diagnostics,
287 execution: result.execution,
288 degraded: result.degraded,
289 })
290}
291
292fn encode_single(
293 sources: &SourceStore,
294 source: PhaseOneSourceId,
295 cst: &CstTables,
296 diagnostics: Vec<Diagnostic>,
297 options: SnapshotOptions,
298) -> Result<SnapshotResult, SnapshotWriteError> {
299 let mut writer = SnapshotWriter::new(options);
300 writer.pre_intern_root_sources(sources, [source])?;
304 writer.add_root(sources, source, cst, &diagnostics)?;
305 let bytes = writer.finish(sources)?;
306 Ok(SnapshotResult {
307 bytes,
308 root: RootId::new(0),
309 diagnostics,
310 })
311}
312
313struct PendingRoot {
316 source_local: u32,
317 root_node: u32,
318 diag_start: u32,
320 diag_count: u32,
321}
322
323#[derive(Debug, Clone, Copy)]
328struct SourceMetaIds {
329 path: StringId,
330 locale: StringId,
331 message_id: StringId,
332}
333
334struct SnapshotWriter {
335 options: SnapshotOptions,
336 string_table: StringTableBuilder,
337 source_phase_one: Vec<PhaseOneSourceId>,
344 source_meta: Vec<SourceMetaIds>,
349 nodes_bytes: Vec<u8>,
350 nodes_count: u32,
351 edges_bytes: Vec<u8>,
352 edges_count: u32,
353 tokens_bytes: Vec<u8>,
354 tokens_count: u32,
355 trivia_bytes: Vec<u8>,
356 trivia_count: u32,
357 diagnostics_bytes: Vec<u8>,
358 diagnostics_count: u32,
359 diagnostic_labels_bytes: Vec<u8>,
360 diagnostic_labels_count: u32,
361 roots: Vec<PendingRoot>,
362}
363
364impl SnapshotWriter {
365 fn new(options: SnapshotOptions) -> Self {
366 Self::with_root_hint(options, 1)
367 }
368
369 fn with_root_hint(options: SnapshotOptions, root_hint: usize) -> Self {
375 let string_hint = root_hint.saturating_mul(3).saturating_add(16);
381 let data_hint = root_hint.saturating_mul(64);
382 Self {
383 options,
384 string_table: StringTableBuilder::with_capacity(string_hint, data_hint),
385 source_phase_one: Vec::with_capacity(root_hint),
386 source_meta: Vec::with_capacity(root_hint),
387 nodes_bytes: Vec::new(),
388 nodes_count: 0,
389 edges_bytes: Vec::new(),
390 edges_count: 0,
391 tokens_bytes: Vec::new(),
392 tokens_count: 0,
393 trivia_bytes: Vec::new(),
394 trivia_count: 0,
395 diagnostics_bytes: Vec::new(),
396 diagnostics_count: 0,
397 diagnostic_labels_bytes: Vec::new(),
398 diagnostic_labels_count: 0,
399 roots: Vec::with_capacity(root_hint),
400 }
401 }
402
403 fn allocate_root_source(
411 &mut self,
412 sources: &SourceStore,
413 root_source: PhaseOneSourceId,
414 ) -> Result<u32, SnapshotWriteError> {
415 let file = sources
416 .get(root_source)
417 .ok_or(SnapshotWriteError::InvalidSourceId)?;
418 let local =
419 checked_u32(self.source_phase_one.len()).ok_or(SnapshotWriteError::TooManySources)?;
420 let path = self.string_table.intern_optional(file.path.as_deref())?;
421 let locale = self.string_table.intern_optional(file.locale.as_deref())?;
422 let message_id = self
423 .string_table
424 .intern_optional(file.message_id.as_deref())?;
425 self.source_phase_one.push(root_source);
426 self.source_meta.push(SourceMetaIds {
427 path,
428 locale,
429 message_id,
430 });
431 debug_assert_eq!(self.source_meta.len(), self.source_phase_one.len());
432 Ok(local)
433 }
434
435 fn pre_intern_root_sources<I>(
446 &mut self,
447 sources: &SourceStore,
448 source_ids: I,
449 ) -> Result<(), SnapshotWriteError>
450 where
451 I: IntoIterator<Item = PhaseOneSourceId>,
452 {
453 for id in source_ids {
454 let file = sources.get(id).ok_or(SnapshotWriteError::InvalidSourceId)?;
455 self.string_table.intern_optional(file.path.as_deref())?;
456 self.string_table.intern_optional(file.locale.as_deref())?;
457 self.string_table
458 .intern_optional(file.message_id.as_deref())?;
459 }
460 Ok(())
461 }
462
463 fn add_root(
464 &mut self,
465 sources: &SourceStore,
466 source: PhaseOneSourceId,
467 cst: &CstTables,
468 diagnostics: &[Diagnostic],
469 ) -> Result<(), SnapshotWriteError> {
470 self.nodes_bytes
476 .reserve(cst.node_count() * NODE_RECORD_SIZE as usize);
477 self.edges_bytes
478 .reserve(cst.edge_count() * EDGE_RECORD_SIZE as usize);
479 self.tokens_bytes
480 .reserve(cst.token_count() * TOKEN_RECORD_SIZE as usize);
481 if self.options.include_trivia {
482 self.trivia_bytes
483 .reserve(cst.trivia_count() * TRIVIA_RECORD_SIZE as usize);
484 }
485 if self.options.include_diagnostics {
486 self.diagnostics_bytes
487 .reserve(diagnostics.len() * DIAGNOSTIC_RECORD_SIZE as usize);
488 let label_total: usize = diagnostics.iter().map(|d| d.labels.len()).sum();
489 self.diagnostic_labels_bytes
490 .reserve(label_total * DIAGNOSTIC_LABEL_RECORD_SIZE as usize);
491 }
492
493 let source_local = self.allocate_root_source(sources, source)?;
499
500 let trivia_remap = self.emit_trivia(cst, source_local)?;
505 let token_remap = self.emit_tokens(cst, &trivia_remap, source_local)?;
507 let node_remap = self.emit_nodes_and_edges(cst, &token_remap)?;
512
513 let root_node = match cst.root_id() {
514 Some(parser_root) => node_remap[parser_root.index()],
515 None => return Err(SnapshotWriteError::MissingRoot),
516 };
517
518 let (diag_start, diag_count) = if self.options.include_diagnostics {
526 let start = self.diagnostics_count;
527 for diag in diagnostics {
528 self.emit_diagnostic(diag, source_local)?;
529 }
530 let count = self
531 .diagnostics_count
532 .checked_sub(start)
533 .expect("diagnostics_count only grows");
534 (start, count)
535 } else {
536 (0, 0)
537 };
538
539 let _ = node_remap;
544 let _ = token_remap;
545 let _ = trivia_remap;
546
547 self.roots.push(PendingRoot {
548 source_local,
549 root_node,
550 diag_start,
551 diag_count,
552 });
553 Ok(())
554 }
555
556 fn emit_trivia(
557 &mut self,
558 cst: &CstTables,
559 root_source_local: u32,
560 ) -> Result<Vec<u32>, SnapshotWriteError> {
561 let trivia_count = cst.trivia_count();
562 let mut remap = Vec::with_capacity(trivia_count);
563 if !self.options.include_trivia || trivia_count == 0 {
564 remap.resize(trivia_count, NONE_REF);
565 return Ok(remap);
566 }
567 for trivia in &cst.trivia {
573 let local = self.next_trivia_id()?;
574 write_u16_le(&mut self.trivia_bytes, trivia.kind);
575 write_u16_le(&mut self.trivia_bytes, 0); write_u32_le(&mut self.trivia_bytes, trivia.span_start);
577 write_u32_le(&mut self.trivia_bytes, trivia.span_end);
578 write_u32_le(&mut self.trivia_bytes, root_source_local);
579 remap.push(local);
580 }
581 Ok(remap)
582 }
583
584 fn emit_tokens(
585 &mut self,
586 cst: &CstTables,
587 trivia_remap: &[u32],
588 root_source_local: u32,
589 ) -> Result<Vec<u32>, SnapshotWriteError> {
590 let mut remap = Vec::with_capacity(cst.token_count());
591 for token in &cst.tokens {
592 let local = self.next_token_id()?;
593 let source_local = root_source_local;
594
595 let (leading_start, leading_count, trailing_start, trailing_count) =
596 if self.options.include_trivia
597 && (token.leading_trivia_count != 0 || token.trailing_trivia_count != 0)
598 {
599 let lead_start_parser = token.first_trivia;
600 let trail_start_parser = lead_start_parser + token.leading_trivia_count as u32;
601 let lead_start_snap = if token.leading_trivia_count == 0 {
602 0
603 } else {
604 trivia_remap[lead_start_parser as usize]
605 };
606 let trail_start_snap = if token.trailing_trivia_count == 0 {
607 0
608 } else {
609 trivia_remap[trail_start_parser as usize]
610 };
611 (
612 lead_start_snap,
613 token.leading_trivia_count as u32,
614 trail_start_snap,
615 token.trailing_trivia_count as u32,
616 )
617 } else {
618 (0, 0, 0, 0)
619 };
620
621 write_u16_le(&mut self.tokens_bytes, token.kind);
622 write_u16_le(&mut self.tokens_bytes, 0); write_u32_le(&mut self.tokens_bytes, token.span_start);
624 write_u32_le(&mut self.tokens_bytes, token.span_end);
625 write_u32_le(&mut self.tokens_bytes, source_local);
626 write_u32_le(&mut self.tokens_bytes, leading_start);
627 write_u32_le(&mut self.tokens_bytes, leading_count);
628 write_u32_le(&mut self.tokens_bytes, trailing_start);
629 write_u32_le(&mut self.tokens_bytes, trailing_count);
630 write_u32_le(&mut self.tokens_bytes, 0); remap.push(local);
632 }
633 Ok(remap)
634 }
635
636 fn emit_nodes_and_edges(
637 &mut self,
638 cst: &CstTables,
639 token_remap: &[u32],
640 ) -> Result<Vec<u32>, SnapshotWriteError> {
641 let mut remap = Vec::with_capacity(cst.node_count());
642 for node in &cst.nodes {
643 let snapshot_node_id = self.next_node_id()?;
644 let child_start = self.edges_count;
645 for edge in cst.edges_for(node) {
649 let snapshot_edge_id = self.next_edge_id()?;
650 let _ = snapshot_edge_id;
651 match edge.kind {
652 k if k == EDGE_KIND_NODE => {
653 let snap_id = remap[edge.ref_id as usize];
654 write_u16_le(&mut self.edges_bytes, EDGE_KIND_NODE);
655 write_u16_le(&mut self.edges_bytes, 0); write_u32_le(&mut self.edges_bytes, snap_id);
657 }
658 k if k == EDGE_KIND_TOKEN => {
659 let snap_id = token_remap[edge.ref_id as usize];
660 write_u16_le(&mut self.edges_bytes, EDGE_KIND_TOKEN);
661 write_u16_le(&mut self.edges_bytes, 0); write_u32_le(&mut self.edges_bytes, snap_id);
663 }
664 _ => {
665 return Err(SnapshotWriteError::InvalidSourceId);
670 }
671 }
672 }
673 let child_count = self
674 .edges_count
675 .checked_sub(child_start)
676 .expect("edges_count only grows");
677
678 write_u16_le(&mut self.nodes_bytes, node.kind);
679 write_u16_le(&mut self.nodes_bytes, 0); write_u32_le(&mut self.nodes_bytes, node.span_start);
681 write_u32_le(&mut self.nodes_bytes, node.span_end);
682 write_u32_le(&mut self.nodes_bytes, child_start);
683 write_u32_le(&mut self.nodes_bytes, child_count);
684 write_u32_le(&mut self.nodes_bytes, NONE_REF); remap.push(snapshot_node_id);
686 }
687 Ok(remap)
688 }
689
690 fn emit_diagnostic(
691 &mut self,
692 diagnostic: &Diagnostic,
693 root_source_local: u32,
694 ) -> Result<(), SnapshotWriteError> {
695 let source_local = root_source_local;
708 let _ = diagnostic.source; let label_start = self.diagnostic_labels_count;
710 for label in &diagnostic.labels {
711 let label_source = root_source_local;
712 let _ = label.source; let msg_id = if self.options.include_diagnostics {
714 self.string_table.intern(label.message)?
715 } else {
716 StringId::NONE
717 };
718 self.next_diagnostic_label_id()?;
719 write_u32_le(&mut self.diagnostic_labels_bytes, label_source);
720 write_u32_le(&mut self.diagnostic_labels_bytes, label.span.start);
721 write_u32_le(&mut self.diagnostic_labels_bytes, label.span.end);
722 write_u32_le(&mut self.diagnostic_labels_bytes, msg_id.raw());
723 }
724 let label_count = self
725 .diagnostic_labels_count
726 .checked_sub(label_start)
727 .expect("label count only grows");
728
729 let message_id = if self.options.include_diagnostics {
730 self.string_table.intern(diagnostic.message)?
731 } else {
732 StringId::NONE
733 };
734
735 self.next_diagnostic_id()?;
736 write_u32_le(&mut self.diagnostics_bytes, source_local);
737 write_u32_le(&mut self.diagnostics_bytes, diagnostic.span.start);
738 write_u32_le(&mut self.diagnostics_bytes, diagnostic.span.end);
739 write_u8(&mut self.diagnostics_bytes, diagnostic.severity as u8);
740 write_u8(&mut self.diagnostics_bytes, 0); write_u16_le(&mut self.diagnostics_bytes, diagnostic.code.as_u16());
742 write_u32_le(&mut self.diagnostics_bytes, message_id.raw());
743 write_u32_le(&mut self.diagnostics_bytes, label_start);
744 write_u32_le(&mut self.diagnostics_bytes, label_count);
745 Ok(())
746 }
747
748 fn finish(self, sources: &SourceStore) -> Result<Vec<u8>, SnapshotWriteError> {
749 let Self {
750 options,
751 string_table,
752 source_phase_one,
753 source_meta,
754 nodes_bytes,
755 nodes_count,
756 edges_bytes,
757 edges_count,
758 tokens_bytes,
759 tokens_count,
760 trivia_bytes,
761 trivia_count,
762 diagnostics_bytes,
763 diagnostics_count,
764 diagnostic_labels_bytes,
765 diagnostic_labels_count,
766 roots,
767 } = self;
768
769 if roots.is_empty() {
770 return Err(SnapshotWriteError::MissingRoot);
771 }
772
773 debug_assert_eq!(source_meta.len(), source_phase_one.len());
774
775 let mut sources_bytes = Vec::with_capacity(source_phase_one.len() * 32);
777 let mut sources_count: u32 = 0;
778 let include_source_text = options.include_source_text;
779 let mut source_text_bytes: Vec<u8> = if include_source_text {
785 let mut total: u32 = 0;
786 for &phase_one in &source_phase_one {
787 let file = sources
788 .get(phase_one)
789 .ok_or(SnapshotWriteError::InvalidSourceId)?;
790 total = total
791 .checked_add(file.len())
792 .ok_or(SnapshotWriteError::SectionTooLarge)?;
793 }
794 Vec::with_capacity(total as usize)
795 } else {
796 Vec::new()
797 };
798 for (snapshot_local, (&phase_one, meta)) in
799 source_phase_one.iter().zip(source_meta.iter()).enumerate()
800 {
801 let snapshot_local =
802 checked_u32(snapshot_local).ok_or(SnapshotWriteError::TooManySources)?;
803 let file = sources
804 .get(phase_one)
805 .ok_or(SnapshotWriteError::InvalidSourceId)?;
806 let (text_source, text_offset, text_len) = if include_source_text {
807 let offset = checked_u32(source_text_bytes.len())
808 .ok_or(SnapshotWriteError::SectionTooLarge)?;
809 let len = file.len();
810 source_text_bytes.extend_from_slice(file.text.as_bytes());
811 (snapshot_local, offset, len)
812 } else {
813 (NONE_REF, 0, 0)
814 };
815 write_u32_le(&mut sources_bytes, snapshot_local);
816 write_u32_le(&mut sources_bytes, meta.path.raw());
817 write_u32_le(&mut sources_bytes, meta.locale.raw());
818 write_u32_le(&mut sources_bytes, meta.message_id.raw());
819 write_u32_le(&mut sources_bytes, file.base_offset);
820 write_u32_le(&mut sources_bytes, text_source);
822 write_u32_le(&mut sources_bytes, text_offset);
823 write_u32_le(&mut sources_bytes, text_len);
824 sources_count = sources_count
825 .checked_add(1)
826 .ok_or(SnapshotWriteError::TooManySources)?;
827 }
828
829 let roots_count = checked_u32(roots.len()).ok_or(SnapshotWriteError::TooManyRoots)?;
831 let mut roots_bytes = Vec::with_capacity(roots.len() * 16);
832 for root in &roots {
833 write_u32_le(&mut roots_bytes, root.root_node);
834 write_u32_le(&mut roots_bytes, root.source_local);
835 if options.include_diagnostics {
836 write_u32_le(&mut roots_bytes, root.diag_start);
837 write_u32_le(&mut roots_bytes, root.diag_count);
838 } else {
839 write_u32_le(&mut roots_bytes, 0);
840 write_u32_le(&mut roots_bytes, 0);
841 }
842 }
843
844 let offsets = string_table.offsets();
846 let strings_count = checked_u32(offsets.len()).ok_or(SnapshotWriteError::TooManyStrings)?;
847 let mut string_offsets_bytes = Vec::with_capacity(offsets.len() * 8);
848 for entry in offsets {
849 write_u32_le(&mut string_offsets_bytes, entry.offset);
850 write_u32_le(&mut string_offsets_bytes, entry.len);
851 }
852 let string_data = string_table.data().to_vec();
853
854 let mut assembler = SnapshotAssembler::new();
856 assembler.push(EmittedSection {
857 kind: SectionKind::Roots,
858 bytes: roots_bytes,
859 count: roots_count,
860 });
861 assembler.push(EmittedSection {
862 kind: SectionKind::Sources,
863 bytes: sources_bytes,
864 count: sources_count,
865 });
866 assembler.push(EmittedSection {
867 kind: SectionKind::Nodes,
868 bytes: nodes_bytes,
869 count: nodes_count,
870 });
871 assembler.push(EmittedSection {
872 kind: SectionKind::Edges,
873 bytes: edges_bytes,
874 count: edges_count,
875 });
876 assembler.push(EmittedSection {
877 kind: SectionKind::Tokens,
878 bytes: tokens_bytes,
879 count: tokens_count,
880 });
881 if options.include_trivia && trivia_count > 0 {
883 assembler.push(EmittedSection {
884 kind: SectionKind::Trivia,
885 bytes: trivia_bytes,
886 count: trivia_count,
887 });
888 }
889 if options.include_diagnostics && diagnostics_count > 0 {
890 assembler.push(EmittedSection {
891 kind: SectionKind::Diagnostics,
892 bytes: diagnostics_bytes,
893 count: diagnostics_count,
894 });
895 }
896 if options.include_diagnostics && diagnostic_labels_count > 0 {
897 assembler.push(EmittedSection {
898 kind: SectionKind::DiagnosticLabels,
899 bytes: diagnostic_labels_bytes,
900 count: diagnostic_labels_count,
901 });
902 }
903 assembler.push(EmittedSection {
904 kind: SectionKind::StringOffsets,
905 bytes: string_offsets_bytes,
906 count: strings_count,
907 });
908 assembler.push(EmittedSection {
909 kind: SectionKind::StringData,
910 bytes: string_data,
911 count: 0,
912 });
913 if include_source_text {
920 assembler.push(EmittedSection {
921 kind: SectionKind::SourceTextData,
922 bytes: source_text_bytes,
923 count: 0,
924 });
925 }
926
927 assembler.finish()
928 }
929
930 fn next_node_id(&mut self) -> Result<u32, SnapshotWriteError> {
933 let id = self.nodes_count;
934 self.nodes_count = self
935 .nodes_count
936 .checked_add(1)
937 .ok_or(SnapshotWriteError::TooManyNodes)?;
938 Ok(id)
939 }
940
941 fn next_edge_id(&mut self) -> Result<u32, SnapshotWriteError> {
942 let id = self.edges_count;
943 self.edges_count = self
944 .edges_count
945 .checked_add(1)
946 .ok_or(SnapshotWriteError::TooManyEdges)?;
947 Ok(id)
948 }
949
950 fn next_token_id(&mut self) -> Result<u32, SnapshotWriteError> {
951 let id = self.tokens_count;
952 self.tokens_count = self
953 .tokens_count
954 .checked_add(1)
955 .ok_or(SnapshotWriteError::TooManyTokens)?;
956 Ok(id)
957 }
958
959 fn next_trivia_id(&mut self) -> Result<u32, SnapshotWriteError> {
960 let id = self.trivia_count;
961 self.trivia_count = self
962 .trivia_count
963 .checked_add(1)
964 .ok_or(SnapshotWriteError::TooManyTrivia)?;
965 Ok(id)
966 }
967
968 fn next_diagnostic_id(&mut self) -> Result<u32, SnapshotWriteError> {
969 let id = self.diagnostics_count;
970 self.diagnostics_count = self
971 .diagnostics_count
972 .checked_add(1)
973 .ok_or(SnapshotWriteError::TooManyDiagnostics)?;
974 Ok(id)
975 }
976
977 fn next_diagnostic_label_id(&mut self) -> Result<u32, SnapshotWriteError> {
978 let id = self.diagnostic_labels_count;
979 self.diagnostic_labels_count = self
980 .diagnostic_labels_count
981 .checked_add(1)
982 .ok_or(SnapshotWriteError::TooManyDiagnosticLabels)?;
983 Ok(id)
984 }
985}
986
987#[allow(dead_code)] fn diagnostic_catalog_str(code: DiagnosticCode) -> &'static str {
990 code.static_message()
991}
992
993#[allow(dead_code)]
994const _ASSERT_MESSAGE_REF_CATALOG: u32 = MESSAGE_REF_CATALOG;