zingolabs_zewif/
script.rs1use super::Data;
2use anyhow::{Context, Result};
3use bc_envelope::prelude::*;
4use std::ops::{
5 Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
6};
7
8#[derive(Clone, PartialEq, Eq, Hash)]
45pub struct Script(Data);
46
47impl Script {
48 pub fn len(&self) -> usize {
49 self.0.len()
50 }
51
52 pub fn is_empty(&self) -> bool {
53 self.len() == 0
54 }
55}
56
57impl std::fmt::Debug for Script {
59 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
60 write!(f, "Script<{}>({})", self.0.len(), hex::encode(self))
61 }
62}
63
64impl AsRef<[u8]> for Script {
66 fn as_ref(&self) -> &[u8] {
67 self.0.as_ref()
68 }
69}
70
71impl From<Script> for Data {
73 fn from(script: Script) -> Self {
74 script.0
75 }
76}
77
78impl From<Data> for Script {
80 fn from(data: Data) -> Self {
81 Script(data)
82 }
83}
84
85impl Index<usize> for Script {
87 type Output = u8;
88
89 fn index(&self, index: usize) -> &Self::Output {
90 &self.0[index]
91 }
92}
93
94impl IndexMut<usize> for Script {
96 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
97 &mut self.0[index]
98 }
99}
100
101impl Index<Range<usize>> for Script {
102 type Output = [u8];
103
104 fn index(&self, index: Range<usize>) -> &Self::Output {
105 &self.0[index]
106 }
107}
108
109impl IndexMut<Range<usize>> for Script {
110 fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
111 &mut self.0[index]
112 }
113}
114
115impl Index<RangeTo<usize>> for Script {
116 type Output = [u8];
117
118 fn index(&self, index: RangeTo<usize>) -> &Self::Output {
119 &self.0[index]
120 }
121}
122
123impl IndexMut<RangeTo<usize>> for Script {
124 fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output {
125 &mut self.0[index]
126 }
127}
128
129impl Index<RangeFrom<usize>> for Script {
130 type Output = [u8];
131
132 fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
133 &self.0[index]
134 }
135}
136
137impl IndexMut<RangeFrom<usize>> for Script {
138 fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output {
139 &mut self.0[index]
140 }
141}
142
143impl Index<RangeFull> for Script {
144 type Output = [u8];
145
146 fn index(&self, index: RangeFull) -> &Self::Output {
147 &self.0[index]
148 }
149}
150
151impl IndexMut<RangeFull> for Script {
152 fn index_mut(&mut self, index: RangeFull) -> &mut Self::Output {
153 &mut self.0[index]
154 }
155}
156
157impl Index<RangeInclusive<usize>> for Script {
158 type Output = [u8];
159
160 fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
161 &self.0[index]
162 }
163}
164
165impl IndexMut<RangeInclusive<usize>> for Script {
166 fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
167 &mut self.0[index]
168 }
169}
170
171impl Index<RangeToInclusive<usize>> for Script {
172 type Output = [u8];
173
174 fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
175 &self.0[index]
176 }
177}
178
179impl IndexMut<RangeToInclusive<usize>> for Script {
180 fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output {
181 &mut self.0[index]
182 }
183}
184
185impl From<Script> for CBOR {
186 fn from(value: Script) -> Self {
187 CBOR::to_byte_string(value.0)
188 }
189}
190
191impl From<&Script> for CBOR {
192 fn from(value: &Script) -> Self {
193 CBOR::to_byte_string(value.0.clone())
194 }
195}
196
197impl TryFrom<CBOR> for Script {
198 type Error = dcbor::Error;
199
200 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
201 let bytes = cbor.try_into_byte_string()?;
202 if bytes.len() > 0xffff {
203 return Err("Script length exceeds maximum size of 65535 bytes".into());
204 }
205 Ok(Script(Data::from_vec(bytes)))
206 }
207}
208
209impl From<Script> for Envelope {
210 fn from(value: Script) -> Self {
211 Envelope::new(CBOR::from(value))
212 }
213}
214
215impl TryFrom<Envelope> for Script {
216 type Error = anyhow::Error;
217
218 fn try_from(envelope: Envelope) -> Result<Self, Self::Error> {
219 envelope.extract_subject().context("Script")
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use crate::{Data, test_cbor_roundtrip, test_envelope_roundtrip};
226
227 use super::Script;
228
229 impl crate::RandomInstance for Script {
230 fn random_with_size(size: usize) -> Self {
231 Self(Data::random_with_size(size))
232 }
233
234 fn random() -> Self {
235 Self(Data::random())
236 }
237 }
238
239 test_cbor_roundtrip!(Script);
240 test_envelope_roundtrip!(Script);
241}