mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
parsing and rendering of packet IDs
This commit is contained in:
parent
2486b4a82a
commit
dfe9ba6a0b
6 changed files with 179 additions and 22 deletions
|
@ -5,6 +5,8 @@ pub mod parser_types;
|
||||||
pub mod packet_types;
|
pub mod packet_types;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
|
pub mod packet_id;
|
||||||
|
|
||||||
pub use parser::*;
|
pub use parser::*;
|
||||||
pub use packet::*;
|
pub use packet::*;
|
||||||
|
pub use packet_id::*;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use types::*;
|
use types::*;
|
||||||
use packet_types::*;
|
use packet_types::*;
|
||||||
|
use packet_id::*;
|
||||||
|
use util;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
@ -42,24 +44,10 @@ extern "C" {
|
||||||
contentlen: usize,
|
contentlen: usize,
|
||||||
flag: PsycPacketFlag);
|
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
|
/// functions from render.h
|
||||||
fn psyc_render(packet: *const RawPsycPacket, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
|
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_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_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 {
|
pub struct PsycList {
|
||||||
|
@ -95,17 +83,14 @@ impl PsycList {
|
||||||
pub fn new(list: &[&[u8]]) -> Self {
|
pub fn new(list: &[&[u8]]) -> Self {
|
||||||
let mut psyc_list: RawPsycList;
|
let mut psyc_list: RawPsycList;
|
||||||
let elements: Vec<PsycElem>;
|
let elements: Vec<PsycElem>;
|
||||||
let mut buffer: Vec<u8>;
|
let buffer: Vec<u8>;
|
||||||
unsafe {
|
unsafe {
|
||||||
psyc_list = mem::uninitialized();
|
psyc_list = mem::uninitialized();
|
||||||
let psyc_list_ptr = &mut psyc_list as *mut RawPsycList;
|
let psyc_list_ptr = &mut psyc_list as *mut RawPsycList;
|
||||||
elements = list.iter().map(|e| make_psyc_elem(&e)).collect();
|
elements = list.iter().map(|e| make_psyc_elem(&e)).collect();
|
||||||
let elements_ptr = elements.as_ptr() as *const PsycElem;
|
let elements_ptr = elements.as_ptr() as *const PsycElem;
|
||||||
psyc_list_init(psyc_list_ptr, elements_ptr, list.len());
|
psyc_list_init(psyc_list_ptr, elements_ptr, list.len());
|
||||||
buffer = Vec::with_capacity(psyc_list.length);
|
buffer = util::render_list(&psyc_list)
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
PsycList {
|
PsycList {
|
||||||
rendered_list: buffer
|
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,
|
fn make_raw_modifier(modifier: &'a PsycModifier,
|
||||||
flag: PsycModifierFlag)
|
flag: PsycModifierFlag)
|
||||||
-> RawPsycModifier {
|
-> RawPsycModifier {
|
||||||
|
|
94
rust/src/packet_id.rs
Normal file
94
rust/src/packet_id.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -283,8 +283,6 @@ impl PsycListParser {
|
||||||
let element_ptr = &mut element as *mut PsycString;
|
let element_ptr = &mut element as *mut PsycString;
|
||||||
loop {
|
loop {
|
||||||
let parse_result = psyc_parse_list(state_ptr, list_type_ptr, element_ptr);
|
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 {
|
match parse_result {
|
||||||
PsycParseListRC::PSYC_PARSE_LIST_END =>
|
PsycParseListRC::PSYC_PARSE_LIST_END =>
|
||||||
return Ok(PsycListParserResult::Complete),
|
return Ok(PsycListParserResult::Complete),
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
|
use packet_types::{RawPsycList, PsycRenderRC};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::os::raw::c_char;
|
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] {
|
pub unsafe fn cstring_to_slice<'a>(cstring: *const c_char, length: usize) -> &'a[u8] {
|
||||||
slice::from_raw_parts(cstring as *const u8, length)
|
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
|
||||||
|
}
|
||||||
|
|
41
rust/tests/test_packet_id.rs
Normal file
41
rust/tests/test_packet_id.rs
Normal 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());
|
||||||
|
}
|
Loading…
Reference in a new issue