use core::ops::{Deref, DerefMut};
#[allow(unused)]
use crate::prelude::*;
#[rustfmt::skip] #[doc(inline)]
pub use self::primitive::*;
mod primitive {
use core::ops::{
Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
};
use super::PushBytesError;
#[allow(unused)]
use crate::prelude::*;
#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
fn check_limit(_: usize) -> Result<(), PushBytesError> { Ok(()) }
#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
fn check_limit(len: usize) -> Result<(), PushBytesError> {
if len < 0x100000000 {
Ok(())
} else {
Err(PushBytesError { len })
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct PushBytes([u8]);
impl PushBytes {
unsafe fn from_slice_unchecked(bytes: &[u8]) -> &Self {
&*(bytes as *const [u8] as *const PushBytes)
}
unsafe fn from_mut_slice_unchecked(bytes: &mut [u8]) -> &mut Self {
&mut *(bytes as *mut [u8] as *mut PushBytes)
}
pub fn empty() -> &'static Self {
unsafe { Self::from_slice_unchecked(&[]) }
}
pub fn as_bytes(&self) -> &[u8] { &self.0 }
pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 }
}
macro_rules! delegate_index {
($($type:ty),* $(,)?) => {
$(
impl Index<$type> for PushBytes {
type Output = Self;
#[inline]
#[track_caller]
fn index(&self, index: $type) -> &Self::Output {
unsafe {
Self::from_slice_unchecked(&self.0[index])
}
}
}
)*
}
}
delegate_index!(
Range<usize>,
RangeFrom<usize>,
RangeTo<usize>,
RangeFull,
RangeInclusive<usize>,
RangeToInclusive<usize>,
(Bound<usize>, Bound<usize>)
);
impl Index<usize> for PushBytes {
type Output = u8;
#[inline]
#[track_caller]
fn index(&self, index: usize) -> &Self::Output { &self.0[index] }
}
impl<'a> TryFrom<&'a [u8]> for &'a PushBytes {
type Error = PushBytesError;
fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
check_limit(bytes.len())?;
Ok(unsafe { PushBytes::from_slice_unchecked(bytes) })
}
}
impl<'a> TryFrom<&'a mut [u8]> for &'a mut PushBytes {
type Error = PushBytesError;
fn try_from(bytes: &'a mut [u8]) -> Result<Self, Self::Error> {
check_limit(bytes.len())?;
Ok(unsafe { PushBytes::from_mut_slice_unchecked(bytes) })
}
}
macro_rules! from_array {
($($len:literal),* $(,)?) => {
$(
impl<'a> From<&'a [u8; $len]> for &'a PushBytes {
fn from(bytes: &'a [u8; $len]) -> Self {
const _: () = [(); 1][($len >= 0x100000000u64) as usize];
unsafe { PushBytes::from_slice_unchecked(bytes) }
}
}
impl<'a> From<&'a mut [u8; $len]> for &'a mut PushBytes {
fn from(bytes: &'a mut [u8; $len]) -> Self {
unsafe { PushBytes::from_mut_slice_unchecked(bytes) }
}
}
impl AsRef<PushBytes> for [u8; $len] {
fn as_ref(&self) -> &PushBytes {
self.into()
}
}
impl AsMut<PushBytes> for [u8; $len] {
fn as_mut(&mut self) -> &mut PushBytes {
self.into()
}
}
impl From<[u8; $len]> for PushBytesBuf {
fn from(bytes: [u8; $len]) -> Self {
PushBytesBuf(Vec::from(&bytes as &[_]))
}
}
impl<'a> From<&'a [u8; $len]> for PushBytesBuf {
fn from(bytes: &'a [u8; $len]) -> Self {
PushBytesBuf(Vec::from(bytes as &[_]))
}
}
)*
}
}
from_array! {
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,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76
}
#[derive(Default, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct PushBytesBuf(Vec<u8>);
impl PushBytesBuf {
#[inline]
pub const fn new() -> Self { PushBytesBuf(Vec::new()) }
pub fn with_capacity(capacity: usize) -> Self { PushBytesBuf(Vec::with_capacity(capacity)) }
pub fn reserve(&mut self, additional_capacity: usize) {
self.0.reserve(additional_capacity)
}
#[allow(deprecated)]
pub fn push(&mut self, byte: u8) -> Result<(), PushBytesError> {
check_limit(self.0.len().saturating_add(1))?;
self.0.push(byte);
Ok(())
}
pub fn extend_from_slice(&mut self, bytes: &[u8]) -> Result<(), PushBytesError> {
let len = self.0.len().saturating_add(bytes.len());
check_limit(len)?;
self.0.extend_from_slice(bytes);
Ok(())
}
pub fn pop(&mut self) -> Option<u8> { self.0.pop() }
#[track_caller]
pub fn remove(&mut self, index: usize) -> u8 { self.0.remove(index) }
pub fn clear(&mut self) { self.0.clear() }
pub fn truncate(&mut self, len: usize) { self.0.truncate(len) }
pub fn as_push_bytes(&self) -> &PushBytes {
unsafe { PushBytes::from_slice_unchecked(&self.0) }
}
pub fn as_mut_push_bytes(&mut self) -> &mut PushBytes {
unsafe { PushBytes::from_mut_slice_unchecked(&mut self.0) }
}
pub(super) fn inner(&self) -> &Vec<u8> { &self.0 }
}
impl From<PushBytesBuf> for Vec<u8> {
fn from(value: PushBytesBuf) -> Self { value.0 }
}
impl TryFrom<Vec<u8>> for PushBytesBuf {
type Error = PushBytesError;
fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
let _: &PushBytes = vec.as_slice().try_into()?;
Ok(PushBytesBuf(vec))
}
}
impl ToOwned for PushBytes {
type Owned = PushBytesBuf;
fn to_owned(&self) -> Self::Owned { PushBytesBuf(self.0.to_owned()) }
}
}
impl PushBytes {
pub fn len(&self) -> usize { self.as_bytes().len() }
pub fn is_empty(&self) -> bool { self.as_bytes().is_empty() }
}
impl PushBytesBuf {
pub fn len(&self) -> usize { self.inner().len() }
pub fn capacity(&self) -> usize { self.inner().capacity() }
pub fn is_empty(&self) -> bool { self.inner().is_empty() }
}
impl AsRef<[u8]> for PushBytes {
fn as_ref(&self) -> &[u8] { self.as_bytes() }
}
impl AsMut<[u8]> for PushBytes {
fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
}
impl Deref for PushBytesBuf {
type Target = PushBytes;
fn deref(&self) -> &Self::Target { self.as_push_bytes() }
}
impl DerefMut for PushBytesBuf {
fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_push_bytes() }
}
impl AsRef<PushBytes> for PushBytes {
fn as_ref(&self) -> &PushBytes { self }
}
impl AsMut<PushBytes> for PushBytes {
fn as_mut(&mut self) -> &mut PushBytes { self }
}
impl AsRef<PushBytes> for PushBytesBuf {
fn as_ref(&self) -> &PushBytes { self.as_push_bytes() }
}
impl AsMut<PushBytes> for PushBytesBuf {
fn as_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() }
}
impl Borrow<PushBytes> for PushBytesBuf {
fn borrow(&self) -> &PushBytes { self.as_push_bytes() }
}
impl BorrowMut<PushBytes> for PushBytesBuf {
fn borrow_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() }
}
pub trait PushBytesErrorReport {
fn input_len(&self) -> usize;
}
impl PushBytesErrorReport for core::convert::Infallible {
#[inline]
fn input_len(&self) -> usize { match *self {} }
}
pub use error::*;
#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
mod error {
use core::fmt;
#[allow(unused)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PushBytesError {
never: core::convert::Infallible,
}
impl super::PushBytesErrorReport for PushBytesError {
#[inline]
fn input_len(&self) -> usize { match self.never {} }
}
impl fmt::Display for PushBytesError {
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { match self.never {} }
}
}
#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
mod error {
use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PushBytesError {
pub(super) len: usize,
}
impl super::PushBytesErrorReport for PushBytesError {
#[inline]
fn input_len(&self) -> usize { self.len }
}
impl fmt::Display for PushBytesError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"attempt to prepare {} bytes to be pushed into script but the limit is 2^32-1",
self.len
)
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for PushBytesError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
}