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 parser;
|
||||
pub mod packet;
|
||||
pub mod packet_id;
|
||||
|
||||
pub use parser::*;
|
||||
pub use packet::*;
|
||||
pub use packet_id::*;
|
||||
|
|
|
@ -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
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;
|
||||
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),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
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