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
108
109
110
111
// Storm Core library: distributed storage & messaging for lightning network.
//
// Written in 2022 by
//     Dr. Maxim Orlovsky <orlovsky@lnp-bp.org>
//
// Copyright (C) 2022 by LNP/BP Standards Association, Switzerland.
//
// You should have received a copy of the MIT License along with this software.
// If not, see <https://opensource.org/licenses/MIT>.

use internet2::{CreateUnmarshaller, Unmarshaller};
use once_cell::sync::Lazy;

use crate::{Chunk, ChunkId, Container, Mesg, MesgId, StormApp};

pub static STORM_P2P_UNMARSHALLER: Lazy<Unmarshaller<Messages>> =
    Lazy::new(|| Messages::create_unmarshaller());

pub trait StormMesg {
    fn storm_app(&self) -> StormApp;
}

#[derive(Clone, Debug, Display, Api, NetworkEncode, NetworkDecode)]
#[api(encoding = "strict")]
#[non_exhaustive]
#[display(inner)]
pub enum Messages {
    #[api(type = 0x0010)]
    Post(PostReq),

    #[api(type = 0x0011)]
    Read(ReadReq),

    #[api(type = 0x0012)]
    Push(ChunkPush),

    #[api(type = 0x0013)]
    Chunk(ChunkPull),

    #[api(type = 0x0020)]
    Decline(DeclineResp),
}

impl StormMesg for Messages {
    fn storm_app(&self) -> StormApp {
        match self {
            Messages::Post(msg) => msg.storm_app(),
            Messages::Read(msg) => msg.storm_app(),
            Messages::Push(msg) => msg.storm_app(),
            Messages::Chunk(msg) => msg.storm_app(),
            Messages::Decline(msg) => msg.storm_app(),
        }
    }
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display("post({app}, {message})")]
pub struct PostReq {
    pub app: StormApp,
    pub message: Mesg,
    pub container: Option<Container>,
}

impl StormMesg for PostReq {
    fn storm_app(&self) -> StormApp { self.app }
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display("read({app}, {message_id}, {with_container})")]
pub struct ReadReq {
    pub app: StormApp,
    pub message_id: MesgId,
    pub with_container: bool,
}

impl StormMesg for ReadReq {
    fn storm_app(&self) -> StormApp { self.app }
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display("push({app}, ...)")]
pub struct ChunkPush {
    pub app: StormApp,
    pub chunk: Chunk,
}

impl StormMesg for ChunkPush {
    fn storm_app(&self) -> StormApp { self.app }
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display("chunk({app}, {chunk_id})")]
pub struct ChunkPull {
    pub app: StormApp,
    pub chunk_id: ChunkId,
}

impl StormMesg for ChunkPull {
    fn storm_app(&self) -> StormApp { self.app }
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display("decline({app}, {mesg_id})")]
pub struct DeclineResp {
    pub app: StormApp,
    pub mesg_id: MesgId,
}

impl StormMesg for DeclineResp {
    fn storm_app(&self) -> StormApp { self.app }
}