Skip to content

Commit 5d8f4b2

Browse files
committed
Merge rust-bitcoin#3156: impl IndexMut for PushBytes (already has Index) and fix/add docs
7c8601a implement IndexMut for PushBytes (Antoni Spaanderman) 71d760b Add and fix documentation on PushBytes's functions (Antoni Spaanderman) Pull request description: ACKs for top commit: Kixunil: ACK 7c8601a tcharding: ACK 7c8601a apoelstra: ACK 7c8601a successfully ran local tests Tree-SHA512: a600dcda638cc727c2a31917e76c2e2f6da57b7044d571a345a919f1c471e0d30b82326492716eacfd9b3ce65c4484430bdd0f2d8ebbd220107cd9259a9faaa6
2 parents f5a9f58 + 7c8601a commit 5d8f4b2

File tree

1 file changed

+37
-14
lines changed

1 file changed

+37
-14
lines changed

bitcoin/src/blockdata/script/push_bytes.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ pub use self::primitive::*;
1515
/// break invariants. Therefore auditing this module should be sufficient.
1616
mod primitive {
1717
use core::ops::{
18-
Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
18+
Bound, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo,
19+
RangeToInclusive,
1920
};
2021

2122
use super::PushBytesError;
@@ -43,53 +44,69 @@ mod primitive {
4344
pub struct PushBytes([u8]);
4445

4546
impl PushBytes {
46-
/// Creates `&Self` without checking the length.
47+
/// Creates `&PushBytes` without checking the length.
4748
///
4849
/// # Safety
4950
///
50-
/// The caller is responsible for checking that the length is less than the [`LIMIT`].
51+
/// The caller is responsible for checking that the length is less than the 2^32.
5152
unsafe fn from_slice_unchecked(bytes: &[u8]) -> &Self {
53+
// SAFETY: The caller must guarantee that bytes.len() < 2^32.
54+
// If that is the case the conversion is sound because &[u8] and &PushBytes
55+
// have the same layout (because of #[repr(transparent)] on PushBytes).
5256
&*(bytes as *const [u8] as *const PushBytes)
5357
}
5458

55-
/// Creates `&mut Self` without checking the length.
59+
/// Creates `&mut PushBytes` without checking the length.
5660
///
5761
/// # Safety
5862
///
59-
/// The caller is responsible for checking that the length is less than the [`LIMIT`].
63+
/// The caller is responsible for checking that the length is less than the 2^32.
6064
unsafe fn from_mut_slice_unchecked(bytes: &mut [u8]) -> &mut Self {
65+
// SAFETY: The caller must guarantee that bytes.len() < 2^32.
66+
// If that is the case the conversion is sound because &mut [u8] and &mut PushBytes
67+
// have the same layout (because of #[repr(transparent)] on PushBytes).
6168
&mut *(bytes as *mut [u8] as *mut PushBytes)
6269
}
6370

64-
/// Creates an empty `PushBytes`.
71+
/// Creates an empty `&PushBytes`.
6572
pub fn empty() -> &'static Self {
66-
// 0 < LIMIT
73+
// SAFETY: 0 < 2^32.
6774
unsafe { Self::from_slice_unchecked(&[]) }
6875
}
6976

7077
/// Returns the underlying bytes.
7178
pub fn as_bytes(&self) -> &[u8] { &self.0 }
7279

73-
/// Returns the underlying mutbale bytes.
80+
/// Returns the underlying mutable bytes.
7481
pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 }
7582
}
7683

7784
macro_rules! delegate_index {
7885
($($type:ty),* $(,)?) => {
7986
$(
80-
/// Script subslicing operation - read [slicing safety](#slicing-safety)!
8187
impl Index<$type> for PushBytes {
8288
type Output = Self;
8389

8490
#[inline]
8591
#[track_caller]
8692
fn index(&self, index: $type) -> &Self::Output {
87-
// Slicing can not make slices longer
93+
// SAFETY: Slicing can not make slices longer.
8894
unsafe {
8995
Self::from_slice_unchecked(&self.0[index])
9096
}
9197
}
9298
}
99+
100+
impl IndexMut<$type> for PushBytes {
101+
#[inline]
102+
#[track_caller]
103+
fn index_mut(&mut self, index: $type) -> &mut Self::Output {
104+
// SAFETY: Slicing can not make slices longer.
105+
unsafe {
106+
Self::from_mut_slice_unchecked(&mut self.0[index])
107+
}
108+
}
109+
}
93110
)*
94111
}
95112
}
@@ -112,12 +129,18 @@ mod primitive {
112129
fn index(&self, index: usize) -> &Self::Output { &self.0[index] }
113130
}
114131

132+
impl IndexMut<usize> for PushBytes {
133+
#[inline]
134+
#[track_caller]
135+
fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.0[index] }
136+
}
137+
115138
impl<'a> TryFrom<&'a [u8]> for &'a PushBytes {
116139
type Error = PushBytesError;
117140

118141
fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
119142
check_limit(bytes.len())?;
120-
// We've just checked the length
143+
// SAFETY: We've just checked the length.
121144
Ok(unsafe { PushBytes::from_slice_unchecked(bytes) })
122145
}
123146
}
@@ -127,7 +150,7 @@ mod primitive {
127150

128151
fn try_from(bytes: &'a mut [u8]) -> Result<Self, Self::Error> {
129152
check_limit(bytes.len())?;
130-
// We've just checked the length
153+
// SAFETY: We've just checked the length.
131154
Ok(unsafe { PushBytes::from_mut_slice_unchecked(bytes) })
132155
}
133156
}
@@ -139,15 +162,15 @@ mod primitive {
139162
fn from(bytes: &'a [u8; $len]) -> Self {
140163
// Check that the macro wasn't called with a wrong number.
141164
const _: () = [(); 1][($len >= 0x100000000u64) as usize];
142-
// We know the size of array statically and we checked macro input.
165+
// SAFETY: We know the size of array statically and we checked macro input.
143166
unsafe { PushBytes::from_slice_unchecked(bytes) }
144167
}
145168
}
146169

147170
impl<'a> From<&'a mut [u8; $len]> for &'a mut PushBytes {
148171
fn from(bytes: &'a mut [u8; $len]) -> Self {
149172
// Macro check already above, no need to duplicate.
150-
// We know the size of array statically and we checked macro input.
173+
// SAFETY: We know the size of array statically and we checked macro input.
151174
unsafe { PushBytes::from_mut_slice_unchecked(bytes) }
152175
}
153176
}

0 commit comments

Comments
 (0)