parsing and rendering of packet IDs

This commit is contained in:
lurchi 2016-09-04 17:37:35 +02:00
parent 2486b4a82a
commit dfe9ba6a0b
6 changed files with 179 additions and 22 deletions

View File

@ -5,6 +5,8 @@ pub mod parser_types;
pub mod packet_types;
pub mod parser;
pub mod packet;
pub mod packet_id;
pub use parser::*;
pub use packet::*;
pub use packet_id::*;

View File

@ -1,5 +1,7 @@
use types::*;
use packet_types::*;
use packet_id::*;
use util;
use std::mem;
use std::ptr;
use std::os::raw::c_char;
@ -41,25 +43,11 @@ extern "C" {
content: *const c_char,
contentlen: usize,
flag: PsycPacketFlag);
fn psyc_packet_id(list: *mut RawPsycList,
elems: *mut PsycElem,
context: *const c_char,
contextlen: usize,
source: *const c_char,
sourcelen: usize,
target: *const c_char,
targetlen: usize,
counter: *const c_char,
counterlen: usize,
fragment: *const c_char,
fragmentlen: usize);
/// functions from render.h
fn psyc_render(packet: *const RawPsycPacket, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
fn psyc_render_modifier(modifier: *const RawPsycModifier, buffer: *mut c_char) -> usize;
fn psyc_render_elem(elem: *const PsycElem, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
fn psyc_render_list(list: *const RawPsycList, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
}
pub struct PsycList {
@ -95,17 +83,14 @@ impl PsycList {
pub fn new(list: &[&[u8]]) -> Self {
let mut psyc_list: RawPsycList;
let elements: Vec<PsycElem>;
let mut buffer: Vec<u8>;
let buffer: Vec<u8>;
unsafe {
psyc_list = mem::uninitialized();
let psyc_list_ptr = &mut psyc_list as *mut RawPsycList;
elements = list.iter().map(|e| make_psyc_elem(&e)).collect();
let elements_ptr = elements.as_ptr() as *const PsycElem;
psyc_list_init(psyc_list_ptr, elements_ptr, list.len());
buffer = Vec::with_capacity(psyc_list.length);
buffer.set_len(psyc_list.length);
let buffer_ptr = buffer.as_ptr() as *mut c_char;
let _ = psyc_render_list(psyc_list_ptr, buffer_ptr, psyc_list.length);
buffer = util::render_list(&psyc_list)
}
PsycList {
rendered_list: buffer
@ -241,6 +226,29 @@ impl<'a> PsycPacket<'a> {
}
}
/// get the packet id
pub fn packet_id(&self) -> PacketId<'a> {
let get_value = |modifier: Option<&PsycModifier<'a>>| {
match modifier {
None => None,
Some(m) => Some(m.value)
}
};
let context = self.routing_modifiers.iter().find(|&r| r.name == "_context");
let source = self.routing_modifiers.iter().find(|&r| r.name == "_source");
let target = self.routing_modifiers.iter().find(|&r| r.name == "_target");
let counter = self.routing_modifiers.iter().find(|&r| r.name == "_counter");
PacketId {
context: get_value(context),
source: get_value(source),
target: get_value(target),
counter: get_value(counter),
fragment: None
}
}
fn make_raw_modifier(modifier: &'a PsycModifier,
flag: PsycModifierFlag)
-> RawPsycModifier {

94
rust/src/packet_id.rs Normal file
View File

@ -0,0 +1,94 @@
use packet_types::{RawPsycList, PsycElem};
use parser::{PsycListParser, PsycListParserResult};
use util;
use std::mem;
use std::ptr;
use std::os::raw::c_char;
extern "C" {
fn psyc_packet_id(list: *mut RawPsycList,
elems: *mut PsycElem,
context: *const c_char,
contextlen: usize,
source: *const c_char,
sourcelen: usize,
target: *const c_char,
targetlen: usize,
counter: *const c_char,
counterlen: usize,
fragment: *const c_char,
fragmentlen: usize);
}
#[derive(PartialEq, Debug)]
pub struct PacketId<'a> {
pub context: Option<&'a [u8]>,
pub source: Option<&'a [u8]>,
pub target: Option<&'a [u8]>,
pub counter: Option<&'a [u8]>,
pub fragment: Option<&'a [u8]>
}
impl<'a> PacketId<'a> {
pub fn from_bytes(bytes: &'a [u8]) -> Option<Self> {
let mut parsed: Vec<Option<&'a [u8]>> = vec![None; 5];
let mut parser = PsycListParser::new();
let mut parsing_error = false;
for slice in &mut parsed {
match parser.parse(bytes) {
Ok(PsycListParserResult::ListElement {value: v}) => *slice = Some(v),
_ => parsing_error = true
}
}
if parsing_error {
None
} else {
let result = PacketId {
context: parsed[0],
source: parsed[1],
target: parsed[2],
counter: parsed[3],
fragment: parsed[4]
};
Some(result)
}
}
pub fn render(&self) -> Vec<u8> {
unsafe {
let get_ptr = |slice: Option<&'a [u8]>| {
match slice {
None => ptr::null::<c_char>(),
Some(s) => s.as_ptr() as *const c_char
}
};
let get_len = |slice: Option<&'a [u8]>| {
match slice {
None => 0,
Some(s) => s.len()
}
};
let mut list: RawPsycList = mem::uninitialized();
let mut elements: Vec<PsycElem> = Vec::with_capacity(5);
let list_ptr = &mut list as *mut RawPsycList;
let elements_ptr = elements.as_mut_ptr();
psyc_packet_id(list_ptr,
elements_ptr,
get_ptr(self.context),
get_len(self.context),
get_ptr(self.source),
get_len(self.source),
get_ptr(self.target),
get_len(self.target),
get_ptr(self.counter),
get_len(self.counter),
get_ptr(self.fragment),
get_len(self.fragment));
util::render_list(&list)
}
}
}

View File

@ -283,8 +283,6 @@ impl PsycListParser {
let element_ptr = &mut element as *mut PsycString;
loop {
let parse_result = psyc_parse_list(state_ptr, list_type_ptr, element_ptr);
println!("parse_result: {:?}", parse_result);
println!("cursor: {}", self.state.cursor);
match parse_result {
PsycParseListRC::PSYC_PARSE_LIST_END =>
return Ok(PsycListParserResult::Complete),

View File

@ -1,6 +1,20 @@
use packet_types::{RawPsycList, PsycRenderRC};
use std::slice;
use std::os::raw::c_char;
extern "C" {
fn psyc_render_list(list: *const RawPsycList, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
}
pub unsafe fn cstring_to_slice<'a>(cstring: *const c_char, length: usize) -> &'a[u8] {
slice::from_raw_parts(cstring as *const u8, length)
}
pub unsafe fn render_list(list: &RawPsycList) -> Vec<u8> {
let mut buffer: Vec<u8> = Vec::with_capacity(list.length);
buffer.set_len(list.length);
let buffer_ptr = buffer.as_ptr() as *mut c_char;
let list_ptr = list as *const RawPsycList;
let _ = psyc_render_list(list_ptr, buffer_ptr, list.length);
buffer
}

View File

@ -0,0 +1,41 @@
extern crate psyc;
use psyc::*;
use psyc::packet_types::*;
#[test]
fn test_packet_id() {
let routing_modifiers = vec![PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
"_source",
b"psyc://ve.symlynx.com/~alice"),
PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
"_target",
b"psyc://ve.symlynx.com/~bob"),
PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
"_counter",
b"42")];
let entity_modifiers = vec![];
let data = vec![];
let packet = PsycPacket::new(&routing_modifiers,
&entity_modifiers,
"",
&data,
PsycStateOp::PSYC_STATE_NOOP);
let expected_id = PacketId {
context: None,
source: Some(b"psyc://ve.symlynx.com/~alice"),
target: Some(b"psyc://ve.symlynx.com/~bob"),
counter: Some(b"42"),
fragment: None
};
assert_eq!(packet.packet_id(), expected_id);
let expected_rendered = b"|| psyc://ve.symlynx.com/~alice| psyc://ve.symlynx.com/~bob| 42|";
assert_eq!(packet.packet_id().render(), expected_rendered.to_vec());
}