workflow_nw/ipc/
messages.rs

1use crate::ipc::error::Error;
2use crate::ipc::imports::*;
3use borsh::{BorshDeserialize, BorshSerialize};
4use js_sys::{ArrayBuffer, Uint8Array};
5use std::fmt::Debug;
6
7pub fn to_msg<Ops, Id>(header: BorshHeader<Id>, payload: &[u8]) -> Result<ArrayBuffer>
8where
9    Id: IdT,
10    Ops: BorshSerialize + BorshDeserialize,
11{
12    let header = borsh::to_vec(&header).expect("to_msg header serialize error");
13    // log_info!("header: {:?}", header);
14    // log_info!("payload: {:?}", payload);
15    let header_len = header.len();
16    let len = payload.len() + header_len;
17    let mut buffer = Vec::with_capacity(len);
18    #[allow(clippy::uninit_vec)]
19    unsafe {
20        buffer.set_len(len);
21    }
22    buffer[0..header_len].copy_from_slice(&header);
23    buffer[header_len..].copy_from_slice(payload);
24    // log_info!("to_msg buffer: {:?}", buffer);
25
26    let array = Uint8Array::from(&buffer[..]);
27    Ok(array.buffer())
28}
29
30#[derive(Debug, Clone, Copy, BorshSerialize, BorshDeserialize)]
31#[repr(u8)]
32#[borsh(use_discriminant = true)]
33pub enum MessageKind {
34    Notification = 0,
35    Request = 1,
36    Response = 2,
37}
38
39impl From<MessageKind> for u32 {
40    fn from(kind: MessageKind) -> u32 {
41        kind as u32
42    }
43}
44
45#[derive(Debug, BorshSerialize, BorshDeserialize)]
46pub struct BorshHeader<Id = Id64>
47where
48    Id: BorshSerialize + BorshDeserialize,
49{
50    pub kind: MessageKind,
51    pub id: Option<Id>,
52    pub op: Vec<u8>,
53}
54
55impl<Id> BorshHeader<Id>
56where
57    Id: BorshSerialize + BorshDeserialize,
58{
59    pub fn request<Ops>(id: Option<Id>, op: Ops) -> Self
60    where
61        Ops: OpsT,
62    {
63        BorshHeader {
64            id,
65            op: borsh::to_vec(&op).expect("request op serialize error"),
66            kind: MessageKind::Request,
67        }
68    }
69
70    pub fn response<Ops>(id: Option<Id>, op: Ops) -> Self
71    where
72        Ops: OpsT,
73    {
74        BorshHeader {
75            id,
76            op: borsh::to_vec(&op).expect("response op serialize error"),
77            kind: MessageKind::Response,
78        }
79    }
80
81    pub fn notification<Ops>(op: Ops) -> Self
82    where
83        Ops: OpsT,
84    {
85        BorshHeader {
86            id: None,
87            op: borsh::to_vec(&op).expect("notification op serialize error"),
88            kind: MessageKind::Notification,
89        }
90    }
91}
92
93#[derive(Debug)]
94pub struct BorshMessage<'data, Id = Id64>
95where
96    Id: BorshSerialize + BorshDeserialize + 'data,
97{
98    pub header: BorshHeader<Id>,
99    pub payload: &'data [u8],
100}
101
102impl<'data, Id> TryFrom<&'data Vec<u8>> for BorshMessage<'data, Id>
103where
104    Id: Debug + BorshSerialize + BorshDeserialize + 'data,
105{
106    type Error = Error;
107
108    fn try_from(src: &'data Vec<u8>) -> std::result::Result<Self, Self::Error> {
109        let v: BorshMessage<Id> = src[..].try_into()?;
110        Ok(v)
111    }
112}
113
114impl<'data, Id> TryFrom<&'data [u8]> for BorshMessage<'data, Id>
115where
116    Id: Debug + BorshSerialize + BorshDeserialize + 'data,
117{
118    type Error = Error;
119
120    fn try_from(src: &'data [u8]) -> std::result::Result<Self, Self::Error> {
121        let mut payload = src;
122        let header = BorshHeader::<Id>::deserialize(&mut payload)?;
123        let message = BorshMessage { header, payload };
124        Ok(message)
125    }
126}