bitcoin_primitives/script/
mod.rs1mod borrowed;
7mod owned;
9
10use core::cmp::Ordering;
11use core::fmt;
12use core::ops::{Deref, DerefMut};
13
14use hex::DisplayHex;
15use internals::script::{self, PushDataLenLen};
16
17use crate::opcodes::all::*;
18use crate::opcodes::{self, Opcode};
19use crate::prelude::rc::Rc;
20#[cfg(target_has_atomic = "ptr")]
21use crate::prelude::sync::Arc;
22use crate::prelude::{Borrow, BorrowMut, Box, Cow, ToOwned, Vec};
23
24#[rustfmt::skip] #[doc(inline)]
26pub use self::{
27 borrowed::Script,
28 owned::ScriptBuf,
29};
30
31impl From<ScriptBuf> for Box<Script> {
34 fn from(v: ScriptBuf) -> Self { v.into_boxed_script() }
35}
36
37impl From<ScriptBuf> for Cow<'_, Script> {
38 fn from(value: ScriptBuf) -> Self { Cow::Owned(value) }
39}
40
41impl<'a> From<Cow<'a, Script>> for ScriptBuf {
42 fn from(value: Cow<'a, Script>) -> Self {
43 match value {
44 Cow::Owned(owned) => owned,
45 Cow::Borrowed(borrwed) => borrwed.into(),
46 }
47 }
48}
49
50impl<'a> From<Cow<'a, Script>> for Box<Script> {
51 fn from(value: Cow<'a, Script>) -> Self {
52 match value {
53 Cow::Owned(owned) => owned.into(),
54 Cow::Borrowed(borrwed) => borrwed.into(),
55 }
56 }
57}
58
59impl<'a> From<&'a Script> for Box<Script> {
60 fn from(value: &'a Script) -> Self { value.to_owned().into() }
61}
62
63impl<'a> From<&'a Script> for ScriptBuf {
64 fn from(value: &'a Script) -> Self { value.to_owned() }
65}
66
67impl<'a> From<&'a Script> for Cow<'a, Script> {
68 fn from(value: &'a Script) -> Self { Cow::Borrowed(value) }
69}
70
71#[cfg(target_has_atomic = "ptr")]
73impl<'a> From<&'a Script> for Arc<Script> {
74 fn from(value: &'a Script) -> Self {
75 let rw: *const [u8] = Arc::into_raw(Arc::from(&value.0));
76 unsafe { Arc::from_raw(rw as *const Script) }
81 }
82}
83
84impl<'a> From<&'a Script> for Rc<Script> {
85 fn from(value: &'a Script) -> Self {
86 let rw: *const [u8] = Rc::into_raw(Rc::from(&value.0));
87 unsafe { Rc::from_raw(rw as *const Script) }
92 }
93}
94
95impl From<Vec<u8>> for ScriptBuf {
96 fn from(v: Vec<u8>) -> Self { ScriptBuf(v) }
97}
98
99impl From<ScriptBuf> for Vec<u8> {
100 fn from(v: ScriptBuf) -> Self { v.0 }
101}
102
103impl AsRef<Script> for Script {
104 #[inline]
105 fn as_ref(&self) -> &Script { self }
106}
107
108impl AsRef<Script> for ScriptBuf {
109 fn as_ref(&self) -> &Script { self }
110}
111
112impl AsRef<[u8]> for Script {
113 #[inline]
114 fn as_ref(&self) -> &[u8] { self.as_bytes() }
115}
116
117impl AsRef<[u8]> for ScriptBuf {
118 fn as_ref(&self) -> &[u8] { self.as_bytes() }
119}
120
121impl AsMut<Script> for Script {
122 fn as_mut(&mut self) -> &mut Script { self }
123}
124
125impl AsMut<Script> for ScriptBuf {
126 fn as_mut(&mut self) -> &mut Script { self }
127}
128
129impl AsMut<[u8]> for Script {
130 #[inline]
131 fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
132}
133
134impl AsMut<[u8]> for ScriptBuf {
135 fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
136}
137
138impl fmt::Debug for Script {
139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 f.write_str("Script(")?;
141 fmt::Display::fmt(self, f)?;
142 f.write_str(")")
143 }
144}
145
146impl fmt::Debug for ScriptBuf {
147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_script(), f) }
148}
149
150impl fmt::Display for Script {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 macro_rules! read_push_data_len {
154 ($iter:expr, $size:path, $formatter:expr) => {
155 match script::read_push_data_len($iter, $size) {
156 Ok(n) => n,
157 Err(_) => {
158 $formatter.write_str("<unexpected end>")?;
159 break;
160 }
161 }
162 };
163 }
164
165 let mut iter = self.as_bytes().iter();
166 let mut at_least_one = false;
168 while let Some(byte) = iter.next() {
171 let opcode = Opcode::from(*byte);
172
173 let data_len = if let opcodes::Class::PushBytes(n) =
174 opcode.classify(opcodes::ClassifyContext::Legacy)
175 {
176 n as usize
177 } else {
178 match opcode {
179 OP_PUSHDATA1 => {
180 read_push_data_len!(&mut iter, PushDataLenLen::One, f)
182 }
183 OP_PUSHDATA2 => {
184 read_push_data_len!(&mut iter, PushDataLenLen::Two, f)
186 }
187 OP_PUSHDATA4 => {
188 read_push_data_len!(&mut iter, PushDataLenLen::Four, f)
190 }
191 _ => 0,
192 }
193 };
194
195 if at_least_one {
196 f.write_str(" ")?;
197 } else {
198 at_least_one = true;
199 }
200 if opcode == OP_PUSHBYTES_0 {
202 f.write_str("OP_0")?;
203 } else {
204 write!(f, "{:?}", opcode)?;
205 }
206 if data_len > 0 {
208 f.write_str(" ")?;
209 if data_len <= iter.len() {
210 for ch in iter.by_ref().take(data_len) {
211 write!(f, "{:02x}", ch)?;
212 }
213 } else {
214 f.write_str("<push past end>")?;
215 break;
216 }
217 }
218 }
219 Ok(())
220 }
221}
222
223impl fmt::Display for ScriptBuf {
224 #[inline]
225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.as_script(), f) }
226}
227
228impl fmt::LowerHex for Script {
229 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230 fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
231 }
232}
233#[cfg(feature = "alloc")]
234internals::impl_to_hex_from_lower_hex!(Script, |script: &Script| script.len() * 2);
235
236impl fmt::LowerHex for ScriptBuf {
237 #[inline]
238 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self.as_script(), f) }
239}
240#[cfg(feature = "alloc")]
241internals::impl_to_hex_from_lower_hex!(ScriptBuf, |script_buf: &ScriptBuf| script_buf.len() * 2);
242
243impl fmt::UpperHex for Script {
244 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
245 fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
246 }
247}
248
249impl fmt::UpperHex for ScriptBuf {
250 #[inline]
251 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(self.as_script(), f) }
252}
253
254impl Deref for ScriptBuf {
255 type Target = Script;
256
257 fn deref(&self) -> &Self::Target { Script::from_bytes(&self.0) }
258}
259
260impl DerefMut for ScriptBuf {
261 fn deref_mut(&mut self) -> &mut Self::Target { Script::from_bytes_mut(&mut self.0) }
262}
263
264impl Borrow<Script> for ScriptBuf {
265 fn borrow(&self) -> &Script { self }
266}
267
268impl BorrowMut<Script> for ScriptBuf {
269 fn borrow_mut(&mut self) -> &mut Script { self }
270}
271
272impl PartialEq<ScriptBuf> for Script {
273 fn eq(&self, other: &ScriptBuf) -> bool { self.eq(other.as_script()) }
274}
275
276impl PartialEq<Script> for ScriptBuf {
277 fn eq(&self, other: &Script) -> bool { self.as_script().eq(other) }
278}
279
280impl PartialOrd<Script> for ScriptBuf {
281 fn partial_cmp(&self, other: &Script) -> Option<Ordering> {
282 self.as_script().partial_cmp(other)
283 }
284}
285
286impl PartialOrd<ScriptBuf> for Script {
287 fn partial_cmp(&self, other: &ScriptBuf) -> Option<Ordering> {
288 self.partial_cmp(other.as_script())
289 }
290}
291
292#[cfg(feature = "serde")]
293impl serde::Serialize for Script {
294 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
296 where
297 S: serde::Serializer,
298 {
299 if serializer.is_human_readable() {
300 serializer.collect_str(&format_args!("{:x}", self))
301 } else {
302 serializer.serialize_bytes(self.as_bytes())
303 }
304 }
305}
306
307#[cfg(feature = "serde")]
309impl<'de> serde::Deserialize<'de> for &'de Script {
310 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
311 where
312 D: serde::Deserializer<'de>,
313 {
314 if deserializer.is_human_readable() {
315 use crate::serde::de::Error;
316
317 return Err(D::Error::custom(
318 "deserialization of `&Script` from human-readable formats is not possible",
319 ));
320 }
321
322 struct Visitor;
323 impl<'de> serde::de::Visitor<'de> for Visitor {
324 type Value = &'de Script;
325
326 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
327 formatter.write_str("borrowed bytes")
328 }
329
330 fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
331 where
332 E: serde::de::Error,
333 {
334 Ok(Script::from_bytes(v))
335 }
336 }
337 deserializer.deserialize_bytes(Visitor)
338 }
339}
340
341#[cfg(feature = "serde")]
342impl serde::Serialize for ScriptBuf {
343 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
345 where
346 S: serde::Serializer,
347 {
348 (**self).serialize(serializer)
349 }
350}
351
352#[cfg(feature = "serde")]
353impl<'de> serde::Deserialize<'de> for ScriptBuf {
354 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
355 where
356 D: serde::Deserializer<'de>,
357 {
358 use core::fmt::Formatter;
359
360 use hex::FromHex;
361
362 if deserializer.is_human_readable() {
363 struct Visitor;
364 impl serde::de::Visitor<'_> for Visitor {
365 type Value = ScriptBuf;
366
367 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
368 formatter.write_str("a script hex")
369 }
370
371 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
372 where
373 E: serde::de::Error,
374 {
375 let v = Vec::from_hex(v).map_err(E::custom)?;
376 Ok(ScriptBuf::from(v))
377 }
378 }
379 deserializer.deserialize_str(Visitor)
380 } else {
381 struct BytesVisitor;
382
383 impl serde::de::Visitor<'_> for BytesVisitor {
384 type Value = ScriptBuf;
385
386 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
387 formatter.write_str("a script Vec<u8>")
388 }
389
390 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
391 where
392 E: serde::de::Error,
393 {
394 Ok(ScriptBuf::from(v.to_vec()))
395 }
396
397 fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
398 where
399 E: serde::de::Error,
400 {
401 Ok(ScriptBuf::from(v))
402 }
403 }
404 deserializer.deserialize_byte_buf(BytesVisitor)
405 }
406 }
407}