pedant_types/resolution/span.rs
1//! Where a definition or reference sits in the snapshotted source.
2
3use std::sync::Arc;
4
5use serde::{Deserialize, Serialize};
6
7/// A zero-based point in one source file.
8///
9/// A column counts UTF-8 bytes from the first byte after the preceding `\n`, so
10/// a `\r` in a CRLF pair is an ordinary byte. Both coordinates are `u32` so a
11/// serialized report reads the same on every platform.
12#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[serde(deny_unknown_fields)]
14pub struct SourcePosition {
15 line: u32,
16 column: u32,
17}
18
19impl SourcePosition {
20 /// A point at a zero-based line and UTF-8 byte column.
21 pub fn new(line: u32, column: u32) -> Self {
22 Self { line, column }
23 }
24
25 /// The zero-based line.
26 pub fn line(self) -> u32 {
27 self.line
28 }
29
30 /// The zero-based UTF-8 byte column.
31 pub fn column(self) -> u32 {
32 self.column
33 }
34}
35
36/// A half-open range in one normalized repository-relative file.
37///
38/// The derived ordering is the report's structural sort key for sites: file,
39/// then start, then end.
40#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
41#[serde(deny_unknown_fields)]
42pub struct SourceSpan {
43 file: Arc<str>,
44 start: SourcePosition,
45 end: SourcePosition,
46}
47
48impl SourceSpan {
49 /// A span over `file`, from `start` up to but excluding `end`.
50 ///
51 /// The path is validated when the report is constructed, so one file value
52 /// shared by many sites is checked once per site rather than at every clone.
53 pub fn new(file: Arc<str>, start: SourcePosition, end: SourcePosition) -> Self {
54 Self { file, start, end }
55 }
56
57 /// The normalized repository-relative path.
58 pub fn file(&self) -> &str {
59 &self.file
60 }
61
62 /// The shared path value itself, for a decoder pointing many spans at one.
63 pub(super) fn shared_file(&self) -> &Arc<str> {
64 &self.file
65 }
66
67 /// Adopt an equal path value that other spans already share.
68 ///
69 /// Serde allocates one path per span on the way in, which is the opposite
70 /// of what this type is for, so the decoder replaces each with the one
71 /// canonical value before the report exists.
72 pub(super) fn adopt_file(&mut self, file: Arc<str>) {
73 self.file = file;
74 }
75
76 /// The inclusive start point.
77 pub fn start(&self) -> SourcePosition {
78 self.start
79 }
80
81 /// The exclusive end point.
82 pub fn end(&self) -> SourcePosition {
83 self.end
84 }
85}