Skip to content

Commit 92146d7

Browse files
committed
Merge #175: Add witness_version functions to CheckedHrpstring
2d7832a Add witness_version functions to CheckedHrpstring (Tobin C. Harding) 3ce7225 Improve docs on `UncheckedHrpstring::witness_version` (Tobin C. Harding) Pull request description: As we did for `UncheckedHrpstring` add functions to the `CheckedHrpstring` struct to allow checking the initial byte of the data part and removing it if required. Add an initial patch that improves the docs on the `UncheckedHrpstring::remove_witness_version` function (this is then copied in patch 2). ACKs for top commit: apoelstra: ACK 2d7832a tested with rust-elements and it works! Tree-SHA512: e380f524c06f8bfa6efe952e835fef66c3620367ed94d6716c6b5070479188ea95d719958292258938c0a3d709810c2da46af35b910e63e0a630776ce0691fbc
2 parents 50d59d6 + 2d7832a commit 92146d7

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

src/primitives/decode.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ impl<'s> UncheckedHrpstring<'s> {
196196
/// Attempts to convert the first character of the data part to a witness version. If this
197197
/// succeeds, and it is a valid version (0..16 inclusive) we return it, otherwise `None`.
198198
///
199+
/// Future calls to [`Self::data_part_ascii`] will still include the witness version, use
200+
/// [`Self::remove_witness_version`] to remove it.
201+
///
199202
/// This function makes no guarantees on the validity of the checksum.
200203
///
201204
/// # Examples
@@ -373,6 +376,68 @@ impl<'s> CheckedHrpstring<'s> {
373376
#[inline]
374377
pub fn data_part_ascii_no_checksum(&self) -> &'s [u8] { self.ascii }
375378

379+
/// Attempts to remove the first byte of the data part, treating it as a witness version.
380+
///
381+
/// If [`Self::witness_version`] succeeds this function removes the first character (witness
382+
/// version byte) from the internal ASCII data part buffer. Future calls to
383+
/// [`Self::data_part_ascii_no_checksum`] will no longer include it.
384+
///
385+
/// # Examples
386+
///
387+
/// ```
388+
/// use bech32::{primitives::decode::CheckedHrpstring, Bech32, Fe32};
389+
///
390+
/// let addr = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
391+
/// let ascii = "ar0srrr7xfkvy5l643lydnw9re59gtzz";
392+
///
393+
/// let mut checked = CheckedHrpstring::new::<Bech32>(&addr).unwrap();
394+
/// let witness_version = checked.remove_witness_version().unwrap();
395+
/// assert_eq!(witness_version, Fe32::Q);
396+
/// assert!(checked.data_part_ascii_no_checksum().iter().eq(ascii.as_bytes().iter()))
397+
/// ```
398+
#[inline]
399+
pub fn remove_witness_version(&mut self) -> Option<Fe32> {
400+
self.witness_version().map(|witver| {
401+
self.ascii = &self.ascii[1..]; // Remove the witness version byte.
402+
witver
403+
})
404+
}
405+
406+
/// Returns the segwit witness version if there is one.
407+
///
408+
/// Attempts to convert the first character of the data part to a witness version. If this
409+
/// succeeds, and it is a valid version (0..16 inclusive) we return it, otherwise `None`.
410+
///
411+
/// Future calls to [`Self::data_part_ascii_no_checksum`] will still include the witness
412+
/// version, use [`Self::remove_witness_version`] to remove it.
413+
///
414+
/// This function makes no guarantees on the validity of the checksum.
415+
///
416+
/// # Examples
417+
///
418+
/// ```
419+
/// use bech32::{primitives::decode::CheckedHrpstring, Bech32, Fe32};
420+
///
421+
/// let addr = "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
422+
///
423+
/// let checked = CheckedHrpstring::new::<Bech32>(&addr).unwrap();
424+
/// assert_eq!(checked.witness_version(), Some(Fe32::Q));
425+
/// ```
426+
#[inline]
427+
pub fn witness_version(&self) -> Option<Fe32> {
428+
let data_part = self.data_part_ascii_no_checksum();
429+
if data_part.is_empty() {
430+
return None;
431+
}
432+
433+
// unwrap ok because we know we gave valid bech32 characters.
434+
let witness_version = Fe32::from_char(data_part[0].into()).unwrap();
435+
if witness_version.to_u8() > 16 {
436+
return None;
437+
}
438+
Some(witness_version)
439+
}
440+
376441
/// Returns an iterator that yields the data part of the parsed bech32 encoded string as [`Fe32`]s.
377442
///
378443
/// Converts the ASCII bytes representing field elements to the respective field elements.

0 commit comments

Comments
 (0)