use crate::protocol::{Encapsulation, Header, Identity, RequestData, ReplyData};
use crate::errors::*;
use std::convert::TryInto;
use std::collections::HashMap;
use std::hash::Hash;
pub struct IceSize {
pub size: i32
}
pub trait ToBytes {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>>;
}
pub trait FromBytes {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized;
}
impl ToBytes for IceSize {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
if self.size < 255 {
Ok(vec![self.size as u8])
} else {
let mut bytes = vec![255];
bytes.extend(self.size.to_bytes()?);
Ok(bytes)
}
}
}
impl FromBytes for IceSize {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
if bytes.len() < 1 {
Err(Box::new(ProtocolError {}))
}
else if bytes[0] == 255 {
if bytes.len() < 5 {
Err(Box::new(ProtocolError {}))
} else {
*read_bytes = 1;
Ok(IceSize {
size: i32::from_bytes(&bytes[1..5], read_bytes)?
})
}
} else {
Ok(IceSize {
size: u8::from_bytes(bytes, read_bytes)? as i32
})
}
}
}
impl ToBytes for str {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut bytes = IceSize{size: self.len() as i32}.to_bytes()?;
bytes.extend(self.as_bytes());
Ok(bytes)
}
}
impl ToBytes for String {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut bytes = IceSize{size: self.len() as i32}.to_bytes()?;
bytes.extend(self.as_bytes());
Ok(bytes)
}
}
impl FromBytes for String {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let mut read = 0;
let size = IceSize::from_bytes(bytes, &mut read)?.size;
let s = String::from_utf8(bytes[read as usize..read as usize + size as usize].to_vec())?;
*read_bytes = *read_bytes + read + size;
Ok(s)
}
}
impl<T: ToBytes, U: ToBytes> ToBytes for HashMap<T, U> {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut bytes = IceSize{size: self.len() as i32}.to_bytes()?;
for (key, value) in self {
bytes.extend(key.to_bytes()?);
bytes.extend(value.to_bytes()?);
}
Ok(bytes)
}
}
impl<T: FromBytes + Eq + Hash, U: FromBytes> FromBytes for HashMap<T, U> {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let mut read = 0;
let size = IceSize::from_bytes(bytes, &mut read)?.size;
let mut dict: HashMap<T, U> = HashMap::new();
for _i in 0..size {
let key = T::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let value = U::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
dict.insert(key, value);
}
*read_bytes = *read_bytes + read;
Ok(dict)
}
}
impl<T: ToBytes> ToBytes for Vec<T>
{
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut bytes = IceSize{size: self.len() as i32}.to_bytes()?;
for item in self {
bytes.extend(item.to_bytes()?);
}
Ok(bytes)
}
}
impl<T: FromBytes> FromBytes for Vec<T>
{
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let mut read = 0;
let size = IceSize::from_bytes(bytes, &mut read)?.size;
let mut seq: Vec<T> = vec![];
for _i in 0..size {
seq.push(T::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?);
}
*read_bytes = *read_bytes + read;
Ok(seq)
}
}
impl ToBytes for u8 {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(vec![*self])
}
}
impl FromBytes for u8 {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
*read_bytes = *read_bytes + 1;
Ok(bytes[0])
}
}
impl ToBytes for i16 {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(self.to_le_bytes().to_vec())
}
}
impl FromBytes for i16 {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let size = std::mem::size_of::<i16>();
if bytes.len() < size {
return Err(Box::new(ProtocolError {}));
}
match bytes[0..size].try_into() {
Ok(barray) => {
*read_bytes = *read_bytes + size as i32;
Ok(i16::from_le_bytes(barray))
},
_ => Err(Box::new(ProtocolError {}))
}
}
}
impl ToBytes for i32 {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(self.to_le_bytes().to_vec())
}
}
impl FromBytes for i32 {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let size = std::mem::size_of::<i32>();
if bytes.len() < size {
return Err(Box::new(ProtocolError {}));
}
match bytes[0..size].try_into() {
Ok(barray) => {
*read_bytes = *read_bytes + size as i32;
Ok(i32::from_le_bytes(barray))
},
_ => Err(Box::new(ProtocolError {}))
}
}
}
impl ToBytes for i64 {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(self.to_le_bytes().to_vec())
}
}
impl FromBytes for i64 {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let size = std::mem::size_of::<i64>();
if bytes.len() < size {
return Err(Box::new(ProtocolError {}));
}
match bytes[0..size].try_into() {
Ok(barray) => {
*read_bytes = *read_bytes + size as i32;
Ok(i64::from_le_bytes(barray))
},
_ => Err(Box::new(ProtocolError {}))
}
}
}
impl ToBytes for f32 {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(self.to_le_bytes().to_vec())
}
}
impl FromBytes for f32 {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let size = std::mem::size_of::<f32>();
if bytes.len() < size {
return Err(Box::new(ProtocolError {}));
}
match bytes[0..size].try_into() {
Ok(barray) => {
*read_bytes = *read_bytes + size as i32;
Ok(f32::from_le_bytes(barray))
},
_ => Err(Box::new(ProtocolError {}))
}
}
}
impl ToBytes for f64 {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(self.to_le_bytes().to_vec())
}
}
impl FromBytes for f64 {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
let size = std::mem::size_of::<f64>();
if bytes.len() < size {
return Err(Box::new(ProtocolError {}));
}
match bytes[0..size].try_into() {
Ok(barray) => {
*read_bytes = *read_bytes + size as i32;
Ok(f64::from_le_bytes(barray))
},
_ => Err(Box::new(ProtocolError {}))
}
}
}
impl ToBytes for bool {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(vec![if *self { 1 } else { 0 }])
}
}
impl FromBytes for bool {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>>
where Self: Sized {
if bytes.len() < 1 {
return Err(Box::new(ProtocolError {}));
}
*read_bytes = *read_bytes + 1;
Ok(bytes[0] != 0)
}
}
impl ToBytes for Identity {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>>
{
let mut buffer: Vec<u8> = Vec::new();
buffer.extend(self.name.to_bytes()?);
buffer.extend(self.category.to_bytes()?);
Ok(buffer)
}
}
impl FromBytes for Identity {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>> {
let mut read = 0;
let name = String::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let category = String::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
*read_bytes = *read_bytes + read;
Ok(Identity {
name: name,
category: category
})
}
}
impl ToBytes for Encapsulation {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>>
{
let mut buffer: Vec<u8> = Vec::new();
buffer.extend(&self.size.to_le_bytes());
buffer.push(self.major);
buffer.push(self.minor);
if self.data.len() > 0 {
buffer.extend(&self.data);
}
Ok(buffer)
}
}
impl FromBytes for Encapsulation {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>> {
let mut read: i32 = 0;
if bytes.len() < 6 {
return Err(Box::new(ProtocolError {}));
}
let size = i32::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let major = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let minor = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
*read_bytes = *read_bytes + read + (bytes.len() as i32 - read);
Ok(Encapsulation {
size: size,
major: major,
minor: minor,
data: bytes[read as usize..bytes.len()].to_vec()
})
}
}
impl ToBytes for RequestData {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>>
{
let mut buffer: Vec<u8> = Vec::new();
buffer.extend(self.request_id.to_bytes()?);
buffer.extend(self.id.to_bytes()?);
buffer.extend(self.facet.to_bytes()?);
buffer.extend(self.operation.to_bytes()?);
buffer.extend(self.mode.to_bytes()?);
buffer.extend(self.context.to_bytes()?);
buffer.extend(self.params.to_bytes()?);
Ok(buffer)
}
}
impl FromBytes for RequestData {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>> {
let mut read = 0;
let request_id = i32::from_bytes(bytes, &mut read)?;
let id = Identity::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let facet = Vec::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let operation = String::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let mode = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let context = HashMap::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let encapsulation = Encapsulation::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
*read_bytes = *read_bytes + read;
Ok(RequestData {
request_id: request_id,
id: id,
facet: facet,
operation: operation,
mode: mode,
context: context,
params: encapsulation
})
}
}
impl ToBytes for ReplyData {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>>
{
let mut buffer: Vec<u8> = Vec::new();
buffer.extend(self.request_id.to_bytes()?);
buffer.extend(self.status.to_bytes()?);
buffer.extend(self.body.to_bytes()?);
Ok(buffer)
}
}
impl FromBytes for ReplyData {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>> {
let mut read: i32 = 0;
if bytes.len() < 11 {
return Err(Box::new(ProtocolError {}));
}
let request_id = i32::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let status = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
match status {
0 | 1 => {
let encapsulation = Encapsulation::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
*read_bytes = *read_bytes + read;
Ok(ReplyData {
request_id: request_id,
status: status,
body: encapsulation
})
}
7 => {
Err(Box::new(
RemoteException {
cause: String::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?
}
))
}
_ => Err(Box::new(ProtocolError {}))
}
}
}
impl ToBytes for Header {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>>
{
let mut buffer: Vec<u8> = Vec::new();
buffer.extend(self.magic.as_bytes());
buffer.extend(self.protocol_major.to_bytes()?);
buffer.extend(self.protocol_minor.to_bytes()?);
buffer.extend(self.encoding_major.to_bytes()?);
buffer.extend(self.encoding_minor.to_bytes()?);
buffer.extend(self.message_type.to_bytes()?);
buffer.extend(self.compression_status.to_bytes()?);
buffer.extend(&self.message_size.to_le_bytes());
Ok(buffer)
}
}
impl FromBytes for Header {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>> {
if bytes.len() < 14 {
return Err(Box::new(ProtocolError {}));
}
let magic = String::from_utf8(bytes[0..4].to_vec())?;
if magic != "IceP" {
return Err(Box::new(ProtocolError {}));
}
let mut read: i32 = 4;
let protocol_major = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let protocol_minor = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let encoding_major = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let encoding_minor = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let message_type = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let comression_status = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let message_size = i32::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
*read_bytes = *read_bytes + read;
Ok(Header {
magic: magic,
protocol_major: protocol_major,
protocol_minor: protocol_minor,
encoding_major: encoding_major,
encoding_minor: encoding_minor,
message_type: message_type,
compression_status: comression_status,
message_size: message_size
})
}
}
impl<T: ToBytes> ToBytes for Option<T> {
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut bytes = Vec::new();
match self {
Some(value) => {
bytes.extend((11 as u8).to_bytes()?);
bytes.extend(value.to_bytes()?);
}
None => {}
}
Ok(bytes)
}
}
impl<T: FromBytes> FromBytes for Option<T> {
fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error>> {
if bytes.len() > 0 {
let mut read: i32 = 0;
let _flag = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
let result = Some(T::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?);
*read_bytes = *read_bytes + read;
Ok(result)
} else {
Ok(None)
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_size_encoding() {
let mut read_bytes = 0;
let encoded = IceSize{size: 10}.to_bytes().expect("Could not encode size");
let decoded = IceSize::from_bytes(&encoded, &mut read_bytes).expect("Could not decode size").size;
assert_eq!(10, decoded);
assert_eq!(1, read_bytes);
read_bytes = 0;
let encoded = IceSize{size: 500}.to_bytes().expect("Could not encode size");
let decoded = IceSize::from_bytes(&encoded, &mut read_bytes).expect("Could not decode size").size;
assert_eq!(500, decoded);
assert_eq!(5, read_bytes);
}
#[test]
fn test_string_encoding() {
let mut read_bytes = 0;
let encoded = "Hello".to_bytes().expect("Cannot necode test string");
let decoded = String::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test string");
assert_eq!("Hello", decoded);
assert_eq!(6, read_bytes);
}
#[test]
fn test_dict_encoding() {
let mut read_bytes = 0;
let mut dict = HashMap::new();
dict.insert(String::from("Hello"), String::from("World"));
let encoded = dict.to_bytes().expect("Cannot encode test dict");
let decoded: HashMap<String, String> = HashMap::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test dict");
assert!(decoded.contains_key("Hello"));
assert_eq!("World", decoded.get("Hello").unwrap_or(&String::from("")));
}
#[test]
fn test_string_seq_encoding() {
let mut read_bytes = 0;
let seq = vec![String::from("Hello"), String::from("World")];
let encoded = seq.to_bytes().expect("Cannot encode test dict");
let decoded: Vec<String> = Vec::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test dict");
assert_eq!(2, decoded.len());
assert_eq!(seq, decoded);
}
#[test]
fn test_short_encoding() {
let mut read_bytes = 0;
let value: i16 = 3;
let encoded = value.to_bytes().expect("Cannot encode test short");
let decoded = i16::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test short");
assert_eq!(value, decoded);
}
#[test]
fn test_int_encoding() {
let mut read_bytes = 0;
let value: i32 = 3;
let encoded = value.to_bytes().expect("Cannot encode test int");
let decoded = i32::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test int");
assert_eq!(value, decoded);
}
#[test]
fn test_long_encoding() {
let mut read_bytes = 0;
let value: i64 = 3;
let encoded = value.to_bytes().expect("Cannot encode test long");
let decoded = i64::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test long");
assert_eq!(value, decoded);
}
#[test]
fn test_float_encoding() {
let mut read_bytes = 0;
let value: f32 = 3.14;
let encoded = value.to_bytes().expect("Cannot encode test float");
let decoded = f32::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test float");
assert_eq!(value, decoded);
}
#[test]
fn test_double_encoding() {
let mut read_bytes = 0;
let value: f64 = 3.14;
let encoded = value.to_bytes().expect("Cannot encode test double");
let decoded = f64::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode double long");
assert_eq!(value, decoded);
}
#[test]
fn test_bool_encoding() {
let mut read_bytes = 0;
let value = true;
let encoded = value.to_bytes().expect("Cannot encode test bool");
let decoded = bool::from_bytes(&encoded, &mut read_bytes).expect("Cannot decode test bool");
assert_eq!(value, decoded);
}
#[test]
fn test_identity_ecoding() {
let mut read_bytes = 0;
let id = Identity {
name: String::from("Hello"),
category: String::from(""),
};
let bytes = id.to_bytes().expect("Cannot encode test identity");
let decoded = Identity::from_bytes(&bytes, &mut read_bytes).expect("Cannot decode test identity");
assert_eq!(7, read_bytes);
assert_eq!(id.name, decoded.name);
assert_eq!(id.category, decoded.category);
}
#[test]
fn test_header_ecoding() {
let mut read_bytes = 0;
let header = Header::new(0, 14);
let bytes = header.to_bytes().expect("Cannot encode test header");
let decoded = Header::from_bytes(&bytes, &mut read_bytes).expect("Cannot decode test header");
assert_eq!(14, read_bytes);
assert_eq!(header.magic, decoded.magic);
assert_eq!(header.message_size, decoded.message_size);
assert_eq!(header.message_type, decoded.message_type);
assert_eq!(header.magic, decoded.magic);
}
#[test]
fn test_request_ecoding() {
let mut read_bytes = 0;
let request = RequestData {
request_id: 1,
id: Identity {
name: String::from("Test"),
category: String::from(""),
},
facet: vec![],
operation: String::from("Op"),
mode: 0,
context: HashMap::new(),
params: Encapsulation::empty()
};
let bytes = request.to_bytes().expect("Cannot encode test request");
let decoded = RequestData::from_bytes(&bytes, &mut read_bytes).expect("Cannot decode test request");
assert_eq!(22, read_bytes);
assert_eq!(request.request_id, decoded.request_id);
assert_eq!(request.id.name, decoded.id.name);
assert_eq!(request.facet, decoded.facet);
assert_eq!(request.operation, decoded.operation);
assert_eq!(request.mode, decoded.mode);
assert_eq!(request.context, decoded.context);
}
#[test]
fn test_reply_encoding() {
let mut read_bytes = 0;
let reply = ReplyData {
request_id: 1,
status: 0,
body: Encapsulation::empty()
};
let bytes = reply.to_bytes().expect("Cannot encode test reply");
let decoded = ReplyData::from_bytes(&bytes, &mut read_bytes).expect("Cannot decode test reply");
assert_eq!(11, read_bytes);
assert_eq!(reply.request_id, decoded.request_id);
assert_eq!(reply.status, decoded.status);
}
}