ckb_script_ipc_common/
packet.rs

1use alloc::string::String;
2use alloc::vec;
3use alloc::vec::Vec;
4use core::fmt::{Debug, Formatter, Result as FmtResult};
5
6use crate::error::IpcError;
7use crate::io::Read;
8use crate::vlq::{vlq_decode, vlq_encode};
9
10/// The `Packet` trait defines the interface for handling packets in an IPC context.
11/// Types implementing this trait can be used to represent and manipulate packets.
12///
13/// # Required Methods
14///
15/// * `version` - This method returns the version of the packet.
16/// * `payload` - This method returns a reference to the payload of the packet.
17/// * `read_from` - This method reads a packet from a reader and returns an instance of the implementing type.
18/// * `serialize` - This method serializes the packet into a vector of bytes.
19pub trait Packet {
20    fn version(&self) -> u8;
21    fn payload(&self) -> &[u8];
22    fn read_from<R: Read>(reader: &mut R) -> Result<Self, IpcError>
23    where
24        Self: Sized;
25    fn serialize(&self) -> Vec<u8>;
26}
27
28pub struct RequestPacket {
29    version: u8,
30    method_id: u64,
31    payload: Vec<u8>,
32}
33
34impl Debug for RequestPacket {
35    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
36        write!(
37            f,
38            "RequestPacket, {} bytes payload: {}",
39            self.payload.len(),
40            String::from_utf8_lossy(&self.payload)
41        )
42    }
43}
44
45impl Packet for RequestPacket {
46    fn version(&self) -> u8 {
47        self.version
48    }
49    fn payload(&self) -> &[u8] {
50        &self.payload
51    }
52    fn read_from<R: Read>(reader: &mut R) -> Result<Self, IpcError> {
53        let version = read_next_vlq(reader)? as u8;
54        let method_id = read_next_vlq(reader)?;
55        let payload_length = read_next_vlq(reader)?;
56        let mut payload = vec![0u8; payload_length as usize];
57        reader
58            .read_exact(&mut payload[..])
59            .map_err(|_| IpcError::ReadExactError)?;
60        Ok(RequestPacket {
61            version,
62            method_id,
63            payload,
64        })
65    }
66    fn serialize(&self) -> Vec<u8> {
67        let mut buf = vec![];
68        buf.extend_from_slice(&vlq_encode(self.version as u64));
69        buf.extend_from_slice(&vlq_encode(self.method_id));
70        buf.extend_from_slice(&vlq_encode(self.payload.len() as u64));
71        buf.extend_from_slice(&self.payload);
72        buf
73    }
74}
75
76impl RequestPacket {
77    pub fn new(payload: Vec<u8>) -> Self {
78        Self {
79            version: 0,
80            method_id: 0,
81            payload,
82        }
83    }
84    pub fn method_id(&self) -> u64 {
85        self.method_id
86    }
87}
88
89pub struct ResponsePacket {
90    version: u8,
91    error_code: u64,
92    payload: Vec<u8>,
93}
94
95impl Debug for ResponsePacket {
96    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
97        write!(
98            f,
99            "ResponsePacket, error_code: {}, {} bytes payload: {}",
100            self.error_code,
101            self.payload.len(),
102            String::from_utf8_lossy(&self.payload)
103        )
104    }
105}
106
107impl Packet for ResponsePacket {
108    fn version(&self) -> u8 {
109        self.version
110    }
111    fn payload(&self) -> &[u8] {
112        &self.payload
113    }
114    fn read_from<R: Read>(reader: &mut R) -> Result<Self, IpcError> {
115        let version = read_next_vlq(reader)? as u8;
116        let error_code = read_next_vlq(reader)?;
117        let payload_length = read_next_vlq(reader)?;
118        let mut payload = vec![0u8; payload_length as usize];
119        reader
120            .read_exact(&mut payload[..])
121            .map_err(|_| IpcError::ReadExactError)?;
122        Ok(ResponsePacket {
123            version,
124            error_code,
125            payload,
126        })
127    }
128    fn serialize(&self) -> Vec<u8> {
129        let mut buf = vec![];
130        buf.extend_from_slice(&vlq_encode(self.version as u64));
131        buf.extend_from_slice(&vlq_encode(self.error_code));
132        buf.extend_from_slice(&vlq_encode(self.payload.len() as u64));
133        buf.extend_from_slice(&self.payload);
134        buf
135    }
136}
137
138impl ResponsePacket {
139    pub fn new(error_code: u64, payload: Vec<u8>) -> Self {
140        Self {
141            version: 0,
142            error_code,
143            payload,
144        }
145    }
146    pub fn error_code(&self) -> u64 {
147        self.error_code
148    }
149}
150
151pub fn read_next_vlq(reader: &mut impl Read) -> Result<u64, IpcError> {
152    let mut peek = [0u8; 1];
153    let mut buf = vec![];
154    loop {
155        let n = reader.read(&mut peek).map_err(|_| IpcError::ReadVlqError)?;
156        if n == 0 {
157            break;
158        }
159        buf.push(peek[0]);
160        if peek[0] & 0x80 == 0 {
161            break;
162        }
163    }
164    vlq_decode(&buf)
165}