This adds an error type called `ByteCountParseError` with a vanilla
`std::error::Error` implementation. The code could be significantly
compressed with a dependency like `thiserror`.
I opted to implement a separate error type for `parse_byte_count` rather
than using `anyhow`'s small ecosystem of error types there (though they
are used in `<binary>::run`) because it allows pairing diagnostic
results with tests, incl. those already written. This can be helpful in
preventing regressions in error diagnostics.
This significantly changes the structure of potential output of
top-level errors. Before, errors that have a `source` were printed on a
single line, with the `source` omitted. Now, an error with a `source`
will be printed like:
```
Error: <`Display` impl of error>
Caused by:
<`Display` impl of `source` error>
```
If there are multiple `source` errors in a chain, then it will be of the
form:
```
Error: <`Display` impl of error>
Caused by:
0: <`Display` impl of first `source` error>
1: <`Display` impl of `source` of `source` error>
# etc.
```
Now, in practice this never happened before, since the only error
type that ever could return from `<binary>::run` was `std::io::Error`,
which has no `source`. However, `source`s can start being added if, say,
future work involved using `anyhow::Context::context` or custom errors
that implement `std::Error::source` are added to the codebase. I believe
this is a good choice going forward, but I definitely want to foster
discussion and acceptance for it in the open first!
This is technically a breaking change because it halves the upper range
of accepted values for byte counts. I thought that fine under the
assumption it will be rare for users to ever want to specify something
in the upper half of `u64`'s value range, especially considering that
this can pave the way for having negative byte offsets (instead of just
counts).
Technically a breaking change for architectures where
`size_of::<usize>() > size_of::<u64>()`, but that strikes me as
extremely unlikely.
This change is important because most file seek offsets, even on older
architectures with word sizes smaller than `u32`, accept a `u64`. In
particular, Rust's own `std` acknowledges this. So, we're actually going
against prior art in Rust by using a `usize`.
This is technically a breaking change, since the data and behavior of
`Input` is exposed publicly. However, it seems unlikely to me that
clients actually depended on a failure in the case that's being changed.
Consider equality for first and last character of a line.
If the first or last character of a line is not equal to previous character,
the state machine should be set back to probe as the line should not be
squeezed.
The unit tests has been expanded for testing the use case described in #62.
Further the body of all unit tests has been simplified.
Fixes#62
The squeeze feature is implement as for hexdump. Reoccurring lines will
be squeezed together and visualized with an asterisk. Further hexyl
received an additional command line argument '-v|--no-squeezing' to
disable squeezing. Squeezing is enabled by default.
If the squeezing goes until the end of the input data, an empty line
with address next to last line will be printed to indicate the highest
address (again similar to hexdump).