1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/// Source position information for parsing, with dual column tracking.
///
/// This is a pure data struct with no mutation methods. Lexers are responsible
/// for computing position values as they scan input.
///
/// This is standalone with no dependency on libgraphql-core.
/// All fields are private with accessor methods.
///
/// # Indexing Convention
///
/// **All position values are 0-based:**
/// - `line`: 0 = first line of the document (0-based)
/// - `col_utf8`: UTF-8 character count within the current line (0-based)
/// - `col_utf16`: Optional UTF-16 code unit offset within the current line
/// (0-based)
/// - `byte_offset`: byte offset within the whole document (0-based)
///
/// # Dual Column Tracking
///
/// Two column representations are supported:
/// - **`col_utf8`** (always available): Number of UTF-8 characters from the
/// start of the current line. Increments by 1 for each character regardless
/// of its byte representation. This is intuitive for users and matches what
/// most text editors display as "column".
/// - **`col_utf16`** (optional): UTF-16 code unit offset within the line. This
/// aligns with LSP (Language Server Protocol) and many editors. It is `Some`
/// when the token source can provide it (e.g. `StrToGraphQLTokenSource`),
/// and `None` when it cannot (e.g. `RustMacroGraphQLTokenSource` in
/// `libgraphql-macros` which uses `proc_macro2::Span` that only provides
/// UTF-8 char-based positions).
///
/// For ASCII text, both columns are equal. For text containing characters
/// outside the Basic Multilingual Plane (e.g., emoji), they differ:
/// - `col_utf8` advances by 1 for each UTF-8 character
/// - `col_utf16` advances by the character's UTF-16 length (1 or 2 code units)
///
/// # Size
///
/// This struct is 20 bytes (4 × `u32` + `Option<u32>`) and derives `Copy`
/// for cheap value semantics. The `u32` fields support files up to 4 GB
/// and lines/columns up to ~4 billion — more than sufficient for any
/// realistic GraphQL document. Accessors return `usize` for ergonomic
/// interop with Rust's standard indexing types.