1use core::borrow::{Borrow, BorrowMut};
6use core::convert::Infallible;
7use core::ops::{Deref, DerefMut};
8
9#[rustfmt::skip] #[doc(inline)]
11pub use self::primitive::{PushBytes, PushBytesBuf};
13
14mod primitive {
17 use alloc::borrow::ToOwned;
18 use alloc::vec::Vec;
19 use core::ops::{
20 Bound, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo,
21 RangeToInclusive,
22 };
23
24 use super::PushBytesError;
25
26 #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
27 fn check_limit(_: usize) -> Result<(), PushBytesError> { Ok(()) }
28
29 #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
30 fn check_limit(len: usize) -> Result<(), PushBytesError> {
31 if len < 0x1_0000_0000 {
32 Ok(())
33 } else {
34 Err(PushBytesError { len })
35 }
36 }
37
38 crate::transparent_newtype! {
40 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
46 pub struct PushBytes([u8]);
47
48 impl PushBytes {
49 fn from_slice_unchecked(bytes: &_) -> &Self;
53
54 fn from_mut_slice_unchecked(bytes: &mut _) -> &mut Self;
58 }
59 }
60
61 impl PushBytes {
62 pub fn empty() -> &'static Self { Self::from_slice_unchecked(&[]) }
64
65 pub fn as_bytes(&self) -> &[u8] { &self.0 }
67
68 pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 }
70 }
71
72 macro_rules! delegate_index {
73 ($($type:ty),* $(,)?) => {
74 $(
75 impl Index<$type> for PushBytes {
76 type Output = Self;
77
78 #[inline]
79 #[track_caller]
80 fn index(&self, index: $type) -> &Self::Output {
81 Self::from_slice_unchecked(&self.0[index])
82 }
83 }
84
85 impl IndexMut<$type> for PushBytes {
86 #[inline]
87 #[track_caller]
88 fn index_mut(&mut self, index: $type) -> &mut Self::Output {
89 Self::from_mut_slice_unchecked(&mut self.0[index])
90 }
91 }
92 )*
93 }
94 }
95
96 delegate_index!(
97 Range<usize>,
98 RangeFrom<usize>,
99 RangeTo<usize>,
100 RangeFull,
101 RangeInclusive<usize>,
102 RangeToInclusive<usize>,
103 (Bound<usize>, Bound<usize>)
104 );
105
106 impl Index<usize> for PushBytes {
107 type Output = u8;
108
109 #[inline]
110 #[track_caller]
111 fn index(&self, index: usize) -> &Self::Output { &self.0[index] }
112 }
113
114 impl IndexMut<usize> for PushBytes {
115 #[inline]
116 #[track_caller]
117 fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.0[index] }
118 }
119
120 impl<'a> TryFrom<&'a [u8]> for &'a PushBytes {
121 type Error = PushBytesError;
122
123 fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
124 check_limit(bytes.len())?;
125 Ok(PushBytes::from_slice_unchecked(bytes))
126 }
127 }
128
129 impl<'a> TryFrom<&'a mut [u8]> for &'a mut PushBytes {
130 type Error = PushBytesError;
131
132 fn try_from(bytes: &'a mut [u8]) -> Result<Self, Self::Error> {
133 check_limit(bytes.len())?;
134 Ok(PushBytes::from_mut_slice_unchecked(bytes))
135 }
136 }
137
138 macro_rules! from_array {
139 ($($len:literal),* $(,)?) => {
140 $(
141 impl<'a> From<&'a [u8; $len]> for &'a PushBytes {
142 fn from(bytes: &'a [u8; $len]) -> Self {
143 const _: () = [(); 1][($len >= 0x100000000u64) as usize];
145 PushBytes::from_slice_unchecked(bytes)
146 }
147 }
148
149 impl<'a> From<&'a mut [u8; $len]> for &'a mut PushBytes {
150 fn from(bytes: &'a mut [u8; $len]) -> Self {
151 PushBytes::from_mut_slice_unchecked(bytes)
154 }
155 }
156
157 impl AsRef<PushBytes> for [u8; $len] {
158 fn as_ref(&self) -> &PushBytes {
159 self.into()
160 }
161 }
162
163 impl AsMut<PushBytes> for [u8; $len] {
164 fn as_mut(&mut self) -> &mut PushBytes {
165 self.into()
166 }
167 }
168
169 impl From<[u8; $len]> for PushBytesBuf {
170 fn from(bytes: [u8; $len]) -> Self {
171 PushBytesBuf(Vec::from(&bytes))
172 }
173 }
174
175 impl<'a> From<&'a [u8; $len]> for PushBytesBuf {
176 fn from(bytes: &'a [u8; $len]) -> Self {
177 PushBytesBuf(Vec::from(bytes))
178 }
179 }
180 )*
181 }
182 }
183
184 from_array! {
186 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,
187 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
188 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
189 71, 72, 73, 74, 75, 76
190 }
191
192 #[derive(Default, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
194 pub struct PushBytesBuf(Vec<u8>);
195
196 impl PushBytesBuf {
197 #[inline]
199 pub const fn new() -> Self { Self(Vec::new()) }
200
201 pub fn with_capacity(capacity: usize) -> Self { Self(Vec::with_capacity(capacity)) }
203
204 pub fn reserve(&mut self, additional_capacity: usize) {
206 self.0.reserve(additional_capacity);
207 }
208
209 #[allow(deprecated)]
215 pub fn push(&mut self, byte: u8) -> Result<(), PushBytesError> {
216 check_limit(self.0.len().saturating_add(1))?;
218 self.0.push(byte);
219 Ok(())
220 }
221
222 pub fn extend_from_slice(&mut self, bytes: &[u8]) -> Result<(), PushBytesError> {
228 let len = self.0.len().saturating_add(bytes.len());
229 check_limit(len)?;
230 self.0.extend_from_slice(bytes);
231 Ok(())
232 }
233
234 pub fn pop(&mut self) -> Option<u8> { self.0.pop() }
236
237 #[track_caller]
243 pub fn remove(&mut self, index: usize) -> u8 { self.0.remove(index) }
244
245 pub fn clear(&mut self) { self.0.clear() }
247
248 pub fn truncate(&mut self, len: usize) { self.0.truncate(len) }
250
251 pub fn as_push_bytes(&self) -> &PushBytes {
253 PushBytes::from_slice_unchecked(&self.0)
255 }
256
257 pub fn as_mut_push_bytes(&mut self) -> &mut PushBytes {
259 PushBytes::from_mut_slice_unchecked(&mut self.0)
261 }
262
263 pub(super) fn inner(&self) -> &Vec<u8> { &self.0 }
265 }
266
267 impl From<PushBytesBuf> for Vec<u8> {
268 fn from(value: PushBytesBuf) -> Self { value.0 }
269 }
270
271 impl TryFrom<Vec<u8>> for PushBytesBuf {
272 type Error = PushBytesError;
273
274 fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
275 let _: &PushBytes = vec.as_slice().try_into()?;
277 Ok(Self(vec))
278 }
279 }
280
281 impl ToOwned for PushBytes {
282 type Owned = PushBytesBuf;
283
284 fn to_owned(&self) -> Self::Owned { PushBytesBuf(self.0.to_owned()) }
285 }
286}
287
288impl PushBytes {
289 pub fn len(&self) -> usize { self.as_bytes().len() }
291
292 pub fn is_empty(&self) -> bool { self.as_bytes().is_empty() }
294}
295
296impl PushBytesBuf {
297 pub fn len(&self) -> usize { self.inner().len() }
299
300 pub fn capacity(&self) -> usize { self.inner().capacity() }
302
303 pub fn is_empty(&self) -> bool { self.inner().is_empty() }
305}
306
307impl AsRef<[u8]> for PushBytes {
308 fn as_ref(&self) -> &[u8] { self.as_bytes() }
309}
310
311impl AsMut<[u8]> for PushBytes {
312 fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
313}
314
315impl Deref for PushBytesBuf {
316 type Target = PushBytes;
317
318 fn deref(&self) -> &Self::Target { self.as_push_bytes() }
319}
320
321impl DerefMut for PushBytesBuf {
322 fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_push_bytes() }
323}
324
325impl AsRef<Self> for PushBytes {
326 fn as_ref(&self) -> &Self { self }
327}
328
329impl AsMut<Self> for PushBytes {
330 fn as_mut(&mut self) -> &mut Self { self }
331}
332
333impl AsRef<PushBytes> for PushBytesBuf {
334 fn as_ref(&self) -> &PushBytes { self.as_push_bytes() }
335}
336
337impl AsMut<PushBytes> for PushBytesBuf {
338 fn as_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() }
339}
340
341impl Borrow<PushBytes> for PushBytesBuf {
342 fn borrow(&self) -> &PushBytes { self.as_push_bytes() }
343}
344
345impl BorrowMut<PushBytes> for PushBytesBuf {
346 fn borrow_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() }
347}
348
349crate::impl_asref_push_bytes! {
350 hashes::ripemd160::Hash,
351 hashes::hash160::Hash,
352 hashes::sha1::Hash,
353 hashes::sha256::Hash,
354 hashes::sha256d::Hash,
355}
356
357pub trait PushBytesErrorReport {
362 fn input_len(&self) -> usize;
364}
365
366impl PushBytesErrorReport for core::convert::Infallible {
367 #[inline]
368 fn input_len(&self) -> usize { match *self {} }
369}
370
371#[doc(no_inline)]
372pub use error::PushBytesError;
373
374#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
375mod error {
376 use core::fmt;
377
378 #[allow(unused)]
380 #[derive(Debug, Clone, PartialEq, Eq)]
381 pub struct PushBytesError {
382 pub(super) never: core::convert::Infallible,
383 }
384
385 impl super::PushBytesErrorReport for PushBytesError {
386 #[inline]
387 fn input_len(&self) -> usize { match self.never {} }
388 }
389
390 impl fmt::Display for PushBytesError {
391 fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { match self.never {} }
392 }
393}
394
395#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
398mod error {
399 use core::fmt;
400
401 #[derive(Debug, Clone, PartialEq, Eq)]
403 pub struct PushBytesError {
404 pub(super) len: usize,
406 }
407
408 impl super::PushBytesErrorReport for PushBytesError {
409 #[inline]
410 fn input_len(&self) -> usize { self.len }
411 }
412
413 impl fmt::Display for PushBytesError {
414 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
415 write!(
416 f,
417 "attempt to prepare {} bytes to be pushed into script but the limit is 2^32-1",
418 self.len
419 )
420 }
421 }
422}
423
424impl From<Infallible> for PushBytesError {
425 fn from(never: Infallible) -> Self { match never {} }
426}
427
428#[cfg(feature = "std")]
429impl std::error::Error for PushBytesError {
430 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
431 #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
432 let Self { never: _ } = self;
433 #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
434 let Self { len: _ } = self;
435 None
436 }
437}
438
439#[cfg(test)]
440mod tests {
441 use alloc::vec;
442
443 use super::*;
444
445 #[test]
446 fn push_bytes_empty_inits() {
447 let pb = PushBytes::empty();
448 assert!(pb.is_empty());
449 assert_eq!(pb.len(), 0);
450 assert_eq!(pb.as_bytes(), &[0u8; 0]);
451
452 let pb = PushBytesBuf::new();
453 assert!(pb.is_empty());
454 assert_eq!(pb.len(), 0);
455 assert_eq!(pb.as_bytes(), &[0u8; 0]);
456
457 let pb = PushBytesBuf::default();
458 assert!(pb.is_empty());
459 assert_eq!(pb.len(), 0);
460 assert_eq!(pb.as_bytes(), &[0u8; 0]);
461 }
462
463 #[test]
464 fn push_bytes_try_from_slice() {
465 let data = [0x01, 0x02, 0x03];
466 let pb = <&PushBytes>::try_from(data.as_slice()).unwrap();
467 assert_eq!(pb.as_bytes(), &data);
468 assert_eq!(pb.len(), 3);
469 assert!(!pb.is_empty());
470 }
471
472 #[test]
473 #[cfg(target_pointer_width = "64")]
474 #[cfg_attr(miri, ignore)]
475 fn push_bytes_check_limit_boundary() {
476 let ptr = core::ptr::NonNull::<u8>::dangling().as_ptr();
481 let too_long: &[u8] = unsafe { core::slice::from_raw_parts(ptr, 0x1_0000_0000) };
482 assert!(<&PushBytes>::try_from(too_long).is_err());
483 }
484
485 #[test]
486 fn push_bytes_from_array() {
487 let data = [0xde, 0xad, 0xbe, 0xef];
488 let pb: &PushBytes = (&data).into();
489 assert_eq!(pb.as_bytes(), &data);
490 }
491
492 #[test]
493 fn push_bytes_asref_array() {
494 let data = [0x01, 0x02];
495 let pb: &PushBytes = data.as_ref();
496 assert_eq!(pb.as_bytes(), &data);
497 }
498
499 #[test]
500 fn push_bytes_index() {
501 let data = [0x01, 0x02, 0x03];
502 let pb: &PushBytes = (&data).into();
503 assert_eq!(pb[0], 0x01);
504 assert_eq!(pb[2], 0x03);
505 let slice = &pb[1..];
506 assert_eq!(slice.as_bytes(), &[0x02, 0x03]);
507 }
508
509 #[test]
510 fn push_bytes_as_mut_bytes() {
511 let mut data = [0x01, 0x02, 0x03];
512 let pb: &mut PushBytes = (&mut data).into();
513 pb.as_mut_bytes()[0] = 0xff;
514 assert_eq!(data, [0xff, 0x02, 0x03]);
515 }
516
517 #[test]
518 fn push_bytes_buf_with_capacity() {
519 let buf = PushBytesBuf::with_capacity(16);
520 assert!(buf.is_empty());
521 assert!(buf.capacity() >= 16);
522 }
523
524 #[test]
525 fn push_bytes_buf_push_and_pop() {
526 let mut buf = PushBytesBuf::new();
527 buf.push(0x01).unwrap();
528 buf.push(0x02).unwrap();
529 assert_eq!(buf.len(), 2);
530 assert!(!buf.is_empty());
531 assert_eq!(buf.pop(), Some(0x02));
532 assert_eq!(buf.pop(), Some(0x01));
533 assert_eq!(buf.pop(), None);
534 assert!(buf.is_empty());
535 }
536
537 #[test]
538 fn push_bytes_buf_reserve() {
539 let mut buf = PushBytesBuf::new();
540 assert_eq!(buf.capacity(), 0);
541 buf.reserve(32);
542 assert!(buf.capacity() >= 32);
543 }
544
545 #[test]
546 fn push_bytes_buf_extend_from_slice() {
547 let mut buf = PushBytesBuf::new();
548 buf.extend_from_slice(&[0x01, 0x02, 0x03]).unwrap();
549 assert_eq!(buf.as_bytes(), &[0x01, 0x02, 0x03]);
550 }
551
552 #[test]
553 fn push_bytes_buf_clear() {
554 let mut buf = PushBytesBuf::new();
555 buf.extend_from_slice(&[0x01, 0x02]).unwrap();
556 buf.clear();
557 assert!(buf.is_empty());
558 }
559
560 #[test]
561 fn push_bytes_buf_truncate() {
562 let mut buf = PushBytesBuf::new();
563 buf.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]).unwrap();
564 buf.truncate(2);
565 assert_eq!(buf.as_bytes(), &[0x01, 0x02]);
566 }
567
568 #[test]
569 fn push_bytes_buf_remove() {
570 let mut buf = PushBytesBuf::new();
571 buf.extend_from_slice(&[0x01, 0x02, 0x03]).unwrap();
572 let removed = buf.remove(1);
573 assert_eq!(removed, 0x02);
574 assert_eq!(buf.as_bytes(), &[0x01, 0x03]);
575 }
576
577 #[test]
578 fn push_bytes_buf_from_array() {
579 let buf = PushBytesBuf::from([0x01, 0x02, 0x03]);
580 assert_eq!(buf.as_bytes(), &[0x01, 0x02, 0x03]);
581 }
582
583 #[test]
584 fn push_bytes_buf_try_from_vec() {
585 let vec = vec![0x01, 0x02, 0x03];
586 let buf = PushBytesBuf::try_from(vec.clone()).unwrap();
587 assert_eq!(buf.as_bytes(), &vec[..]);
588 }
589
590 #[test]
591 fn push_bytes_buf_into_vec() {
592 let buf = PushBytesBuf::from([0x01, 0x02]);
593 let vec: alloc::vec::Vec<u8> = buf.into();
594 assert_eq!(vec, [0x01, 0x02]);
595 }
596
597 #[test]
598 fn push_bytes_buf_as_push_bytes() {
599 let buf = PushBytesBuf::from([0xab, 0xcd]);
600 let pb: &PushBytes = buf.as_push_bytes();
601 assert_eq!(pb.as_bytes(), &[0xab, 0xcd]);
602 }
603
604 #[test]
605 fn push_bytes_buf_deref() {
606 let buf = PushBytesBuf::from([0x01, 0x02]);
607 let pb: &PushBytes = &buf;
608 assert_eq!(pb.as_bytes(), buf.as_bytes());
609 }
610
611 #[test]
612 fn push_bytes_buf_to_owned() {
613 use alloc::borrow::ToOwned;
614 let data = [0x01, 0x02, 0x03];
615 let pb: &PushBytes = (&data).into();
616 let owned: PushBytesBuf = pb.to_owned();
617 assert_eq!(owned.as_bytes(), pb.as_bytes());
618 }
619}