substrate_stellar_xdr/
xdr_codec.rs1use base64::{decode_config_slice, encode_config_slice};
4use core::convert::{AsRef, TryInto};
5use sp_std::{boxed::Box, vec::Vec};
6
7use crate::streams::{DecodeError, ReadStream, WriteStream};
8
9pub trait XdrCodec: Sized {
13 fn to_xdr(&self) -> Vec<u8> {
17 let mut write_stream = WriteStream::new();
18 self.to_xdr_buffered(&mut write_stream);
19 write_stream.get_result()
20 }
21
22 fn from_xdr<T: AsRef<[u8]>>(input: T) -> Result<Self, DecodeError> {
26 let mut read_stream = ReadStream::new(input);
27 let value = Self::from_xdr_buffered(&mut read_stream)?;
28 if read_stream.no_of_bytes_left_to_read() != 0 {
29 return Err(DecodeError::TypeEndsTooEarly {
30 remaining_no_of_bytes: read_stream.no_of_bytes_left_to_read(),
31 });
32 }
33
34 Ok(value)
35 }
36
37 fn to_base64_xdr(&self) -> Vec<u8> {
42 let xdr = self.to_xdr();
43 let mut base64_buffer = Vec::new();
44 base64_buffer.resize(xdr.len() * 4 / 3 + 4, 0);
45 let bytes_written = encode_config_slice(xdr, base64::STANDARD, &mut base64_buffer);
46 base64_buffer.resize(bytes_written, 0);
47 base64_buffer
48 }
49
50 fn from_base64_xdr<T: AsRef<[u8]>>(input: T) -> Result<Self, DecodeError> {
55 let input = input.as_ref();
56 let mut buf = Vec::new();
57 buf.resize(input.len() * 4 / 3 + 4, 0);
58
59 match decode_config_slice(input, base64::STANDARD, &mut buf) {
60 Ok(bytes_written) => {
61 buf.resize(bytes_written, 0);
62 Self::from_xdr(buf)
63 }
64 Err(_) => Err(DecodeError::InvalidBase64),
65 }
66 }
67
68 fn to_xdr_buffered(&self, write_stream: &mut WriteStream);
73
74 fn from_xdr_buffered<T: AsRef<[u8]>>(
79 read_stream: &mut ReadStream<T>,
80 ) -> Result<Self, DecodeError>;
81}
82
83impl XdrCodec for u64 {
85 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
86 write_stream.write_next_u64(*self);
87 }
88
89 fn from_xdr_buffered<T: AsRef<[u8]>>(
90 read_stream: &mut ReadStream<T>,
91 ) -> Result<Self, DecodeError> {
92 read_stream.read_next_u64()
93 }
94}
95
96impl XdrCodec for i64 {
98 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
99 write_stream.write_next_i64(*self);
100 }
101
102 fn from_xdr_buffered<T: AsRef<[u8]>>(
103 read_stream: &mut ReadStream<T>,
104 ) -> Result<Self, DecodeError> {
105 read_stream.read_next_i64()
106 }
107}
108
109impl XdrCodec for u32 {
111 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
112 write_stream.write_next_u32(*self);
113 }
114
115 fn from_xdr_buffered<T: AsRef<[u8]>>(
116 read_stream: &mut ReadStream<T>,
117 ) -> Result<Self, DecodeError> {
118 read_stream.read_next_u32()
119 }
120}
121
122impl XdrCodec for i32 {
124 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
125 write_stream.write_next_i32(*self);
126 }
127
128 fn from_xdr_buffered<T: AsRef<[u8]>>(
129 read_stream: &mut ReadStream<T>,
130 ) -> Result<Self, DecodeError> {
131 read_stream.read_next_i32()
132 }
133}
134
135impl XdrCodec for bool {
137 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
138 write_stream.write_next_i32(if *self { 1 } else { 0 });
139 }
140
141 fn from_xdr_buffered<T: AsRef<[u8]>>(
142 read_stream: &mut ReadStream<T>,
143 ) -> Result<Self, DecodeError> {
144 let parsed_int = read_stream.read_next_i32()?;
145 match parsed_int {
146 0 => Ok(false),
147 1 => Ok(true),
148 _ => Err(DecodeError::InvalidBoolean {
149 found_integer: parsed_int,
150 at_position: read_stream.get_position(),
151 }),
152 }
153 }
154}
155
156impl<T: XdrCodec, const N: usize> XdrCodec for [T; N] {
160 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
161 for item in self.iter() {
162 item.to_xdr_buffered(write_stream);
163 }
164 }
165
166 fn from_xdr_buffered<R: AsRef<[u8]>>(
167 read_stream: &mut ReadStream<R>,
168 ) -> Result<Self, DecodeError> {
169 let mut result = Vec::<T>::with_capacity(N);
170 for _ in 0..N {
171 result.push(T::from_xdr_buffered(read_stream)?)
172 }
173 result.try_into().map_err(|_| unreachable!())
174 }
175}
176
177impl<const N: usize> XdrCodec for [u8; N] {
179 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
180 write_stream.write_next_binary_data(self);
181 }
182
183 fn from_xdr_buffered<T: AsRef<[u8]>>(
184 read_stream: &mut ReadStream<T>,
185 ) -> Result<Self, DecodeError> {
186 let value = read_stream.read_next_binary_data(N)?;
187 value.try_into().map_err(|_| unreachable!())
188 }
189}
190
191impl<T: XdrCodec> XdrCodec for Option<T> {
195 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
196 match self {
197 None => write_stream.write_next_u32(0),
198 Some(value) => {
199 write_stream.write_next_u32(1);
200 value.to_xdr_buffered(write_stream);
201 }
202 }
203 }
204
205 fn from_xdr_buffered<R: AsRef<[u8]>>(
206 read_stream: &mut ReadStream<R>,
207 ) -> Result<Self, DecodeError> {
208 match read_stream.read_next_u32()? {
209 0 => Ok(None),
210 1 => T::from_xdr_buffered(read_stream).map(|ok| Some(ok)),
211 code => Err(DecodeError::InvalidOptional {
212 at_position: read_stream.get_position(),
213 has_code: code,
214 }),
215 }
216 }
217}
218
219impl<T: XdrCodec> XdrCodec for Box<T> {
223 fn to_xdr_buffered(&self, write_stream: &mut WriteStream) {
224 self.as_ref().to_xdr_buffered(write_stream)
225 }
226
227 fn from_xdr_buffered<R: AsRef<[u8]>>(
228 read_stream: &mut ReadStream<R>,
229 ) -> Result<Self, DecodeError> {
230 Ok(Box::new(T::from_xdr_buffered(read_stream)?))
231 }
232}