Skip to main content

shank_parse/
lib.rs

1pub use shank_parse_macro::shank_parse;
2
3#[doc(hidden)]
4pub mod __private {
5    pub use solana_sdk::instruction::{AccountMeta, Instruction};
6    pub use solana_sdk::pubkey::Pubkey;
7
8    use base64::Engine;
9
10    pub fn base64_decode(input: &str) -> Result<Vec<u8>, base64::DecodeError> {
11        base64::engine::general_purpose::STANDARD.decode(input)
12    }
13
14    pub fn base64_encode(data: &[u8]) -> String {
15        base64::engine::general_purpose::STANDARD.encode(data)
16    }
17
18    // Read helpers
19
20    pub fn read_u8(data: &[u8], offset: &mut usize) -> Result<u8, std::io::Error> {
21        if *offset >= data.len() {
22            return Err(std::io::Error::new(
23                std::io::ErrorKind::UnexpectedEof,
24                "unexpected eof",
25            ));
26        }
27        let val = data[*offset];
28        *offset += 1;
29        Ok(val)
30    }
31
32    pub fn read_bool(data: &[u8], offset: &mut usize) -> Result<bool, std::io::Error> {
33        Ok(read_u8(data, offset)? != 0)
34    }
35
36    macro_rules! impl_read_int {
37        ($fname:ident, $ty:ty, $size:expr) => {
38            pub fn $fname(data: &[u8], offset: &mut usize) -> Result<$ty, std::io::Error> {
39                let end = *offset + $size;
40                if end > data.len() {
41                    return Err(std::io::Error::new(
42                        std::io::ErrorKind::UnexpectedEof,
43                        "unexpected eof",
44                    ));
45                }
46                let mut bytes = [0u8; $size];
47                bytes.copy_from_slice(&data[*offset..end]);
48                *offset = end;
49                Ok(<$ty>::from_le_bytes(bytes))
50            }
51        };
52    }
53
54    impl_read_int!(read_u16, u16, 2);
55    impl_read_int!(read_u32, u32, 4);
56    impl_read_int!(read_u64, u64, 8);
57    impl_read_int!(read_u128, u128, 16);
58    impl_read_int!(read_i8, i8, 1);
59    impl_read_int!(read_i16, i16, 2);
60    impl_read_int!(read_i32, i32, 4);
61    impl_read_int!(read_i64, i64, 8);
62    impl_read_int!(read_i128, i128, 16);
63
64    pub fn read_bytes<const N: usize>(
65        data: &[u8],
66        offset: &mut usize,
67    ) -> Result<[u8; N], std::io::Error> {
68        let end = *offset + N;
69        if end > data.len() {
70            return Err(std::io::Error::new(
71                std::io::ErrorKind::UnexpectedEof,
72                "unexpected eof",
73            ));
74        }
75        let mut bytes = [0u8; N];
76        bytes.copy_from_slice(&data[*offset..end]);
77        *offset = end;
78        Ok(bytes)
79    }
80
81    // Write helpers
82
83    pub fn write_u8(data: &mut Vec<u8>, val: u8) {
84        data.push(val);
85    }
86
87    pub fn write_bool(data: &mut Vec<u8>, val: bool) {
88        data.push(val as u8);
89    }
90
91    macro_rules! impl_write_int {
92        ($fname:ident, $ty:ty) => {
93            pub fn $fname(data: &mut Vec<u8>, val: $ty) {
94                data.extend_from_slice(&val.to_le_bytes());
95            }
96        };
97    }
98
99    impl_write_int!(write_u16, u16);
100    impl_write_int!(write_u32, u32);
101    impl_write_int!(write_u64, u64);
102    impl_write_int!(write_u128, u128);
103    impl_write_int!(write_i8, i8);
104    impl_write_int!(write_i16, i16);
105    impl_write_int!(write_i32, i32);
106    impl_write_int!(write_i64, i64);
107    impl_write_int!(write_i128, i128);
108
109    pub fn write_bytes(data: &mut Vec<u8>, val: &[u8]) {
110        data.extend_from_slice(val);
111    }
112}