depo_api/request/
delete_shares.rs

1use std::collections::HashSet;
2
3use bc_envelope::prelude::*;
4
5use crate::{
6    DELETE_SHARES_FUNCTION, Error, RECEIPT_PARAM, RECEIPT_PARAM_NAME, Result,
7    receipt::Receipt,
8    util::{Abbrev, FlankedFunction},
9};
10
11//
12// Request
13//
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct DeleteShares(HashSet<Receipt>);
17
18impl DeleteShares {
19    pub fn new<I, T>(iterable: I) -> Self
20    where
21        I: IntoIterator<Item = T>,
22        T: Clone + Into<Receipt>,
23    {
24        Self(
25            iterable
26                .into_iter()
27                .map(|item| item.clone().into())
28                .collect(),
29        )
30    }
31
32    pub fn receipts(&self) -> &HashSet<Receipt> { &self.0 }
33}
34
35impl From<DeleteShares> for Expression {
36    fn from(value: DeleteShares) -> Self {
37        let mut expression = Expression::new(DELETE_SHARES_FUNCTION);
38        for receipt in value.0.into_iter() {
39            expression = expression.with_parameter(RECEIPT_PARAM, receipt);
40        }
41        expression
42    }
43}
44
45impl TryFrom<Expression> for DeleteShares {
46    type Error = Error;
47
48    fn try_from(expression: Expression) -> Result<Self> {
49        let receipts = expression
50            .objects_for_parameter(RECEIPT_PARAM)
51            .into_iter()
52            .map(|parameter| {
53                parameter.try_into().map_err(|e| Error::InvalidParameter {
54                    parameter: RECEIPT_PARAM_NAME.to_string(),
55                    message: format!("failed to convert to Receipt: {}", e),
56                })
57            })
58            .collect::<Result<HashSet<Receipt>>>()?;
59        Ok(Self::new(receipts))
60    }
61}
62
63impl std::fmt::Display for DeleteShares {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        f.write_fmt(format_args!(
66            "{} {}",
67            "deleteShares".flanked_function(),
68            self.receipts().abbrev()
69        ))
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use bc_components::XID;
76    use indoc::indoc;
77
78    use super::*;
79
80    fn user_id() -> XID {
81        XID::from_data_ref(hex_literal::hex!(
82            "8712dfac3d0ebfa910736b2a9ee39d4b68f64222a77bcc0074f3f5f1c9216d30"
83        ))
84        .unwrap()
85    }
86
87    fn receipt_1() -> Receipt { Receipt::new(user_id(), b"data_1") }
88
89    fn receipt_2() -> Receipt { Receipt::new(user_id(), b"data_2") }
90
91    #[test]
92    fn test_request() {
93        bc_envelope::register_tags();
94
95        let receipts = vec![receipt_1(), receipt_2()];
96
97        let request = DeleteShares::new(receipts);
98        let expression: Expression = request.clone().into();
99        let request_envelope = expression.to_envelope();
100        // println!("{}", request_envelope.format());
101        #[rustfmt::skip]
102        assert_eq!(request_envelope.format(), indoc! {r#"
103            «"deleteShares"» [
104                ❰"receipt"❱: Bytes(32) [
105                    'isA': "Receipt"
106                ]
107                ❰"receipt"❱: Bytes(32) [
108                    'isA': "Receipt"
109                ]
110            ]
111        "#}.trim());
112        let decoded_expression =
113            Expression::try_from(request_envelope).unwrap();
114        let decoded = DeleteShares::try_from(decoded_expression).unwrap();
115        assert_eq!(request, decoded);
116    }
117}