Skip to content

Commit af49fb4

Browse files
committed
Tidying
1 parent f53ac78 commit af49fb4

File tree

9 files changed

+81
-62
lines changed

9 files changed

+81
-62
lines changed

Cargo.lock

Lines changed: 0 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

complex-indifference/src/index.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ impl<T: ?Sized> Index<T> {
3535
self.index
3636
}
3737

38-
pub fn up_to(&self, ix: Index<T>) -> Span<T> {
38+
pub fn up_to(&self, ix: Index<T>) -> Option<Span<T>> {
3939
debug_assert!(
4040
*self <= ix,
4141
"cannot go up_to a lower index: {} > {}",
4242
self.index,
4343
ix.index
4444
);
4545

46-
Span::from_indices(*self, ix)
46+
Span::try_from_indices(*self, ix)
4747
}
4848
}
4949

complex-indifference/src/span.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{Count, Index};
22

3-
/// A range of [`Index`]es.
3+
/// A non-empty range of [`Index`]es.
44
#[derive(Debug, PartialEq, Eq)]
55
pub struct Span<T: ?Sized> {
66
start: Index<T>,
@@ -30,10 +30,10 @@ impl<T: ?Sized> From<(Index<T>, Count<T>)> for Span<T> {
3030
}
3131
}
3232

33-
// TODO: this is really try-from
34-
impl<T: ?Sized> From<(Index<T>, Index<T>)> for Span<T> {
35-
fn from(value: (Index<T>, Index<T>)) -> Self {
36-
Self::from_indices(value.0, value.1)
33+
impl<T: ?Sized> TryFrom<(Index<T>, Index<T>)> for Span<T> {
34+
type Error = ();
35+
fn try_from(value: (Index<T>, Index<T>)) -> Result<Self, ()> {
36+
Self::try_from_indices(value.0, value.1).ok_or(())
3737
}
3838
}
3939

@@ -45,8 +45,16 @@ impl<T: ?Sized> Span<T> {
4545
}
4646
}
4747

48-
pub fn from_indices(start: Index<T>, end: Index<T>) -> Self {
49-
debug_assert!(
48+
pub fn try_from_indices(start: Index<T>, end: Index<T>) -> Option<Self> {
49+
if start > end {
50+
None
51+
} else {
52+
Some(Self { start, end })
53+
}
54+
}
55+
56+
pub fn unsafe_from_indices(start: Index<T>, end: Index<T>) -> Self {
57+
assert!(
5058
start <= end,
5159
"indices are in the wrong order: {} > {}",
5260
start.index(),

errful/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,13 @@ edition.workspace = true
99
complex-indifference = { path = "../complex-indifference", features = ["unicode-width"] }
1010
derive_more = { version = "1.0.0", features = ["from", "display", "error"] }
1111
errful-derive = { path = "../errful-derive" }
12-
impls = "1.0.3"
13-
mappable-rc = "0.1.1"
1412
owo-colors = { version = "4.0.0" }
1513
ref-cast = "1.0.23"
1614
snippets = { path = "../snippets" }
1715
textwrap = { version = "0.16.1", features = ["terminal_size"] }
1816
unicode-width = "0.2.0"
1917
url = "2.5.2"
2018
url-macro = "0.2"
21-
yoke = "0.7.4"
2219

2320
[dev-dependencies]
2421
ansi-to-html = "0.2.1"

errful/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ pub mod result;
1212
pub use complex_indifference::Span;
1313
pub use errful_derive::Error;
1414
pub use formatting::PrettyDisplay;
15-
#[doc(hidden)]
16-
pub use impls::impls;
1715
pub use protocol::{AsErrful, Errful};
1816
pub use result::MainResult;
1917

errful/src/protocol.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! - Types which are specific to this crate are provided by providing a
1212
//! reference to the [`Errful`] trait from this crate. This is used for non-specific
1313
//! types such as labels, source code, etc.
14-
//!
14+
//!
1515
//! The reason for this is that the `provide` method cannot distinguish between
1616
//! multiple values of the same type, so it would be necessary to define wrapper
1717
//! types anyway (e.g. `struct Code(str)` – this is how an earlier version of this
@@ -23,6 +23,8 @@
2323
//! (`T + 'static`) or a reference (`&'self (T + 'static)`), but something like
2424
//! `Vec<&'self (T + 'static)>` is not possible.
2525
//!
26+
//! ## Notes
27+
//!
2628
//! An earlier version of this trait returned a `Vec<Box<dyn ErrField>>` where `ErrField`
2729
//! is implemented by a zero-sized type representing the field. This then allowed reading
2830
//! the specific field from the error and turn this into a `Vec<&dyn Error>` (for example).

errful/src/result.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@ impl<E> MainResult<E> {
2323
}
2424
}
2525

26+
impl<E> From<Result<(), E>> for MainResult<E> {
27+
fn from(value: Result<(), E>) -> Self {
28+
match value {
29+
Ok(()) => MainResult::success(),
30+
Err(err) => MainResult::error(err),
31+
}
32+
}
33+
}
34+
35+
impl<E> From<Result<std::process::ExitCode, E>> for MainResult<E> {
36+
fn from(value: Result<std::process::ExitCode, E>) -> Self {
37+
match value {
38+
Ok(code) => MainResult::exit_code(code),
39+
Err(err) => MainResult::error(err),
40+
}
41+
}
42+
}
43+
2644
impl<Err> std::ops::FromResidual<Result<Infallible, Err>> for MainResult<Err> {
2745
fn from_residual(residual: Result<Infallible, Err>) -> Self {
2846
match residual {
@@ -54,12 +72,3 @@ impl<E: Error> Termination for MainResult<E> {
5472
}
5573
}
5674
}
57-
58-
impl<E> From<Result<(), E>> for MainResult<E> {
59-
fn from(value: Result<(), E>) -> Self {
60-
match value {
61-
Ok(()) => MainResult::Code(ExitCode::SUCCESS),
62-
Err(err) => MainResult::Err(err),
63-
}
64-
}
65-
}

snippets/src/lib.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ pub fn render(source_code: &str, mut labels: Vec1<Label>) -> String {
2727
let span = label.span;
2828
let start_ix = source_code.floor_char_boundary(span.start().index());
2929
let end_ix = source_code.ceil_char_boundary(span.end().index());
30-
label.span = Span::from_indices(start_ix.into(), end_ix.into());
30+
// UNWRAP: since span is already ordered, we know that start_ix <= end_ix
31+
label.span = Span::try_from_indices(start_ix.into(), end_ix.into()).unwrap();
3132
}
3233

3334
Highlighter::new(source_code).render_spans(labels.into())
@@ -108,8 +109,7 @@ impl Highlighter<'_> {
108109
.unwrap_or(self.source_code.len())
109110
.into();
110111

111-
let line_span = Span::from((start_of_line, end_of_line));
112-
112+
let line_span = Span::try_from((start_of_line, end_of_line)).unwrap();
113113
debug_assert!(
114114
line_span.contains_offset(span.start())
115115
|| (span.len() == Count::ZERO && span.start() == line_span.end())
@@ -421,8 +421,9 @@ impl LineHighlighter<'_> {
421421
// |← offset_to_space →|
422422
// [l.start]----
423423
// |← offset_from_start? →|
424-
let offset_from_start =
425-
self.source_code[line_start.up_to(l.start())].width();
424+
let offset_from_start = self.source_code
425+
[line_start.up_to(l.start()).expect("l.start >= line_start")]
426+
.width();
426427

427428
if offset_from_start == offset_to_space {
428429
Some(&l.style)
@@ -452,7 +453,10 @@ impl LineHighlighter<'_> {
452453
};
453454

454455
debug_assert!(line_start <= label.start());
455-
let indent_width = self.source_code[line_start.up_to(label.start())].width();
456+
let indent_width = self.source_code[line_start
457+
.up_to(label.start())
458+
.expect("label.start >= line_start")]
459+
.width();
456460

457461
// 2 chars at start of messages: "└╴"
458462
const MSG_PREFIX_WIDTH: usize = 2;
@@ -484,7 +488,9 @@ impl LineHighlighter<'_> {
484488
// |← total_width →|← len? →|
485489
// [l.start]-------
486490
// |← offset_from_start →|
487-
let offset_from_start = self.source_code[line_start.up_to(l.start())].width();
491+
let offset_from_start = self.source_code
492+
[line_start.up_to(l.start()).expect("l.start >= line_start")]
493+
.width();
488494
if let Some(len) = offset_from_start.checked_sub(total_width) {
489495
if len > 0 {
490496
out.push(no_style.style(" ".repeat(len).into()));
@@ -517,7 +523,10 @@ impl LineHighlighter<'_> {
517523
let end = min(wanted_end, label.start());
518524

519525
// emit highlighted portion of line
520-
let value = Span::from_indices(up_to, end).str(self.source_code);
526+
// UNWRAP: since start is > up_to, end must be as well
527+
let value = Span::try_from_indices(up_to, end)
528+
.unwrap()
529+
.str(self.source_code);
521530
self.line.push(outer_label.style.style(value.into()));
522531

523532
// emit indicator line
@@ -543,14 +552,17 @@ impl LineHighlighter<'_> {
543552
// if we still didn’t get to the start of the next label
544553
// then there is an unhighlighted gap
545554
if label.start() > up_to {
546-
// emit unhighlighted characters
547-
let value = &self.source_code[up_to.up_to(label.start())];
548-
self.line.push(no_style.style(value.into()));
549-
// space indicator line wide enough
550-
self.indicator_line
551-
.push(no_style.style(" ".repeat(value.width()).into()));
552-
553-
up_to = label.start();
555+
// the first check ensures that start > up_to, .up_to() will allow start >= up_to
556+
if let Some(slice) = up_to.up_to(label.start()) {
557+
// emit unhighlighted characters
558+
let value = &self.source_code[slice];
559+
self.line.push(no_style.style(value.into()));
560+
// space indicator line wide enough
561+
self.indicator_line
562+
.push(no_style.style(" ".repeat(value.width()).into()));
563+
564+
up_to = label.start();
565+
}
554566
}
555567
}
556568

@@ -560,10 +572,11 @@ impl LineHighlighter<'_> {
560572

561573
while let Some(label) = stack.pop() {
562574
let end = label.end();
563-
if up_to <= end {
575+
576+
if let Some(slice) = up_to.up_to(end) {
564577
// TODO: what are the effects of this check?
565578
// it prevents a crash found by fuzzing but might skip a message?
566-
let value = &self.source_code[up_to.up_to(end)];
579+
let value = &self.source_code[slice];
567580
let continuing = label.start() < up_to;
568581
self.fill_indicator(continuing, false, value, &label.style);
569582
self.line.push(label.style.style(value.into()));
@@ -574,10 +587,13 @@ impl LineHighlighter<'_> {
574587

575588
// if we didn't reach the end, we need to emit the rest
576589
if up_to < line_span.end() {
577-
// emit unhighlighted characters
578-
let value = self.source_code[up_to.up_to(line_span.end())].trim_ascii_end();
579-
self.line.push(no_style.style(value.into()));
580-
// indicator line doesn't need spacing
590+
// note that .up_to() would allow <= line_span.end()
591+
if let Some(slice) = up_to.up_to(line_span.end()) {
592+
// emit unhighlighted characters
593+
let value = self.source_code[slice].trim_ascii_end();
594+
self.line.push(no_style.style(value.into()));
595+
// indicator line doesn't need spacing
596+
}
581597
}
582598

583599
// emit all messages now that we know the full order

snippets/tests/render_test/main.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ fn main() {
2323
.iter()
2424
.map(|l| {
2525
Label::new(
26-
Span::from_indices(min(l.start, l.end).into(), max(l.start, l.end).into()),
26+
Span::try_from_indices(
27+
min(l.start, l.end).into(),
28+
max(l.start, l.end).into(),
29+
)
30+
.unwrap(),
2731
l.label.deref().into(),
2832
style,
2933
)

0 commit comments

Comments
 (0)