bitcoin_primitives/script/
owned.rs

1// SPDX-License-Identifier: CC0-1.0
2
3#[cfg(doc)]
4use core::ops::Deref;
5
6#[cfg(feature = "arbitrary")]
7use arbitrary::{Arbitrary, Unstructured};
8
9use super::Script;
10use crate::prelude::{Box, Vec};
11
12/// An owned, growable script.
13///
14/// `ScriptBuf` is the most common script type that has the ownership over the contents of the
15/// script. It has a close relationship with its borrowed counterpart, [`Script`].
16///
17/// Just as other similar types, this implements [`Deref`], so [deref coercions] apply. Also note
18/// that all the safety/validity restrictions that apply to [`Script`] apply to `ScriptBuf` as well.
19///
20/// [deref coercions]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion
21#[derive(Default, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
22pub struct ScriptBuf(pub(in crate::script) Vec<u8>);
23
24impl ScriptBuf {
25    /// Constructs a new empty script.
26    #[inline]
27    pub const fn new() -> Self { ScriptBuf(Vec::new()) }
28
29    /// Converts byte vector into script.
30    ///
31    /// This method doesn't (re)allocate.
32    pub fn from_bytes(bytes: Vec<u8>) -> Self { ScriptBuf(bytes) }
33
34    /// Returns a reference to unsized script.
35    pub fn as_script(&self) -> &Script { Script::from_bytes(&self.0) }
36
37    /// Returns a mutable reference to unsized script.
38    pub fn as_mut_script(&mut self) -> &mut Script { Script::from_bytes_mut(&mut self.0) }
39
40    /// Converts the script into a byte vector.
41    ///
42    /// This method doesn't (re)allocate.
43    pub fn into_bytes(self) -> Vec<u8> { self.0 }
44
45    /// Converts this `ScriptBuf` into a [boxed](Box) [`Script`].
46    ///
47    /// This method reallocates if the capacity is greater than length of the script but should not
48    /// when they are equal. If you know beforehand that you need to create a script of exact size
49    /// use [`reserve_exact`](Self::reserve_exact) before adding data to the script so that the
50    /// reallocation can be avoided.
51    #[must_use = "`self` will be dropped if the result is not used"]
52    #[inline]
53    pub fn into_boxed_script(self) -> Box<Script> {
54        // Copied from PathBuf::into_boxed_path
55        let rw = Box::into_raw(self.0.into_boxed_slice()) as *mut Script;
56        unsafe { Box::from_raw(rw) }
57    }
58
59    /// Constructs a new empty script with pre-allocated capacity.
60    pub fn with_capacity(capacity: usize) -> Self { ScriptBuf(Vec::with_capacity(capacity)) }
61
62    /// Pre-allocates at least `additional_len` bytes if needed.
63    ///
64    /// Reserves capacity for at least `additional_len` more bytes to be inserted in the given
65    /// script. The script may reserve more space to speculatively avoid frequent reallocations.
66    /// After calling `reserve`, capacity will be greater than or equal to
67    /// `self.len() + additional_len`. Does nothing if capacity is already sufficient.
68    ///
69    /// # Panics
70    ///
71    /// Panics if the new capacity exceeds `isize::MAX bytes`.
72    pub fn reserve(&mut self, additional_len: usize) { self.0.reserve(additional_len); }
73
74    /// Pre-allocates exactly `additional_len` bytes if needed.
75    ///
76    /// Unlike `reserve`, this will not deliberately over-allocate to speculatively avoid frequent
77    /// allocations. After calling `reserve_exact`, capacity will be greater than or equal to
78    /// `self.len() + additional`. Does nothing if the capacity is already sufficient.
79    ///
80    /// Note that the allocator may give the collection more space than it requests. Therefore,
81    /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`](Self::reserve)
82    /// if future insertions are expected.
83    ///
84    /// # Panics
85    ///
86    /// Panics if the new capacity exceeds `isize::MAX bytes`.
87    pub fn reserve_exact(&mut self, additional_len: usize) { self.0.reserve_exact(additional_len); }
88}
89
90#[cfg(feature = "arbitrary")]
91impl<'a> Arbitrary<'a> for ScriptBuf {
92    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
93        let v = Vec::<u8>::arbitrary(u)?;
94        Ok(ScriptBuf(v))
95    }
96}