ignite_rs/protocol/
mod.rs

1use std::io;
2use std::io::{ErrorKind, Read, Write};
3
4use crate::error::{IgniteError, IgniteResult};
5
6use crate::{Enum, ReadableType};
7use std::convert::TryFrom;
8
9pub(crate) mod cache_config;
10pub(crate) mod data_types;
11
12pub const FLAG_USER_TYPE: u16 = 0x0001;
13pub const FLAG_HAS_SCHEMA: u16 = 0x0002;
14pub const FLAG_COMPACT_FOOTER: u16 = 0x0020;
15pub const FLAG_OFFSET_ONE_BYTE: u16 = 0x0008;
16pub const FLAG_OFFSET_TWO_BYTES: u16 = 0x0010;
17
18pub const COMPLEX_OBJ_HEADER_LEN: i32 = 24;
19
20/// All Data types described in Binary Protocol
21/// https://apacheignite.readme.io/docs/binary-client-protocol-data-format
22#[derive(PartialOrd, PartialEq)]
23pub enum TypeCode {
24    // primitives
25    Byte = 1,
26    Short = 2,
27    Int = 3,
28    Long = 4,
29    Float = 5,
30    Double = 6,
31    Char = 7,
32    Bool = 8,
33    // standard objects
34    String = 9,
35    Enum = 28,
36    // arrays of primitives
37    ArrByte = 12,
38    ArrShort = 13,
39    ArrInt = 14,
40    ArrLong = 15,
41    ArrFloat = 16,
42    ArrDouble = 17,
43    ArrChar = 18,
44    ArrBool = 19,
45    // object collections
46    ArrObj = 23,
47    Collection = 24,
48    ComplexObj = 103,
49    Null = 101,
50    WrappedData = 27,
51}
52
53impl TryFrom<u8> for TypeCode {
54    type Error = IgniteError;
55
56    fn try_from(value: u8) -> Result<Self, Self::Error> {
57        match value {
58            1 => Ok(TypeCode::Byte),
59            2 => Ok(TypeCode::Short),
60            3 => Ok(TypeCode::Int),
61            4 => Ok(TypeCode::Long),
62            5 => Ok(TypeCode::Float),
63            6 => Ok(TypeCode::Double),
64            7 => Ok(TypeCode::Char),
65            8 => Ok(TypeCode::Bool),
66            9 => Ok(TypeCode::String),
67            28 => Ok(TypeCode::Enum),
68            12 => Ok(TypeCode::ArrByte),
69            13 => Ok(TypeCode::ArrShort),
70            14 => Ok(TypeCode::ArrInt),
71            15 => Ok(TypeCode::ArrLong),
72            16 => Ok(TypeCode::ArrFloat),
73            17 => Ok(TypeCode::ArrDouble),
74            18 => Ok(TypeCode::ArrChar),
75            19 => Ok(TypeCode::ArrBool),
76            23 => Ok(TypeCode::ArrObj),
77            24 => Ok(TypeCode::Collection),
78            27 => Ok(TypeCode::WrappedData),
79            103 => Ok(TypeCode::ComplexObj),
80            101 => Ok(TypeCode::Null),
81            _ => Err(IgniteError::from(
82                format!("Cannot read TypeCode {}", value).as_str(),
83            )),
84        }
85    }
86}
87
88/// Flag of general Response header
89pub(crate) enum Flag {
90    Success,
91    Failure { err_msg: String },
92}
93
94/// Reads data objects that are wrapped in the WrappedData(type code = 27)
95pub fn read_wrapped_data<T: ReadableType>(reader: &mut impl Read) -> IgniteResult<Option<T>> {
96    let type_code = TypeCode::try_from(read_u8(reader)?)?;
97    match type_code {
98        TypeCode::WrappedData => {
99            read_i32(reader)?; // skip len
100            let value = T::read(reader);
101            read_i32(reader)?; // skip offset
102            value
103        }
104        _ => T::read_unwrapped(type_code, reader),
105    }
106}
107
108/// This function is basically a String's PackType implementation but for &str.
109/// It should be used only for strings in request bodies (like cache creation, configuration etc.)
110/// not for KV (a.k.a DataObject)
111pub(crate) fn write_string_type_code(writer: &mut dyn Write, value: &str) -> io::Result<()> {
112    let value_bytes = value.as_bytes();
113    write_u8(writer, TypeCode::String as u8)?;
114    write_i32(writer, value_bytes.len() as i32)?;
115    writer.write_all(value_bytes)?;
116    Ok(())
117}
118
119//// Read functions. No TypeCode, no NULL checking
120
121pub fn write_string(writer: &mut dyn Write, value: &str) -> io::Result<()> {
122    let value_bytes = value.as_bytes();
123    write_i32(writer, value_bytes.len() as i32)?;
124    writer.write_all(value_bytes)?;
125    Ok(())
126}
127
128pub fn read_string(reader: &mut impl Read) -> io::Result<String> {
129    let str_len = read_i32(reader)?;
130
131    let mut new_alloc = vec![0u8; str_len as usize];
132    match reader.read_exact(new_alloc.as_mut_slice()) {
133        Ok(_) => match String::from_utf8(new_alloc) {
134            Ok(s) => Ok(s),
135            Err(err) => Err(io::Error::new(ErrorKind::InvalidData, err)),
136        },
137        Err(err) => Err(err),
138    }
139}
140
141pub fn read_bool(reader: &mut impl Read) -> io::Result<bool> {
142    let mut new_alloc = [0u8; 1];
143    match reader.read_exact(&mut new_alloc[..]) {
144        Ok(_) => Ok(0u8.ne(&new_alloc[0])),
145        Err(err) => Err(err),
146    }
147}
148
149pub fn write_bool(writer: &mut dyn Write, v: bool) -> io::Result<()> {
150    if v {
151        write_u8(writer, 1u8)
152    } else {
153        write_u8(writer, 0u8)
154    }
155}
156
157pub fn read_u8(reader: &mut impl Read) -> io::Result<u8> {
158    let mut new_alloc = [0u8; 1];
159    match reader.read_exact(&mut new_alloc[..]) {
160        Ok(_) => Ok(u8::from_le_bytes(new_alloc)),
161        Err(err) => Err(err),
162    }
163}
164
165pub fn write_u8(writer: &mut dyn Write, v: u8) -> io::Result<()> {
166    writer.write_all(&u8::to_le_bytes(v))?;
167    Ok(())
168}
169
170pub fn read_i8(reader: &mut impl Read) -> io::Result<i8> {
171    let mut new_alloc = [0u8; 1];
172    match reader.read_exact(&mut new_alloc[..]) {
173        Ok(_) => Ok(i8::from_le_bytes(new_alloc)),
174        Err(err) => Err(err),
175    }
176}
177
178pub fn write_i8(writer: &mut dyn Write, v: i8) -> io::Result<()> {
179    writer.write_all(&i8::to_le_bytes(v))?;
180    Ok(())
181}
182
183pub fn read_u16(reader: &mut impl Read) -> io::Result<u16> {
184    let mut new_alloc = [0u8; 2];
185    match reader.read_exact(&mut new_alloc[..]) {
186        Ok(_) => Ok(u16::from_le_bytes(new_alloc)),
187        Err(err) => Err(err),
188    }
189}
190
191pub fn write_u16(writer: &mut dyn Write, v: u16) -> io::Result<()> {
192    writer.write_all(&u16::to_le_bytes(v))?;
193    Ok(())
194}
195
196pub fn read_i16(reader: &mut impl Read) -> io::Result<i16> {
197    let mut new_alloc = [0u8; 2];
198    match reader.read_exact(&mut new_alloc[..]) {
199        Ok(_) => Ok(i16::from_le_bytes(new_alloc)),
200        Err(err) => Err(err),
201    }
202}
203
204pub fn write_i16(writer: &mut dyn Write, v: i16) -> io::Result<()> {
205    writer.write_all(&i16::to_le_bytes(v))?;
206    Ok(())
207}
208
209pub fn read_i32(reader: &mut impl Read) -> io::Result<i32> {
210    let mut new_alloc = [0u8; 4];
211    match reader.read_exact(&mut new_alloc[..]) {
212        Ok(_) => Ok(i32::from_le_bytes(new_alloc)),
213        Err(err) => Err(err),
214    }
215}
216
217pub fn write_i32(writer: &mut dyn Write, v: i32) -> io::Result<()> {
218    writer.write_all(&i32::to_le_bytes(v))?;
219    Ok(())
220}
221
222pub fn read_u32(reader: &mut impl Read) -> io::Result<u32> {
223    let mut new_alloc = [0u8; 4];
224    match reader.read_exact(&mut new_alloc[..]) {
225        Ok(_) => Ok(u32::from_le_bytes(new_alloc)),
226        Err(err) => Err(err),
227    }
228}
229
230pub fn write_u32(writer: &mut dyn Write, v: u32) -> io::Result<()> {
231    writer.write_all(&u32::to_le_bytes(v))?;
232    Ok(())
233}
234
235pub fn read_i64(reader: &mut impl Read) -> io::Result<i64> {
236    let mut new_alloc = [0u8; 8];
237    match reader.read_exact(&mut new_alloc[..]) {
238        Ok(_) => Ok(i64::from_le_bytes(new_alloc)),
239        Err(err) => Err(err),
240    }
241}
242
243pub fn write_u64(writer: &mut dyn Write, v: u64) -> io::Result<()> {
244    writer.write_all(&u64::to_le_bytes(v))?;
245    Ok(())
246}
247
248pub fn read_u64(reader: &mut impl Read) -> io::Result<u64> {
249    let mut new_alloc = [0u8; 8];
250    match reader.read_exact(&mut new_alloc[..]) {
251        Ok(_) => Ok(u64::from_le_bytes(new_alloc)),
252        Err(err) => Err(err),
253    }
254}
255
256pub fn write_i64(writer: &mut dyn Write, v: i64) -> io::Result<()> {
257    writer.write_all(&i64::to_le_bytes(v))?;
258    Ok(())
259}
260
261pub fn read_f32(reader: &mut impl Read) -> io::Result<f32> {
262    let mut new_alloc = [0u8; 4];
263    match reader.read_exact(&mut new_alloc[..]) {
264        Ok(_) => Ok(f32::from_le_bytes(new_alloc)),
265        Err(err) => Err(err),
266    }
267}
268
269pub fn write_f32(writer: &mut dyn Write, v: f32) -> io::Result<()> {
270    writer.write_all(&f32::to_le_bytes(v))?;
271    Ok(())
272}
273
274pub fn read_f64(reader: &mut impl Read) -> io::Result<f64> {
275    let mut new_alloc = [0u8; 8];
276    match reader.read_exact(&mut new_alloc[..]) {
277        Ok(_) => Ok(f64::from_le_bytes(new_alloc)),
278        Err(err) => Err(err),
279    }
280}
281
282pub fn write_f64(writer: &mut dyn Write, v: f64) -> io::Result<()> {
283    writer.write_all(&f64::to_le_bytes(v))?;
284    Ok(())
285}
286
287pub fn read_primitive_arr<T, R, F>(reader: &mut R, read_fn: F) -> io::Result<Vec<T>>
288where
289    R: Read,
290    F: Fn(&mut R) -> io::Result<T>,
291{
292    let len = read_i32(reader)?;
293    let mut payload: Vec<T> = Vec::with_capacity(len as usize);
294    for _ in 0..len {
295        payload.push(read_fn(reader)?);
296    }
297    Ok(payload)
298}
299
300pub fn read_enum(reader: &mut impl Read) -> io::Result<Enum> {
301    let type_id = read_i32(reader)?;
302    let ordinal = read_i32(reader)?;
303    Ok(Enum { type_id, ordinal })
304}
305
306pub fn write_enum(writer: &mut dyn Write, val: Enum) -> io::Result<()> {
307    write_i32(writer, val.type_id)?;
308    write_i32(writer, val.ordinal)?;
309    Ok(())
310}