1#[cfg(feature = "bitcoin")]
16pub mod bitcoin;
17pub mod core;
18#[cfg(feature = "elements")]
19pub mod elements;
20mod init;
21pub mod type_name;
22
23pub use self::core::CoreEnv;
24#[cfg(feature = "bitcoin")]
25pub use crate::jet::bitcoin::BitcoinEnv;
26#[cfg(feature = "elements")]
27pub use elements::ElementsTxEnv;
28
29#[cfg(feature = "bitcoin")]
30pub use init::bitcoin::Bitcoin;
31pub use init::core::Core;
32#[cfg(feature = "elements")]
33pub use init::elements::Elements;
34use simplicity_sys::c_jets::frame_ffi::CFrameItem;
35
36use crate::analysis::Cost;
37use crate::decode;
38use crate::jet::type_name::TypeName;
39use crate::merkle::cmr::Cmr;
40use crate::{BitIter, BitWriter};
41use std::any::{Any, TypeId};
42use std::cmp::Ordering;
43use std::hash::{Hash, Hasher};
44use std::io::Write;
45
46#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
50pub struct JetFailed;
51
52impl std::fmt::Display for JetFailed {
53 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
54 f.write_str("Jet failed during execution")
55 }
56}
57
58impl std::error::Error for JetFailed {}
59
60pub trait JetEnvironment {
62 type Jet: Jet;
64
65 type CJetEnvironment;
67
68 fn c_jet_env(&self) -> &Self::CJetEnvironment;
70
71 fn c_jet_ptr(
73 jet: &Self::Jet,
74 ) -> fn(&mut CFrameItem, CFrameItem, &Self::CJetEnvironment) -> bool;
75}
76
77pub trait Jet: DynJet + std::fmt::Debug + std::fmt::Display + Send + Sync + 'static {
86 fn cmr(&self) -> Cmr;
88
89 fn source_ty(&self) -> TypeName;
91
92 fn target_ty(&self) -> TypeName;
94
95 fn encode(&self, w: &mut BitWriter<&mut dyn Write>) -> std::io::Result<usize>;
97
98 fn decode<I: Iterator<Item = u8>>(bits: &mut BitIter<I>) -> Result<Self, decode::Error>
100 where
101 Self: Sized;
102
103 fn cost(&self) -> Cost;
105
106 fn parse(s: &str) -> Result<Self, crate::Error>
108 where
109 Self: Sized;
110}
111
112pub trait DynJet {
114 fn as_any(&self) -> &dyn Any;
115 fn dyn_clone(&self) -> Box<dyn Jet>;
116 fn dyn_eq(&self, other: &dyn Jet) -> bool;
117 fn dyn_cmp(&self, other: &dyn Jet) -> Ordering;
118 fn dyn_hash(&self, state: &mut dyn Hasher);
119}
120
121impl<T: Jet + Clone + Ord + Hash> DynJet for T {
122 fn as_any(&self) -> &dyn Any {
123 self
124 }
125
126 fn dyn_clone(&self) -> Box<dyn Jet> {
127 Box::new(self.clone())
128 }
129
130 fn dyn_eq(&self, other: &dyn Jet) -> bool {
131 other
132 .as_any()
133 .downcast_ref::<Self>()
134 .is_some_and(|other| self == other)
135 }
136
137 fn dyn_cmp(&self, other: &dyn Jet) -> Ordering {
138 match other.as_any().downcast_ref::<Self>() {
139 Some(other) => self.cmp(other),
140 None => TypeId::of::<Self>().cmp(&other.as_any().type_id()),
141 }
142 }
143
144 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
145 self.hash(&mut state)
146 }
147}
148
149impl Clone for Box<dyn Jet> {
150 fn clone(&self) -> Self {
151 (**self).dyn_clone()
152 }
153}
154
155impl PartialEq for Box<dyn Jet> {
156 fn eq(&self, other: &Self) -> bool {
157 (**self).dyn_eq(&**other)
158 }
159}
160
161impl Eq for Box<dyn Jet> {}
162
163impl PartialOrd for Box<dyn Jet> {
164 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
165 Some(self.cmp(other))
166 }
167}
168
169impl Ord for Box<dyn Jet> {
170 fn cmp(&self, other: &Self) -> Ordering {
171 (**self).dyn_cmp(&**other)
172 }
173}
174
175impl Hash for Box<dyn Jet> {
176 fn hash<H: Hasher>(&self, state: &mut H) {
177 (**self).dyn_hash(state)
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use crate::jet::{Core, CoreEnv};
184 use crate::node::{ConstructNode, CoreConstructible, JetConstructible};
185 use crate::types;
186 use crate::value::Word;
187 use crate::{BitMachine, Value};
188 use std::sync::Arc;
189
190 #[test]
191 fn test_ffi_jet() {
192 types::Context::with_context(|ctx| {
193 let two_words = Arc::<ConstructNode>::comp(
194 &Arc::<ConstructNode>::pair(
195 &Arc::<ConstructNode>::const_word(&ctx, Word::u32(2)),
196 &Arc::<ConstructNode>::const_word(&ctx, Word::u32(16)),
197 )
198 .unwrap(),
199 &Arc::<ConstructNode>::jet(&ctx, &Core::Add32),
200 )
201 .unwrap();
202 assert_eq!(
203 BitMachine::test_exec(two_words, &CoreEnv::new()).expect("executing"),
204 Value::product(
205 Value::u1(0), Value::u32(2 + 16), ),
208 );
209 });
210 }
211
212 #[test]
213 fn test_simple() {
214 types::Context::with_context(|ctx| {
215 let two_words = Arc::<ConstructNode>::pair(
216 &Arc::<ConstructNode>::const_word(&ctx, Word::u32(2)),
217 &Arc::<ConstructNode>::const_word(&ctx, Word::u16(16)),
218 )
219 .unwrap();
220 assert_eq!(
221 BitMachine::test_exec(two_words, &CoreEnv::new()).expect("executing"),
222 Value::product(Value::u32(2), Value::u16(16)),
223 );
224 });
225 }
226}