use core::convert::Infallible;
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use encoding::{ByteVecDecoder, ByteVecDecoderError, Decodable, Decoder};
use internals::write_err;
use super::Script;
use crate::prelude::{Box, Vec};
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct ScriptBuf<T>(PhantomData<T>, Vec<u8>);
impl<T> ScriptBuf<T> {
#[inline]
pub const fn new() -> Self { Self::from_bytes(Vec::new()) }
#[inline]
pub const fn from_bytes(bytes: Vec<u8>) -> Self { Self(PhantomData, bytes) }
#[inline]
pub fn as_script(&self) -> &Script<T> { Script::from_bytes(&self.1) }
#[inline]
pub fn as_mut_script(&mut self) -> &mut Script<T> { Script::from_bytes_mut(&mut self.1) }
#[inline]
pub fn into_bytes(self) -> Vec<u8> { self.1 }
#[must_use]
#[inline]
pub fn into_boxed_script(self) -> Box<Script<T>> {
Script::from_boxed_bytes(self.into_bytes().into_boxed_slice())
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self { Self::from_bytes(Vec::with_capacity(capacity)) }
#[inline]
pub fn reserve(&mut self, additional_len: usize) { self.1.reserve(additional_len); }
#[inline]
pub fn reserve_exact(&mut self, additional_len: usize) { self.1.reserve_exact(additional_len); }
#[inline]
pub fn capacity(&self) -> usize { self.1.capacity() }
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
#[inline]
#[deprecated(since = "1.0.0-rc.0", note = "use `format!(\"{var:x}\")` instead")]
pub fn to_hex(&self) -> alloc::string::String { alloc::format!("{:x}", self) }
}
impl<T> Default for ScriptBuf<T> {
fn default() -> Self { Self(PhantomData, Vec::new()) }
}
impl<T> Deref for ScriptBuf<T> {
type Target = Script<T>;
#[inline]
fn deref(&self) -> &Self::Target { self.as_script() }
}
impl<T> DerefMut for ScriptBuf<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_script() }
}
pub struct ScriptBufDecoder<T>(ByteVecDecoder, PhantomData<T>);
impl<T> ScriptBufDecoder<T> {
pub const fn new() -> Self { Self(ByteVecDecoder::new(), PhantomData) }
}
impl<T> Default for ScriptBufDecoder<T> {
fn default() -> Self { Self::new() }
}
impl<T> Decoder for ScriptBufDecoder<T> {
type Output = ScriptBuf<T>;
type Error = ScriptBufDecoderError;
#[inline]
fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
Ok(self.0.push_bytes(bytes)?)
}
#[inline]
fn end(self) -> Result<Self::Output, Self::Error> { Ok(ScriptBuf::from_bytes(self.0.end()?)) }
#[inline]
fn read_limit(&self) -> usize { self.0.read_limit() }
}
impl<T> Decodable for ScriptBuf<T> {
type Decoder = ScriptBufDecoder<T>;
fn decoder() -> Self::Decoder { ScriptBufDecoder(ByteVecDecoder::new(), PhantomData) }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScriptBufDecoderError(ByteVecDecoderError);
impl From<Infallible> for ScriptBufDecoderError {
fn from(never: Infallible) -> Self { match never {} }
}
impl From<ByteVecDecoderError> for ScriptBufDecoderError {
fn from(e: ByteVecDecoderError) -> Self { Self(e) }
}
impl fmt::Display for ScriptBufDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write_err!(f, "decoder error"; self.0) }
}
#[cfg(feature = "std")]
impl std::error::Error for ScriptBufDecoderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
}
#[cfg(feature = "arbitrary")]
impl<'a, T> Arbitrary<'a> for ScriptBuf<T> {
#[inline]
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let v = Vec::<u8>::arbitrary(u)?;
Ok(Self::from_bytes(v))
}
}
#[cfg(test)]
mod tests {
type ScriptBuf = super::super::ScriptSigBuf;
#[cfg(feature = "alloc")]
use alloc::string::ToString;
#[cfg(feature = "alloc")]
use alloc::vec;
#[cfg(feature = "std")]
use std::error::Error as _;
use super::*;
#[test]
fn script_buf_from_bytes() {
let bytes = vec![1, 2, 3];
let script = ScriptBuf::from_bytes(bytes.clone());
assert_eq!(script.as_bytes(), bytes);
}
#[test]
fn script_buf_as_script() {
let bytes = vec![1, 2, 3];
let script = ScriptBuf::from_bytes(bytes.clone());
let script_ref = script.as_script();
assert_eq!(script_ref.as_bytes(), bytes);
}
#[test]
fn script_buf_as_mut_script() {
let mut script = ScriptBuf::from_bytes(vec![1, 2, 3]);
let script_mut_ref = script.as_mut_script();
script_mut_ref.as_mut_bytes()[0] = 4;
assert_eq!(script.as_mut_bytes(), &[4, 2, 3]);
}
#[test]
fn script_buf_into_bytes() {
let bytes = vec![1, 2, 3];
let script = ScriptBuf::from_bytes(bytes.clone());
let result = script.into_bytes();
assert_eq!(result, bytes);
}
#[test]
fn script_buf_into_boxed_script() {
let bytes = vec![1, 2, 3];
let script = ScriptBuf::from_bytes(bytes.clone());
let boxed_script = script.into_boxed_script();
assert_eq!(boxed_script.as_bytes(), bytes);
}
#[test]
fn script_buf_capacity() {
let script = ScriptBuf::with_capacity(10);
assert!(script.capacity() >= 10);
}
#[test]
fn script_buf_reserve() {
let mut script = ScriptBuf::new();
script.reserve(10);
assert!(script.capacity() >= 10);
}
#[test]
fn script_buf_reserve_exact() {
let mut script = ScriptBuf::new();
script.reserve_exact(10);
assert!(script.capacity() >= 10);
}
#[test]
fn script_buf_default() {
let script: ScriptBuf = ScriptBuf::default();
assert!(script.is_empty());
}
#[test]
fn script_consensus_decode_empty() {
let bytes = vec![0_u8];
let mut push = bytes.as_slice();
let mut decoder = ScriptBuf::decoder();
decoder.push_bytes(&mut push).unwrap();
let got = decoder.end().unwrap();
let want = ScriptBuf::new();
assert_eq!(got, want);
}
#[test]
fn script_consensus_decode_empty_with_more_data() {
let bytes = vec![0x00_u8, 0xff, 0xff, 0xff, 0xff];
let mut push = bytes.as_slice();
let mut decoder = ScriptBuf::decoder();
decoder.push_bytes(&mut push).unwrap();
let got = decoder.end().unwrap();
let want = ScriptBuf::new();
assert_eq!(got, want);
}
#[test]
fn decoder_full_read_limit() {
let mut decoder = ScriptBuf::decoder();
assert_eq!(decoder.read_limit(), 1);
let mut push = [32_u8].as_slice();
decoder.push_bytes(&mut push).unwrap();
assert_eq!(decoder.read_limit(), 32);
let mut push = [0xAA_u8].as_slice();
decoder.push_bytes(&mut push).unwrap();
assert_eq!(decoder.read_limit(), 31);
}
#[test]
#[cfg(feature = "alloc")]
fn decoder_error_display() {
let bytes = vec![0x01_u8];
let mut push = bytes.as_slice();
let mut decoder = <ScriptBuf as Decodable>::Decoder::default();
decoder.push_bytes(&mut push).unwrap();
let err = decoder.end().unwrap_err();
assert!(!err.to_string().is_empty());
#[cfg(feature = "std")]
assert!(err.source().is_some());
}
}