From 384af079a8ce1127e678b3134ae20f84f0fd87cc Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 12 Jul 2021 13:35:06 +0100 Subject: [PATCH] zcash_address: Add `unified::Address::receivers{_as_parsed}` APIs These expose the receivers in sorted order, and in parsed order. --- components/zcash_address/src/kind/unified.rs | 47 +++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/components/zcash_address/src/kind/unified.rs b/components/zcash_address/src/kind/unified.rs index 312f77be3..0f8a6fd8f 100644 --- a/components/zcash_address/src/kind/unified.rs +++ b/components/zcash_address/src/kind/unified.rs @@ -145,7 +145,7 @@ impl Error for ParseError {} /// > When derived on enums, variants are ordered by their top-to-bottom discriminant /// > order. #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub(crate) enum Receiver { +pub enum Receiver { Orchard([u8; 43]), Sapling(kind::sapling::Data), P2pkh(kind::p2pkh::Data), @@ -287,6 +287,23 @@ impl Address { f4jumble::f4jumble(&encoded).unwrap() } + + /// Returns the receivers contained within this address, sorted in preference order. + pub fn receivers(&self) -> Vec { + let mut receivers = self.0.clone(); + // Unstable sorting is fine, because all receivers are guaranteed by construction + // to have distinct typecodes. + receivers.sort_unstable_by_key(|r| r.typecode()); + receivers + } + + /// Returns the receivers contained within this address, in the order they were + /// parsed from the string encoding. + /// + /// This API is for advanced usage; in most cases you should use `Address::receivers`. + pub fn receivers_as_parsed(&self) -> &[Receiver] { + &self.0 + } } #[cfg(test)] @@ -383,4 +400,32 @@ mod tests { Err(ParseError::InvalidEncoding) ); } + + #[test] + fn receivers_are_sorted() { + // Construct a UA with receivers in an unsorted order. + let ua = Address(vec![ + Receiver::P2pkh([0; 20]), + Receiver::Orchard([0; 43]), + Receiver::Unknown { + typecode: 0xff, + data: vec![], + }, + Receiver::Sapling([0; 43]), + ]); + + // `Address::receivers` sorts the receivers in priority order. + assert_eq!( + ua.receivers(), + vec![ + Receiver::Orchard([0; 43]), + Receiver::Sapling([0; 43]), + Receiver::P2pkh([0; 20]), + Receiver::Unknown { + typecode: 0xff, + data: vec![], + }, + ] + ) + } }