clvm_utils/
curried_program.rs1use clvm_traits::{
2 clvm_list, clvm_quote, destructure_list, destructure_quote, match_list, match_quote,
3 ClvmDecoder, ClvmEncoder, FromClvm, FromClvmError, MatchByte, ToClvm, ToClvmError,
4};
5
6#[derive(Debug, Clone)]
7pub struct CurriedProgram<P, A> {
8 pub program: P,
9 pub args: A,
10}
11
12impl<N, D: ClvmDecoder<Node = N>, P, A> FromClvm<D> for CurriedProgram<P, A>
13where
14 P: FromClvm<D>,
15 A: FromClvm<D>,
16{
17 fn from_clvm(decoder: &D, node: N) -> Result<Self, FromClvmError> {
18 let destructure_list!(_, destructure_quote!(program), args) =
19 <match_list!(MatchByte<2>, match_quote!(P), A)>::from_clvm(decoder, node)?;
20 Ok(Self { program, args })
21 }
22}
23
24impl<N, E: ClvmEncoder<Node = N>, P, A> ToClvm<E> for CurriedProgram<P, A>
25where
26 P: ToClvm<E>,
27 A: ToClvm<E>,
28{
29 fn to_clvm(&self, encoder: &mut E) -> Result<N, ToClvmError> {
30 clvm_list!(2, clvm_quote!(&self.program), &self.args).to_clvm(encoder)
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use std::fmt::Debug;
37
38 use clvm_traits::clvm_curried_args;
39 use clvmr::{serde::node_to_bytes, Allocator};
40
41 use super::*;
42
43 fn check<P, A>(program: &P, args: &A, expected: &str)
44 where
45 P: Debug + PartialEq + ToClvm<Allocator> + FromClvm<Allocator>,
46 A: Debug + PartialEq + ToClvm<Allocator> + FromClvm<Allocator>,
47 {
48 let a = &mut Allocator::new();
49
50 let curry = CurriedProgram {
51 program: &program,
52 args: &args,
53 }
54 .to_clvm(a)
55 .unwrap();
56 let actual = node_to_bytes(a, curry).unwrap();
57 assert_eq!(hex::encode(actual), expected);
58
59 let curried = CurriedProgram::<P, A>::from_clvm(a, curry).unwrap();
60 assert_eq!(&curried.program, program);
61 assert_eq!(&curried.args, args);
62 }
63
64 #[test]
65 fn curry() {
66 check(
67 &"xyz".to_string(),
68 &clvm_curried_args!("a".to_string(), "b".to_string(), "c".to_string()),
69 "ff02ffff018378797affff04ffff0161ffff04ffff0162ffff04ffff0163ff0180808080",
70 );
71 }
72}