depo_api/request/
delete_shares.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::collections::HashSet;

use bc_envelope::prelude::*;
use anyhow::{Error, Result};

use crate::{receipt::Receipt, DELETE_SHARES_FUNCTION, RECEIPT_PARAM, util::{Abbrev, FlankedFunction}};

//
// Request
//

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DeleteShares(HashSet<Receipt>);

impl DeleteShares {
    pub fn new<I, T>(iterable: I) -> Self
    where
        I: IntoIterator<Item = T>,
        T: Clone + Into<Receipt>,
    {
        Self(iterable.into_iter().map(|item| item.clone().into()).collect())
    }

    pub fn receipts(&self) -> &HashSet<Receipt> {
        &self.0
    }
}

impl From<DeleteShares> for Expression {
    fn from(value: DeleteShares) -> Self {
        let mut expression = Expression::new(DELETE_SHARES_FUNCTION);
        for receipt in value.0.into_iter() {
            expression = expression.with_parameter(RECEIPT_PARAM, receipt);
        }
        expression
    }
}

impl TryFrom<Expression> for DeleteShares {
    type Error = Error;

    fn try_from(expression: Expression) -> Result<Self> {
        let receipts = expression
            .objects_for_parameter(RECEIPT_PARAM)
            .into_iter()
            .map(|parameter| parameter.try_into())
            .collect::<Result<HashSet<Receipt>>>()?;
        Ok(Self::new(receipts))
    }
}

impl std::fmt::Display for DeleteShares {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("{} {}",
            "deleteShares".flanked_function(),
            self.receipts().abbrev(),
        ))
    }
}

#[cfg(test)]
mod tests {
    use bc_components::ARID;
    use indoc::indoc;

    use super::*;

    fn user_id() -> ARID {
        ARID::from_data_ref(hex_literal::hex!(
            "8712dfac3d0ebfa910736b2a9ee39d4b68f64222a77bcc0074f3f5f1c9216d30"
        ))
        .unwrap()
    }

    fn receipt_1() -> Receipt {
        Receipt::new(&user_id(), b"data_1")
    }

    fn receipt_2() -> Receipt {
        Receipt::new(&user_id(), b"data_2")
    }

    #[test]
    fn test_request() {
        bc_envelope::register_tags();

        let receipts = vec![receipt_1(), receipt_2()];

        let request = DeleteShares::new(receipts);
        let expression: Expression = request.clone().into();
        let request_envelope = expression.to_envelope();
        // println!("{}", request_envelope.format());
        assert_eq!(request_envelope.format(), indoc! {r#"
        «"deleteShares"» [
            ❰"receipt"❱: Bytes(32) [
                'isA': "Receipt"
            ]
            ❰"receipt"❱: Bytes(32) [
                'isA': "Receipt"
            ]
        ]
        "#}.trim());
        let decoded_expression = Expression::try_from(request_envelope).unwrap();
        let decoded = DeleteShares::try_from(decoded_expression).unwrap();
        assert_eq!(request, decoded);
    }
}