#[cfg(feature = "bitcoin")]
pub mod bitcoin;
pub mod core;
#[cfg(feature = "elements")]
pub mod elements;
mod init;
pub mod type_name;
pub use self::core::CoreEnv;
#[cfg(feature = "bitcoin")]
pub use crate::jet::bitcoin::BitcoinEnv;
#[cfg(feature = "elements")]
pub use elements::ElementsTxEnv;
#[cfg(feature = "bitcoin")]
pub use init::bitcoin::Bitcoin;
pub use init::core::Core;
#[cfg(feature = "elements")]
pub use init::elements::Elements;
use simplicity_sys::c_jets::frame_ffi::CFrameItem;
use crate::analysis::Cost;
use crate::decode;
use crate::jet::type_name::TypeName;
use crate::merkle::cmr::Cmr;
use crate::{BitIter, BitWriter};
use std::any::{Any, TypeId};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::io::Write;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct JetFailed;
impl std::fmt::Display for JetFailed {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str("Jet failed during execution")
}
}
impl std::error::Error for JetFailed {}
pub trait JetEnvironment {
type Jet: Jet;
type CJetEnvironment;
fn c_jet_env(&self) -> &Self::CJetEnvironment;
fn c_jet_ptr(
jet: &Self::Jet,
) -> fn(&mut CFrameItem, CFrameItem, &Self::CJetEnvironment) -> bool;
}
pub trait Jet: DynJet + std::fmt::Debug + std::fmt::Display + Send + Sync + 'static {
fn cmr(&self) -> Cmr;
fn source_ty(&self) -> TypeName;
fn target_ty(&self) -> TypeName;
fn encode(&self, w: &mut BitWriter<&mut dyn Write>) -> std::io::Result<usize>;
fn decode<I: Iterator<Item = u8>>(bits: &mut BitIter<I>) -> Result<Self, decode::Error>
where
Self: Sized;
fn cost(&self) -> Cost;
fn parse(s: &str) -> Result<Self, crate::Error>
where
Self: Sized;
}
pub trait DynJet {
fn as_any(&self) -> &dyn Any;
fn dyn_clone(&self) -> Box<dyn Jet>;
fn dyn_eq(&self, other: &dyn Jet) -> bool;
fn dyn_cmp(&self, other: &dyn Jet) -> Ordering;
fn dyn_hash(&self, state: &mut dyn Hasher);
}
impl<T: Jet + Clone + Ord + Hash> DynJet for T {
fn as_any(&self) -> &dyn Any {
self
}
fn dyn_clone(&self) -> Box<dyn Jet> {
Box::new(self.clone())
}
fn dyn_eq(&self, other: &dyn Jet) -> bool {
other
.as_any()
.downcast_ref::<Self>()
.is_some_and(|other| self == other)
}
fn dyn_cmp(&self, other: &dyn Jet) -> Ordering {
match other.as_any().downcast_ref::<Self>() {
Some(other) => self.cmp(other),
None => TypeId::of::<Self>().cmp(&other.as_any().type_id()),
}
}
fn dyn_hash(&self, mut state: &mut dyn Hasher) {
self.hash(&mut state)
}
}
impl Clone for Box<dyn Jet> {
fn clone(&self) -> Self {
(**self).dyn_clone()
}
}
impl PartialEq for Box<dyn Jet> {
fn eq(&self, other: &Self) -> bool {
(**self).dyn_eq(&**other)
}
}
impl Eq for Box<dyn Jet> {}
impl PartialOrd for Box<dyn Jet> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Box<dyn Jet> {
fn cmp(&self, other: &Self) -> Ordering {
(**self).dyn_cmp(&**other)
}
}
impl Hash for Box<dyn Jet> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).dyn_hash(state)
}
}
#[cfg(test)]
mod tests {
use crate::jet::{Core, CoreEnv};
use crate::node::{ConstructNode, CoreConstructible, JetConstructible};
use crate::types;
use crate::value::Word;
use crate::{BitMachine, Value};
use std::sync::Arc;
#[test]
fn test_ffi_jet() {
types::Context::with_context(|ctx| {
let two_words = Arc::<ConstructNode>::comp(
&Arc::<ConstructNode>::pair(
&Arc::<ConstructNode>::const_word(&ctx, Word::u32(2)),
&Arc::<ConstructNode>::const_word(&ctx, Word::u32(16)),
)
.unwrap(),
&Arc::<ConstructNode>::jet(&ctx, &Core::Add32),
)
.unwrap();
assert_eq!(
BitMachine::test_exec(two_words, &CoreEnv::new()).expect("executing"),
Value::product(
Value::u1(0), Value::u32(2 + 16), ),
);
});
}
#[test]
fn test_simple() {
types::Context::with_context(|ctx| {
let two_words = Arc::<ConstructNode>::pair(
&Arc::<ConstructNode>::const_word(&ctx, Word::u32(2)),
&Arc::<ConstructNode>::const_word(&ctx, Word::u16(16)),
)
.unwrap();
assert_eq!(
BitMachine::test_exec(two_words, &CoreEnv::new()).expect("executing"),
Value::product(Value::u32(2), Value::u16(16)),
);
});
}
}