@@ -14,7 +14,7 @@ use internals::compact_size;
1414use internals:: wrap_debug:: WrapDebug ;
1515use internals:: slice:: SliceExt ;
1616
17- use crate :: prelude:: Vec ;
17+ use crate :: prelude:: { Box , Vec } ;
1818
1919/// The Witness is the data used to unlock bitcoin since the [SegWit upgrade].
2020///
@@ -238,6 +238,109 @@ fn decode_cursor(bytes: &[u8], start_of_indices: usize, index: usize) -> Option<
238238 bytes. get_array :: < 4 > ( start) . map ( |index_bytes| u32:: from_ne_bytes ( * index_bytes) as usize )
239239}
240240
241+ // Note: we use `Borrow` in the following `PartialEq` impls specifically because of its additional
242+ // constraints on equality semantics.
243+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < [ T ] > for Witness {
244+ fn eq ( & self , rhs : & [ T ] ) -> bool {
245+ if self . len ( ) != rhs. len ( ) {
246+ return false ;
247+ }
248+ self . iter ( ) . zip ( rhs) . all ( |( left, right) | left == right. borrow ( ) )
249+ }
250+ }
251+
252+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < & [ T ] > for Witness {
253+ fn eq ( & self , rhs : & & [ T ] ) -> bool {
254+ * self == * * rhs
255+ }
256+ }
257+
258+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for [ T ] {
259+ fn eq ( & self , rhs : & Witness ) -> bool {
260+ * rhs == * self
261+ }
262+ }
263+
264+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for & [ T ] {
265+ fn eq ( & self , rhs : & Witness ) -> bool {
266+ * rhs == * * self
267+ }
268+ }
269+
270+ impl < const N : usize , T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < [ T ; N ] > for Witness {
271+ fn eq ( & self , rhs : & [ T ; N ] ) -> bool {
272+ * self == * rhs. as_slice ( )
273+ }
274+ }
275+
276+ impl < const N : usize , T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < & [ T ; N ] > for Witness {
277+ fn eq ( & self , rhs : & & [ T ; N ] ) -> bool {
278+ * self == * rhs. as_slice ( )
279+ }
280+ }
281+
282+ impl < const N : usize , T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for [ T ; N ] {
283+ fn eq ( & self , rhs : & Witness ) -> bool {
284+ * rhs == * self
285+ }
286+ }
287+
288+ impl < const N : usize , T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for & [ T ; N ] {
289+ fn eq ( & self , rhs : & Witness ) -> bool {
290+ * rhs == * * self
291+ }
292+ }
293+
294+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Vec < T > > for Witness {
295+ fn eq ( & self , rhs : & Vec < T > ) -> bool {
296+ * self == * * rhs
297+ }
298+ }
299+
300+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for Vec < T > {
301+ fn eq ( & self , rhs : & Witness ) -> bool {
302+ * rhs == * self
303+ }
304+ }
305+
306+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Box < [ T ] > > for Witness {
307+ fn eq ( & self , rhs : & Box < [ T ] > ) -> bool {
308+ * self == * * rhs
309+ }
310+ }
311+
312+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for Box < [ T ] > {
313+ fn eq ( & self , rhs : & Witness ) -> bool {
314+ * rhs == * self
315+ }
316+ }
317+
318+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < alloc:: rc:: Rc < [ T ] > > for Witness {
319+ fn eq ( & self , rhs : & alloc:: rc:: Rc < [ T ] > ) -> bool {
320+ * self == * * rhs
321+ }
322+ }
323+
324+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for alloc:: rc:: Rc < [ T ] > {
325+ fn eq ( & self , rhs : & Witness ) -> bool {
326+ * rhs == * self
327+ }
328+ }
329+
330+ #[ cfg( target_has_atomic = "ptr" ) ]
331+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < alloc:: sync:: Arc < [ T ] > > for Witness {
332+ fn eq ( & self , rhs : & alloc:: sync:: Arc < [ T ] > ) -> bool {
333+ * self == * * rhs
334+ }
335+ }
336+
337+ #[ cfg( target_has_atomic = "ptr" ) ]
338+ impl < T : core:: borrow:: Borrow < [ u8 ] > > PartialEq < Witness > for alloc:: sync:: Arc < [ T ] > {
339+ fn eq ( & self , rhs : & Witness ) -> bool {
340+ * rhs == * self
341+ }
342+ }
343+
241344/// Debug implementation that displays the witness as a structured output containing:
242345/// - Number of witness elements
243346/// - Total bytes across all elements
@@ -410,6 +513,46 @@ impl From<Vec<&[u8]>> for Witness {
410513 fn from ( vec : Vec < & [ u8 ] > ) -> Self { Witness :: from_slice ( & vec) }
411514}
412515
516+ impl < const N : usize > From < [ & [ u8 ] ; N ] > for Witness {
517+ #[ inline]
518+ fn from ( arr : [ & [ u8 ] ; N ] ) -> Self { Witness :: from_slice ( & arr) }
519+ }
520+
521+ impl < const N : usize > From < & [ & [ u8 ] ; N ] > for Witness {
522+ #[ inline]
523+ fn from ( arr : & [ & [ u8 ] ; N ] ) -> Self { Witness :: from_slice ( arr) }
524+ }
525+
526+ impl < const N : usize > From < & [ [ u8 ; N ] ] > for Witness {
527+ #[ inline]
528+ fn from ( slice : & [ [ u8 ; N ] ] ) -> Self { Witness :: from_slice ( slice) }
529+ }
530+
531+ impl < const N : usize > From < & [ & [ u8 ; N ] ] > for Witness {
532+ #[ inline]
533+ fn from ( slice : & [ & [ u8 ; N ] ] ) -> Self { Witness :: from_slice ( slice) }
534+ }
535+
536+ impl < const N : usize , const M : usize > From < [ [ u8 ; M ] ; N ] > for Witness {
537+ #[ inline]
538+ fn from ( slice : [ [ u8 ; M ] ; N ] ) -> Self { Witness :: from_slice ( & slice) }
539+ }
540+
541+ impl < const N : usize , const M : usize > From < & [ [ u8 ; M ] ; N ] > for Witness {
542+ #[ inline]
543+ fn from ( slice : & [ [ u8 ; M ] ; N ] ) -> Self { Witness :: from_slice ( slice) }
544+ }
545+
546+ impl < const N : usize , const M : usize > From < [ & [ u8 ; M ] ; N ] > for Witness {
547+ #[ inline]
548+ fn from ( slice : [ & [ u8 ; M ] ; N ] ) -> Self { Witness :: from_slice ( & slice) }
549+ }
550+
551+ impl < const N : usize , const M : usize > From < & [ & [ u8 ; M ] ; N ] > for Witness {
552+ #[ inline]
553+ fn from ( slice : & [ & [ u8 ; M ] ; N ] ) -> Self { Witness :: from_slice ( slice) }
554+ }
555+
413556impl Default for Witness {
414557 #[ inline]
415558 fn default ( ) -> Self { Self :: new ( ) }
@@ -438,11 +581,7 @@ mod test {
438581
439582 // A witness with a single element that is empty (zero length).
440583 fn single_empty_element ( ) -> Witness {
441- // The first is 0 serialized as a compact size integer.
442- // The last four bytes represent start at index 0.
443- let content = [ 0_u8 ; 5 ] ;
444-
445- Witness { witness_elements : 1 , content : content. to_vec ( ) , indices_start : 1 }
584+ Witness :: from ( [ [ 0u8 ; 0 ] ] )
446585 }
447586
448587 #[ test]
@@ -477,13 +616,7 @@ mod test {
477616 witness. push ( push) ;
478617 assert ! ( !witness. is_empty( ) ) ;
479618
480- let elements = [ 1u8 , 11 ] ;
481- let expected = Witness {
482- witness_elements : 1 ,
483- content : append_u32_vec ( & elements, & [ 0 ] ) , // Start at index 0.
484- indices_start : elements. len ( ) ,
485- } ;
486- assert_eq ! ( witness, expected) ;
619+ assert_eq ! ( witness, [ [ 11_u8 ] ] ) ;
487620
488621 let element_0 = push. as_slice ( ) ;
489622 assert_eq ! ( element_0, & witness[ 0 ] ) ;
@@ -500,13 +633,7 @@ mod test {
500633 let push = [ 21u8 , 22u8 ] ;
501634 witness. push ( push) ;
502635
503- let elements = [ 1u8 , 11 , 2 , 21 , 22 ] ;
504- let expected = Witness {
505- witness_elements : 2 ,
506- content : append_u32_vec ( & elements, & [ 0 , 2 ] ) ,
507- indices_start : elements. len ( ) ,
508- } ;
509- assert_eq ! ( witness, expected) ;
636+ assert_eq ! ( witness, [ & [ 11_u8 ] as & [ _] , & [ 21 , 22 ] ] ) ;
510637
511638 let element_1 = push. as_slice ( ) ;
512639 assert_eq ! ( element_1, & witness[ 1 ] ) ;
@@ -523,13 +650,7 @@ mod test {
523650 let push = [ 31u8 , 32u8 ] ;
524651 witness. push ( push) ;
525652
526- let elements = [ 1u8 , 11 , 2 , 21 , 22 , 2 , 31 , 32 ] ;
527- let expected = Witness {
528- witness_elements : 3 ,
529- content : append_u32_vec ( & elements, & [ 0 , 2 , 5 ] ) ,
530- indices_start : elements. len ( ) ,
531- } ;
532- assert_eq ! ( witness, expected) ;
653+ assert_eq ! ( witness, [ & [ 11_u8 ] as & [ _] , & [ 21 , 22 ] , & [ 31 , 32 ] ] ) ;
533654
534655 let element_2 = push. as_slice ( ) ;
535656 assert_eq ! ( element_2, & witness[ 2 ] ) ;
@@ -603,6 +724,27 @@ mod test {
603724 assert ! ( expected. is_empty( ) ) ;
604725 }
605726
727+ #[ test]
728+ fn partial_eq ( ) {
729+ const EMPTY_BYTES : & [ u8 ] = & [ ] ;
730+ assert_eq ! ( Vec :: <& [ u8 ] >:: new( ) , Witness :: new( ) ) ;
731+ macro_rules! ck {
732+ ( $container: expr) => {
733+ {
734+ let container = $container;
735+ let witness = Witness :: from( Clone :: clone( & container) ) ;
736+ assert_eq!( witness, container, stringify!( $container) ) ;
737+ }
738+ }
739+ }
740+ ck ! ( [ EMPTY_BYTES ] ) ;
741+ ck ! ( [ EMPTY_BYTES , EMPTY_BYTES ] ) ;
742+ ck ! ( [ [ 42 ] ] ) ;
743+ ck ! ( [ [ 42 , 21 ] ] ) ;
744+ ck ! ( [ & [ 42 ] , EMPTY_BYTES ] ) ;
745+ ck ! ( [ [ 42u8 ] , [ 21 ] ] ) ;
746+ }
747+
606748 #[ test]
607749 #[ cfg( feature = "serde" ) ]
608750 fn serde_bincode_backward_compatibility ( ) {
0 commit comments