Skip to main content

source_lang/
lib.rs

1//! # source_lang
2//!
3//! The multi-file coordinate layer of a compiler front-end. It holds many
4//! sources — files and in-memory buffers — in one [`SourceMap`], gives each a
5//! stable [`SourceId`], lays them out across a single global position space, and
6//! resolves any global [`BytePos`] back to the source and local offset it came
7//! from.
8//!
9//! It is the layer above [`span_lang`]: a [`Span`] says *where in a buffer* an
10//! error is, and this crate says *which buffer*, so a diagnostic can name the
11//! file as well as the position. It owns source storage and coordinate mapping
12//! only — no lexing, no diagnostic rendering.
13//!
14//! ## Model
15//!
16//! Sources are placed end to end in the order they are added. The first occupies
17//! global offsets `0..len₀`, the next `len₀..len₀ + len₁`, and so on, so the
18//! ranges never overlap and the whole project shares one position space. Because
19//! each base is the running total, the sources stay sorted by offset and
20//! [`SourceMap::locate`] is a binary search — `O(log files)` — that borrows the
21//! resolved source rather than copying it. The space is 32 bits wide, so the
22//! combined length of every source is capped at `u32::MAX`; overrunning it is a
23//! defined [`SourceMapError`], never a silent wrap.
24//!
25//! ## Quickstart
26//!
27//! ```
28//! use source_lang::{BytePos, SourceMap};
29//!
30//! let mut map = SourceMap::new();
31//! let main = map.add("main.rs", "fn main() {}")?; // global 0..12
32//! let util = map.add("util.rs", "fn helper() {}")?; // global 12..26
33//!
34//! // Resolve a global position to its file and the local offset within it.
35//! let (id, local) = map.locate(BytePos::new(13)).expect("inside util.rs");
36//! assert_eq!(id, util);
37//! assert_eq!(local, BytePos::new(1)); // 13 - 12
38//!
39//! // The id is a stable handle back to the source.
40//! assert_eq!(map.source(main).unwrap().name(), "main.rs");
41//! # Ok::<(), source_lang::SourceMapError>(())
42//! ```
43
44#![cfg_attr(not(feature = "std"), no_std)]
45#![cfg_attr(docsrs, feature(doc_cfg))]
46#![deny(missing_docs)]
47#![forbid(unsafe_code)]
48
49extern crate alloc;
50
51mod error;
52mod file;
53mod id;
54mod map;
55
56pub use error::SourceMapError;
57pub use file::SourceFile;
58pub use id::SourceId;
59pub use map::SourceMap;
60
61// Re-exported so a downstream consuming this crate's API does not also have to
62// name `span-lang` as a dependency just to spell the position types it returns.
63pub use span_lang::{BytePos, Span};