Skip to content

Commit 8386dc6

Browse files
committed
Improve crate documentation
With upcoming decoding stabilization we need to inform users about details of the stabilization and make sure our API doc is understandable. This makes various doc improvements including explaining how we're going to stabilize things and feature flags.
1 parent 6170d45 commit 8386dc6

File tree

3 files changed

+85
-14
lines changed

3 files changed

+85
-14
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@
22

33
General purpose hex encoding/decoding library with a conservative MSRV and dependency policy.
44

5+
## Stabilization strategy
6+
7+
Because downstream crates may need to return hex errors in their APIs and they need to be
8+
stabilized soon, this crate only exposes the errors and two basic decoding functions. This
9+
should already help with the vast majority of the cases and we're sufficiently confident that
10+
these errors won't have a breaking change any time soon (possibly never).
11+
12+
If you're writing a binary you don't need to worry about any of this and just use the unstable
13+
version for now. If you're writing a library you should use these stable errors in the API but
14+
you may internally depend on the unstable crate version to get the advanced features that won't
15+
affect your API. This way your API can stabilize before all features in this crate are fully
16+
stable and you still can use all of them.
17+
18+
## Crate feature flags
19+
20+
* `std` - enables the standard library, on by default.
21+
* `alloc` - enables features that require allocation such as decoding into `Vec<u8>`, implied
22+
by `std`.
23+
* `newer-rust-version` - enables Rust version detection and thus newer features, may add
24+
dependency on a feature detection crate to reduce compile times. This
25+
feature is expected to do nothing once the native detection is in Rust
26+
and our MSRV is at least that version. We may also remove the feature
27+
gate in 2.0 with semver trick once that happens.
28+
529
## Minimum Supported Rust Version (MSRV)
630

731
This library should compile with almost any combination of features on **Rust 1.63.0**, however we

src/error.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,18 @@ macro_rules! write_err {
6565
}
6666
pub(crate) use write_err;
6767

68-
/// Hex decoding error.
68+
/// Error returned when hex decoding a hex string with variable length.
69+
///
70+
/// This represents the first error encountered during decoding, however we may add other remaining
71+
/// ones in the future.
72+
///
73+
/// This error differs from [`HexToArrayError`] in that the number of bytes is only known at
74+
/// run time - e.g. when decoding `Vec<u8>`.
6975
#[derive(Debug, Clone, PartialEq, Eq)]
7076
pub enum HexToBytesError {
7177
/// Non-hexadecimal character.
7278
InvalidChar(InvalidCharError),
73-
/// Purported hex string had odd length.
79+
/// Purported hex string had odd (not even) length.
7480
OddLengthString(OddLengthStringError),
7581
}
7682

@@ -272,7 +278,10 @@ if_std_error! {{
272278
impl StdError for OddLengthStringError {}
273279
}}
274280

275-
/// Hex decoding error.
281+
/// Error returned when hex decoding bytes whose length is known at compile time.
282+
///
283+
/// This error differs from [`HexToBytesError`] in that the number of bytes is known at
284+
/// compile time - e.g. when decoding to an array of bytes.
276285
#[derive(Debug, Clone, PartialEq, Eq)]
277286
pub enum HexToArrayError {
278287
/// Non-hexadecimal character.
@@ -364,9 +373,16 @@ impl From<Infallible> for InvalidLengthError {
364373

365374
impl InvalidLengthError {
366375
/// Returns the expected length.
376+
///
377+
/// Note that this represents both the number of bytes and the number of characters that needs
378+
/// to be passed into the decoder, since the hex digits are ASCII and thus always 1-byte long.
367379
#[inline]
368380
pub fn expected_length(&self) -> usize { self.expected }
369-
/// Returns the position of the invalid character byte.
381+
382+
/// Returns the number of *hex bytes* passed to the hex decoder.
383+
///
384+
/// Note that this does not imply the number of characters nor hex digits since they may be
385+
/// invalid (wide unicode chars).
370386
#[inline]
371387
pub fn invalid_length(&self) -> usize { self.invalid }
372388
}

src/lib.rs

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@
3434
//! # }
3535
//! ```
3636
//!
37+
//! ## Stabilization strategy
38+
//!
39+
//! Because downstream crates may need to return hex errors in their APIs and they need to be
40+
//! stabilized soon, this crate only exposes the errors and two basic decoding functions. This
41+
//! should already help with the vast majority of the cases and we're sufficiently confident that
42+
//! these errors won't have a breaking change any time soon (possibly never).
43+
//!
44+
//! If you're writing a binary you don't need to worry about any of this and just use the unstable
45+
//! version for now. If you're writing a library you should use these stable errors in the API but
46+
//! you may internally depend on the unstable crate version to get the advanced features that won't
47+
//! affect your API. This way your API can stabilize before all features in this crate are fully
48+
//! stable and you still can use all of them.
49+
//!
50+
//! ## Crate feature flags
51+
//!
52+
//! * `std` - enables the standard library, on by default.
53+
//! * `alloc` - enables features that require allocation such as decoding into `Vec<u8>`, implied
54+
//! by `std`.
55+
//! * `newer-rust-version` - enables Rust version detection and thus newer features, may add
56+
//! dependency on a feature detection crate to reduce compile times. This feature is expected to
57+
//! do nothing once the native detection is in Rust and our MSRV is at least that version. We may
58+
//! also remove the feature gate in 2.0 with semver trick once that happens.
59+
//!
3760
//! ## MSRV policy
3861
//!
3962
//! The MSRV of the crate is currently 1.63.0 and we don't intend to bump it until the newer Rust
@@ -97,29 +120,37 @@ pub use self::{
97120
parse::FromHex,
98121
};
99122

100-
/// Decodes a hex string into a vector of bytes.
123+
/// Decodes a hex string with variable length.
124+
///
125+
/// The length of the returned `Vec` is determined by the length of the input, meaning all even
126+
/// lengths of the input string are allowed. If you know the required length at compile time using
127+
/// [`decode_to_array`] is most likely a better choice.
101128
///
102129
/// # Errors
103130
///
104-
/// Errors if `s` is not a valid hex string.
131+
/// Returns an error if `hex` contains invalid characters or doesn't have even length.
105132
#[cfg(feature = "alloc")]
106-
pub fn decode_to_vec(s: &str) -> Result<Vec<u8>, HexToBytesError> {
107-
Ok(HexToBytesIter::new(s)?.drain_to_vec()?)
133+
pub fn decode_to_vec(hex: &str) -> Result<Vec<u8>, HexToBytesError> {
134+
Ok(HexToBytesIter::new(hex)?.drain_to_vec()?)
108135
}
109136

110-
/// Decodes a hex string into an array of bytes.
137+
/// Decodes a hex string with an expected length kown at compile time.
138+
///
139+
/// If you don't know the required length at compile time you need to use [`decode_to_vec`]
140+
/// instead.
111141
///
112142
/// # Errors
113143
///
114-
/// Errors if `s` is not a valid hex string or the correct length.
115-
pub fn decode_to_array<const N: usize>(s: &str) -> Result<[u8; N], HexToArrayError> {
116-
if s.len() == N * 2 {
144+
/// Returns an error if `hex` contains invalid characters or has incorrect length. (Should be
145+
/// `N * 2`.)
146+
pub fn decode_to_array<const N: usize>(hex: &str) -> Result<[u8; N], HexToArrayError> {
147+
if hex.len() == N * 2 {
117148
let mut ret = [0u8; N];
118149
// checked above
119-
HexToBytesIter::new_unchecked(s).drain_to_slice(&mut ret)?;
150+
HexToBytesIter::new_unchecked(hex).drain_to_slice(&mut ret)?;
120151
Ok(ret)
121152
} else {
122-
Err(InvalidLengthError { invalid: s.len(), expected: 2 * N }.into())
153+
Err(InvalidLengthError { invalid: hex.len(), expected: 2 * N }.into())
123154
}
124155
}
125156

0 commit comments

Comments
 (0)