ergotree_ir/mir/
sigma_and.rs

1//! AND conjunction for sigma propositions
2
3use std::convert::TryInto;
4
5use crate::serialization::op_code::OpCode;
6use crate::serialization::sigma_byte_reader::SigmaByteRead;
7use crate::serialization::sigma_byte_writer::SigmaByteWrite;
8use crate::serialization::SigmaParsingError;
9use crate::serialization::SigmaSerializable;
10use crate::serialization::SigmaSerializeResult;
11use crate::sigma_protocol::sigma_boolean::SigmaConjectureItems;
12use crate::types::stype::SType;
13
14use super::expr::Expr;
15use super::expr::InvalidArgumentError;
16use crate::has_opcode::HasStaticOpCode;
17
18/// AND conjunction for sigma propositions
19#[derive(PartialEq, Eq, Debug, Clone)]
20pub struct SigmaAnd {
21    /// Collection of SSigmaProp
22    pub items: SigmaConjectureItems<Expr>,
23}
24
25impl SigmaAnd {
26    /// Create new object, returns an error if any of the requirements failed
27    pub fn new(items: Vec<Expr>) -> Result<Self, InvalidArgumentError> {
28        let item_types: Vec<SType> = items
29            .clone()
30            .into_iter()
31            .map(|it| it.post_eval_tpe())
32            .collect();
33        if item_types
34            .iter()
35            .all(|tpe| matches!(tpe, SType::SSigmaProp))
36        {
37            Ok(Self {
38                items: items.try_into()?,
39            })
40        } else {
41            Err(InvalidArgumentError(format!(
42                "Sigma conjecture: expected all items be of type SSigmaProp, got {:?},\n items: {:?}",
43                item_types, items
44            )))
45        }
46    }
47
48    /// Type
49    pub fn tpe(&self) -> SType {
50        SType::SSigmaProp
51    }
52}
53
54impl HasStaticOpCode for SigmaAnd {
55    const OP_CODE: OpCode = OpCode::SIGMA_AND;
56}
57
58impl SigmaSerializable for SigmaAnd {
59    fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
60        self.items.sigma_serialize(w)
61    }
62
63    fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
64        Ok(Self::new(Vec::<Expr>::sigma_parse(r)?)?)
65    }
66}
67
68/// Arbitrary impl
69#[cfg(feature = "arbitrary")]
70#[allow(clippy::unwrap_used)]
71mod arbitrary {
72    use super::*;
73    use crate::mir::constant::Constant;
74    use proptest::collection::vec;
75    use proptest::prelude::*;
76
77    impl Arbitrary for SigmaAnd {
78        type Strategy = BoxedStrategy<Self>;
79        type Parameters = ();
80
81        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
82            vec(any_with::<Constant>(SType::SSigmaProp.into()), 2..5)
83                .prop_map(|constants| Self {
84                    items: constants
85                        .into_iter()
86                        .map(|c| c.into())
87                        .collect::<Vec<Expr>>()
88                        .try_into()
89                        .unwrap(),
90                })
91                .boxed()
92        }
93    }
94}
95
96#[cfg(test)]
97#[allow(clippy::panic)]
98mod tests {
99    use super::*;
100    use crate::mir::expr::Expr;
101    use crate::serialization::sigma_serialize_roundtrip;
102    use proptest::prelude::*;
103
104    proptest! {
105
106        #[test]
107        fn ser_roundtrip(v in any::<SigmaAnd>()) {
108            let expr: Expr = v.into();
109            prop_assert_eq![sigma_serialize_roundtrip(&expr), expr];
110        }
111
112    }
113}