Skip to content

Commit 9966022

Browse files
authored
fix(rust): encode non-zero line invariant in API (#31)
1 parent 56ae38b commit 9966022

File tree

2 files changed

+26
-24
lines changed

2 files changed

+26
-24
lines changed

rust/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ the source buffer (zero-copy).
6565
| `exports_count()` | `usize` | Number of named exports |
6666
| `reexports_count()` | `usize` | Number of re-export specifiers |
6767
| `export_name(index)` | `Option<&'a str>` | Export name at index |
68-
| `export_line(index)` | `Option<u32>` | 1-based line number of export |
68+
| `export_line(index)` | `Option<NonZeroU32>` | 1-based non-zero line number of export |
6969
| `reexport_name(index)` | `Option<&'a str>` | Re-export specifier at index |
70-
| `reexport_line(index)` | `Option<u32>` | 1-based line number of re-export |
70+
| `reexport_line(index)` | `Option<NonZeroU32>` | 1-based non-zero line number of re-export |
7171
| `exports()` | `ExportIter` | Iterator over all exports |
7272
| `reexports()` | `ExportIter` | Iterator over all re-exports |
7373

@@ -76,7 +76,7 @@ the source buffer (zero-copy).
7676
```rust
7777
pub struct Export<'a> {
7878
pub name: &'a str,
79-
pub line: u32,
79+
pub line: NonZeroU32,
8080
}
8181
```
8282

rust/src/lib.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extern crate std;
3434

3535
use core::fmt;
3636
use core::marker::PhantomData;
37+
use core::num::NonZeroU32;
3738

3839
/// Error codes returned by the merve lexer.
3940
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -175,16 +176,12 @@ impl<'a> Analysis<'a> {
175176
///
176177
/// Returns `None` if `index` is out of bounds.
177178
#[must_use]
178-
pub fn export_line(&self, index: usize) -> Option<u32> {
179+
pub fn export_line(&self, index: usize) -> Option<NonZeroU32> {
179180
if index >= self.exports_count() {
180181
return None;
181182
}
182183
let line = unsafe { ffi::merve_get_export_line(self.handle, index) };
183-
if line == 0 {
184-
None
185-
} else {
186-
Some(line)
187-
}
184+
NonZeroU32::new(line)
188185
}
189186

190187
/// Get the module specifier of the re-export at `index`.
@@ -203,16 +200,12 @@ impl<'a> Analysis<'a> {
203200
///
204201
/// Returns `None` if `index` is out of bounds.
205202
#[must_use]
206-
pub fn reexport_line(&self, index: usize) -> Option<u32> {
203+
pub fn reexport_line(&self, index: usize) -> Option<NonZeroU32> {
207204
if index >= self.reexports_count() {
208205
return None;
209206
}
210207
let line = unsafe { ffi::merve_get_reexport_line(self.handle, index) };
211-
if line == 0 {
212-
None
213-
} else {
214-
Some(line)
215-
}
208+
NonZeroU32::new(line)
216209
}
217210

218211
/// Iterate over all named exports.
@@ -253,7 +246,7 @@ pub struct Export<'a> {
253246
/// The export name (or module specifier for re-exports).
254247
pub name: &'a str,
255248
/// 1-based source line number.
256-
pub line: u32,
249+
pub line: NonZeroU32,
257250
}
258251

259252
impl fmt::Display for Export<'_> {
@@ -290,12 +283,20 @@ impl<'a, 'b> Iterator for ExportIter<'a, 'b> {
290283
self.index += 1;
291284
let (name, line) = match self.kind {
292285
ExportKind::Export => (
293-
self.analysis.export_name(i).unwrap_or(""),
294-
self.analysis.export_line(i).unwrap_or(0),
286+
self.analysis
287+
.export_name(i)
288+
.expect("invariant: export index is in bounds"),
289+
self.analysis
290+
.export_line(i)
291+
.expect("invariant: export line is non-zero and in bounds"),
295292
),
296293
ExportKind::ReExport => (
297-
self.analysis.reexport_name(i).unwrap_or(""),
298-
self.analysis.reexport_line(i).unwrap_or(0),
294+
self.analysis
295+
.reexport_name(i)
296+
.expect("invariant: re-export index is in bounds"),
297+
self.analysis
298+
.reexport_line(i)
299+
.expect("invariant: re-export line is non-zero and in bounds"),
299300
),
300301
};
301302
Some(Export { name, line })
@@ -402,6 +403,7 @@ pub fn version_components() -> (i32, i32, i32) {
402403
#[cfg(test)]
403404
mod tests {
404405
use super::*;
406+
use core::num::NonZeroU32;
405407

406408
#[test]
407409
fn version_is_not_empty() {
@@ -486,9 +488,9 @@ mod tests {
486488
fn export_lines() {
487489
let source = "exports.a = 1;\nexports.b = 2;\nexports.c = 3;";
488490
let analysis = parse_commonjs(source).expect("should parse");
489-
assert_eq!(analysis.export_line(0), Some(1));
490-
assert_eq!(analysis.export_line(1), Some(2));
491-
assert_eq!(analysis.export_line(2), Some(3));
491+
assert_eq!(analysis.export_line(0), NonZeroU32::new(1));
492+
assert_eq!(analysis.export_line(1), NonZeroU32::new(2));
493+
assert_eq!(analysis.export_line(2), NonZeroU32::new(3));
492494
}
493495

494496
#[cfg(feature = "std")]
@@ -535,7 +537,7 @@ mod tests {
535537
fn export_display_impl() {
536538
let e = Export {
537539
name: "foo",
538-
line: 42,
540+
line: NonZeroU32::new(42).unwrap(),
539541
};
540542
assert_eq!(format!("{e}"), "foo (line 42)");
541543
}

0 commit comments

Comments
 (0)