tidecoin_primitives/script/
push_bytes.rs1use core::fmt;
4use core::ops::{
5 Bound, Deref, DerefMut, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo,
6 RangeToInclusive,
7};
8
9use crate::prelude::{Borrow, BorrowMut, ToOwned, Vec};
10
11#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
12fn check_limit(_: usize) -> Result<(), PushBytesError> {
13 Ok(())
14}
15
16#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
17fn check_limit(len: usize) -> Result<(), PushBytesError> {
18 if len < 0x0001_0000_0000 {
19 Ok(())
20 } else {
21 Err(PushBytesError { len })
22 }
23}
24
25internals::transparent_newtype! {
26 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
28 pub struct PushBytes([u8]);
29
30 impl PushBytes {
31 fn from_slice_unchecked(bytes: &_) -> &Self;
32 fn from_mut_slice_unchecked(bytes: &mut _) -> &mut Self;
33 }
34}
35
36impl PushBytes {
37 pub fn empty() -> &'static Self {
39 Self::from_slice_unchecked(&[])
40 }
41
42 pub fn as_bytes(&self) -> &[u8] {
44 &self.0
45 }
46
47 pub fn as_mut_bytes(&mut self) -> &mut [u8] {
49 &mut self.0
50 }
51
52 pub fn len(&self) -> usize {
54 self.as_bytes().len()
55 }
56
57 pub fn is_empty(&self) -> bool {
59 self.as_bytes().is_empty()
60 }
61
62 pub fn read_scriptint(&self) -> Result<i32, ScriptIntError> {
72 let ret = self.read_scriptint_internal(4)?;
73 Ok(i32::try_from(ret).expect("4 bytes or less fits in i32"))
74 }
75
76 pub fn read_cltv_scriptint(&self) -> Result<i64, ScriptIntError> {
82 self.read_scriptint_internal(5)
83 }
84
85 fn read_scriptint_internal(&self, max_size: usize) -> Result<i64, ScriptIntError> {
86 super::read_scriptnum(self.as_bytes(), true, max_size)
87 }
88}
89
90macro_rules! delegate_index {
91 ($($type:ty),* $(,)?) => {
92 $(
93 impl Index<$type> for PushBytes {
94 type Output = Self;
95
96 #[inline]
97 #[track_caller]
98 fn index(&self, index: $type) -> &Self::Output {
99 Self::from_slice_unchecked(&self.0[index])
100 }
101 }
102
103 impl IndexMut<$type> for PushBytes {
104 #[inline]
105 #[track_caller]
106 fn index_mut(&mut self, index: $type) -> &mut Self::Output {
107 Self::from_mut_slice_unchecked(&mut self.0[index])
108 }
109 }
110 )*
111 }
112}
113
114delegate_index!(
115 Range<usize>,
116 RangeFrom<usize>,
117 RangeTo<usize>,
118 RangeFull,
119 RangeInclusive<usize>,
120 RangeToInclusive<usize>,
121 (Bound<usize>, Bound<usize>)
122);
123
124impl Index<usize> for PushBytes {
125 type Output = u8;
126
127 #[inline]
128 #[track_caller]
129 fn index(&self, index: usize) -> &Self::Output {
130 &self.0[index]
131 }
132}
133
134impl IndexMut<usize> for PushBytes {
135 #[inline]
136 #[track_caller]
137 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
138 &mut self.0[index]
139 }
140}
141
142impl<'a> TryFrom<&'a [u8]> for &'a PushBytes {
143 type Error = PushBytesError;
144
145 fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
146 check_limit(bytes.len())?;
147 Ok(PushBytes::from_slice_unchecked(bytes))
148 }
149}
150
151impl<'a> TryFrom<&'a mut [u8]> for &'a mut PushBytes {
152 type Error = PushBytesError;
153
154 fn try_from(bytes: &'a mut [u8]) -> Result<Self, Self::Error> {
155 check_limit(bytes.len())?;
156 Ok(PushBytes::from_mut_slice_unchecked(bytes))
157 }
158}
159
160macro_rules! from_array {
161 ($($len:literal),* $(,)?) => {
162 $(
163 impl<'a> From<&'a [u8; $len]> for &'a PushBytes {
164 fn from(bytes: &'a [u8; $len]) -> Self {
165 const _: () = [(); 1][($len >= 0x100000000u64) as usize];
166 PushBytes::from_slice_unchecked(bytes)
167 }
168 }
169
170 impl<'a> From<&'a mut [u8; $len]> for &'a mut PushBytes {
171 fn from(bytes: &'a mut [u8; $len]) -> Self {
172 PushBytes::from_mut_slice_unchecked(bytes)
173 }
174 }
175
176 impl AsRef<PushBytes> for [u8; $len] {
177 fn as_ref(&self) -> &PushBytes { self.into() }
178 }
179
180 impl AsMut<PushBytes> for [u8; $len] {
181 fn as_mut(&mut self) -> &mut PushBytes { self.into() }
182 }
183
184 impl From<[u8; $len]> for PushBytesBuf {
185 fn from(bytes: [u8; $len]) -> Self { PushBytesBuf(Vec::from(&bytes)) }
186 }
187
188 impl<'a> From<&'a [u8; $len]> for PushBytesBuf {
189 fn from(bytes: &'a [u8; $len]) -> Self { PushBytesBuf(Vec::from(bytes)) }
190 }
191 )*
192 }
193}
194
195from_array! {
197 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
198 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
199 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
200 71, 72, 73, 74, 75, 76
201}
202
203#[derive(Default, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
205pub struct PushBytesBuf(Vec<u8>);
206
207impl PushBytesBuf {
208 pub const fn new() -> Self {
210 Self(Vec::new())
211 }
212
213 pub fn with_capacity(capacity: usize) -> Self {
215 Self(Vec::with_capacity(capacity))
216 }
217
218 pub fn reserve(&mut self, additional_capacity: usize) {
220 self.0.reserve(additional_capacity);
221 }
222
223 pub fn push(&mut self, byte: u8) -> Result<(), PushBytesError> {
229 check_limit(self.0.len().saturating_add(1))?;
230 self.0.push(byte);
231 Ok(())
232 }
233
234 pub fn extend_from_slice(&mut self, bytes: &[u8]) -> Result<(), PushBytesError> {
240 let len = self.0.len().saturating_add(bytes.len());
241 check_limit(len)?;
242 self.0.extend_from_slice(bytes);
243 Ok(())
244 }
245
246 pub fn pop(&mut self) -> Option<u8> {
248 self.0.pop()
249 }
250
251 #[track_caller]
253 pub fn remove(&mut self, index: usize) -> u8 {
254 self.0.remove(index)
255 }
256
257 pub fn clear(&mut self) {
259 self.0.clear();
260 }
261
262 pub fn truncate(&mut self, len: usize) {
264 self.0.truncate(len);
265 }
266
267 pub fn as_push_bytes(&self) -> &PushBytes {
269 PushBytes::from_slice_unchecked(&self.0)
270 }
271
272 pub fn as_mut_push_bytes(&mut self) -> &mut PushBytes {
274 PushBytes::from_mut_slice_unchecked(&mut self.0)
275 }
276
277 pub(crate) fn inner(&self) -> &Vec<u8> {
278 &self.0
279 }
280
281 pub fn len(&self) -> usize {
283 self.inner().len()
284 }
285
286 pub fn capacity(&self) -> usize {
288 self.inner().capacity()
289 }
290
291 pub fn is_empty(&self) -> bool {
293 self.inner().is_empty()
294 }
295}
296
297impl From<PushBytesBuf> for Vec<u8> {
298 fn from(value: PushBytesBuf) -> Self {
299 value.0
300 }
301}
302
303impl TryFrom<Vec<u8>> for PushBytesBuf {
304 type Error = PushBytesError;
305
306 fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
307 let _: &PushBytes = vec.as_slice().try_into()?;
308 Ok(Self(vec))
309 }
310}
311
312impl ToOwned for PushBytes {
313 type Owned = PushBytesBuf;
314
315 fn to_owned(&self) -> Self::Owned {
316 PushBytesBuf(self.0.to_owned())
317 }
318}
319
320impl AsRef<[u8]> for PushBytes {
321 fn as_ref(&self) -> &[u8] {
322 self.as_bytes()
323 }
324}
325
326impl AsMut<[u8]> for PushBytes {
327 fn as_mut(&mut self) -> &mut [u8] {
328 self.as_mut_bytes()
329 }
330}
331
332impl AsRef<Self> for PushBytes {
333 fn as_ref(&self) -> &Self {
334 self
335 }
336}
337
338impl AsMut<Self> for PushBytes {
339 fn as_mut(&mut self) -> &mut Self {
340 self
341 }
342}
343
344impl AsRef<PushBytes> for PushBytesBuf {
345 fn as_ref(&self) -> &PushBytes {
346 self.as_push_bytes()
347 }
348}
349
350impl AsMut<PushBytes> for PushBytesBuf {
351 fn as_mut(&mut self) -> &mut PushBytes {
352 self.as_mut_push_bytes()
353 }
354}
355
356impl AsRef<[u8]> for PushBytesBuf {
357 fn as_ref(&self) -> &[u8] {
358 self.as_push_bytes().as_bytes()
359 }
360}
361
362impl Deref for PushBytesBuf {
363 type Target = PushBytes;
364
365 fn deref(&self) -> &Self::Target {
366 self.as_push_bytes()
367 }
368}
369
370impl DerefMut for PushBytesBuf {
371 fn deref_mut(&mut self) -> &mut Self::Target {
372 self.as_mut_push_bytes()
373 }
374}
375
376impl Borrow<PushBytes> for PushBytesBuf {
377 fn borrow(&self) -> &PushBytes {
378 self.as_push_bytes()
379 }
380}
381
382impl BorrowMut<PushBytes> for PushBytesBuf {
383 fn borrow_mut(&mut self) -> &mut PushBytes {
384 self.as_mut_push_bytes()
385 }
386}
387
388#[derive(Debug, Clone, PartialEq, Eq)]
390pub struct PushBytesError {
391 pub len: usize,
393}
394
395impl fmt::Display for PushBytesError {
396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
397 write!(
398 f,
399 "attempt to prepare {} bytes to be pushed into script but the limit is 2^32-1",
400 self.len
401 )
402 }
403}
404
405#[cfg(feature = "std")]
406impl std::error::Error for PushBytesError {}
407
408#[derive(Debug, Clone, PartialEq, Eq)]
410#[non_exhaustive]
411pub enum ScriptIntError {
412 NumericOverflow,
414 NonMinimal,
416}
417
418impl fmt::Display for ScriptIntError {
419 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420 match self {
421 Self::NumericOverflow => f.write_str("script integer outside of valid range"),
422 Self::NonMinimal => f.write_str("non-minimal encoded script integer"),
423 }
424 }
425}
426
427#[cfg(feature = "std")]
428impl std::error::Error for ScriptIntError {}