mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
Merge remote-tracking branch
This commit is contained in:
commit
d6c4f9c4e4
16 changed files with 667 additions and 344 deletions
|
@ -688,7 +688,7 @@ psyc_parse_remaining_buffer (PsycParseState *state)
|
|||
* in case of the body it will point to the data.
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseRC
|
||||
psyc_parse (PsycParseState *state, char *oper,
|
||||
|
@ -706,25 +706,25 @@ psyc_parse (PsycParseState *state, char *oper,
|
|||
* @param elem It will point to the next element in the list.
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseListRC
|
||||
psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem);
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseDictRC
|
||||
psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem);
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseIndexRC
|
||||
psyc_parse_index (PsycParseIndexState *state, PsycString *idx);
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseUpdateRC
|
||||
psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value);
|
||||
|
|
|
@ -172,7 +172,7 @@ psyc_text (PsycTextState *state, PsycTextCB get_value, void *get_value_cls);
|
|||
|
||||
extern const PsycTemplates psyc_templates;
|
||||
|
||||
static inline const char *
|
||||
inline const char *
|
||||
psyc_template (PsycMethod mc, size_t *len) {
|
||||
PsycString t = psyc_templates.a[mc];
|
||||
if (len)
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#![allow(dead_code)]
|
||||
mod types;
|
||||
mod util;
|
||||
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;
|
||||
|
@ -18,14 +20,11 @@ extern "C" {
|
|||
|
||||
fn psyc_elem_length_check(value: *const PsycString, end: c_char) -> PsycElemFlag;
|
||||
fn psyc_elem_length(elem: *const PsycElem) -> usize;
|
||||
fn psyc_dict_key_length(elem: *const PsycDictKey) -> usize;
|
||||
fn psyc_list_length_set(list: *mut RawPsycList) -> usize;
|
||||
fn psyc_dict_length_set(dict: *mut RawPsycDict) -> usize;
|
||||
fn psyc_modifier_length(m: *const RawPsycModifier) -> usize;
|
||||
fn psyc_packet_length_check(p: *const RawPsycPacket) -> PsycPacketFlag;
|
||||
fn psyc_packet_length_set(p: *mut RawPsycPacket) -> usize;
|
||||
fn psyc_list_init(list: *mut RawPsycList, elems: *const PsycElem, num_elems: usize);
|
||||
fn psyc_dict_init(dict: *mut RawPsycDict, elems: *const PsycDictElem, num_elems: usize);
|
||||
fn psyc_packet_init(packet: *mut RawPsycPacket,
|
||||
routing: *const RawPsycModifier,
|
||||
routinglen: usize,
|
||||
|
@ -45,36 +44,16 @@ extern "C" {
|
|||
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_dict_key(elem: *const PsycDictKey, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
|
||||
fn psyc_render_list(list: *const RawPsycList, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
|
||||
fn psyc_render_dict(dict: *const RawPsycDict, buffer: *mut c_char, buflen: usize) -> PsycRenderRC;
|
||||
}
|
||||
|
||||
pub struct PsycList {
|
||||
rendered_list: Vec<u8>
|
||||
}
|
||||
|
||||
pub struct PsycDict {
|
||||
rendered_dict: Vec<u8>
|
||||
}
|
||||
|
||||
pub struct PsycModifier<'a> {
|
||||
name: &'a str,
|
||||
value: &'a [u8],
|
||||
|
@ -104,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
|
||||
|
@ -128,39 +104,6 @@ impl PsycList {
|
|||
}
|
||||
}
|
||||
|
||||
impl PsycDict {
|
||||
/// Construct a PsycDict from a list of key value pairs
|
||||
pub fn new(dict: &[(&[u8], &[u8])]) -> Self {
|
||||
let mut psyc_dict: RawPsycDict;
|
||||
let elements: Vec<PsycDictElem>;
|
||||
let mut buffer: Vec<u8>;
|
||||
unsafe {
|
||||
psyc_dict = mem::uninitialized();
|
||||
let psyc_dict_ptr = &mut psyc_dict as *mut RawPsycDict;
|
||||
elements = dict.iter().map(|e| make_psyc_dict_elem(e)).collect();
|
||||
let elements_ptr = elements.as_ptr() as *const PsycDictElem;
|
||||
psyc_dict_init(psyc_dict_ptr, elements_ptr, dict.len());
|
||||
buffer = Vec::with_capacity(psyc_dict.length);
|
||||
buffer.set_len(psyc_dict.length);
|
||||
let buffer_ptr = buffer.as_ptr() as *mut c_char;
|
||||
let _ = psyc_render_dict(psyc_dict_ptr, buffer_ptr, psyc_dict.length);
|
||||
}
|
||||
PsycDict{
|
||||
rendered_dict: buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a PsycDict from a list of key / value string pairs (comfort
|
||||
/// function)
|
||||
pub fn from_strings(dict: &[(&str, &str)]) -> Self {
|
||||
let kv_list_slices: Vec<(&[u8], &[u8])> = dict.iter().map(|e| {
|
||||
let &(k, v) = e;
|
||||
(k.as_bytes(), v.as_bytes())
|
||||
}).collect();
|
||||
Self::new(&kv_list_slices)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PsycModifier<'a> {
|
||||
/// construct a PsycModifier
|
||||
pub fn new(operator: PsycOperator, name: &'a str, value: &'a [u8]) -> Self {
|
||||
|
@ -190,20 +133,6 @@ impl<'a> PsycModifier<'a> {
|
|||
operator: operator
|
||||
}
|
||||
}
|
||||
|
||||
/// construct a PsycModifier with a dictionary value (comfort function)
|
||||
pub fn with_dict_value(operator: PsycOperator,
|
||||
name: &'a str,
|
||||
value: &'a PsycDict)
|
||||
-> Self {
|
||||
PsycModifier {
|
||||
name: name,
|
||||
value: &value.rendered_dict,
|
||||
operator: operator
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl<'a> PsycPacket<'a> {
|
||||
|
@ -297,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 {
|
||||
|
@ -327,21 +279,3 @@ unsafe fn make_psyc_elem(list_element: &[u8]) -> PsycElem {
|
|||
flag: PsycElemFlag::PSYC_ELEM_CHECK_LENGTH
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn make_psyc_dict_elem(dict_element: &(&[u8], &[u8])) -> PsycDictElem {
|
||||
let &(key, value) = dict_element;
|
||||
let key_ptr = key.as_ptr() as *const c_char;
|
||||
let psyc_dict_elem_value = make_psyc_elem(value);
|
||||
let psyc_dict_elem_key = PsycDictKey {
|
||||
value: PsycString {
|
||||
length: key.len(),
|
||||
data: key_ptr
|
||||
},
|
||||
length: 0,
|
||||
flag: PsycElemFlag::PSYC_ELEM_CHECK_LENGTH
|
||||
};
|
||||
PsycDictElem {
|
||||
value: psyc_dict_elem_value,
|
||||
key: psyc_dict_elem_key
|
||||
}
|
||||
}
|
||||
|
|
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::with_capacity(5);
|
||||
let mut parser = PsycListParser::new();
|
||||
for _i in 0..5 {
|
||||
match parser.parse(bytes) {
|
||||
Ok(PsycListParserResult::ListElement {value: b""}) => parsed.push(None),
|
||||
Ok(PsycListParserResult::ListElement {value: v}) => parsed.push(Some(v)),
|
||||
_ => break
|
||||
}
|
||||
}
|
||||
if parsed.len() < 5 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,27 +69,6 @@ pub struct PsycElem {
|
|||
pub flag: PsycElemFlag
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycDictKey {
|
||||
pub value: PsycString,
|
||||
pub length: usize,
|
||||
pub flag: PsycElemFlag
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycDictElem {
|
||||
pub value: PsycElem,
|
||||
pub key: PsycDictKey
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RawPsycDict {
|
||||
dict_type: PsycString,
|
||||
elems: *const PsycDictElem,
|
||||
num_elems: usize,
|
||||
pub length: usize
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RawPsycList {
|
||||
list_type: PsycString,
|
||||
|
@ -137,6 +116,3 @@ pub enum PsycRenderRC {
|
|||
/// Packet is rendered successfully in the buffer.
|
||||
PSYC_RENDER_SUCCESS = 0,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,28 +1,16 @@
|
|||
use types::*;
|
||||
use parser_types::*;
|
||||
use util;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
extern "C" {
|
||||
fn psyc_parse_state_init(state: *mut PsycParseState, flags: u8);
|
||||
fn psyc_parse_buffer_set(state: *mut PsycParseState, buffer: *const c_char, length: usize);
|
||||
fn psyc_parse_list_state_init(state: *mut PsycParseState);
|
||||
fn psyc_parse_list_buffer_set(state: *mut PsycParseState, buffer: *const c_char, length: usize);
|
||||
fn psyc_parse_dict_state_init(state: *mut PsycParseState);
|
||||
fn psyc_parse_dict_buffer_set(state: *mut PsycParseState, buffer: *const c_char, length: usize);
|
||||
fn psyc_parse_index_state_init(state: *mut PsycParseState);
|
||||
fn psyc_parse_index_buffer_set(state: *mut PsycParseState, buffer: *const c_char, length: usize);
|
||||
fn psyc_parse_update_state_init(state: *mut PsycParseState);
|
||||
fn psyc_parse_update_buffer_set(state: *mut PsycParseState, buffer: *const c_char, length: usize);
|
||||
fn psyc_parse_content_length(state: *mut PsycParseState) -> usize;
|
||||
fn psyc_parse_content_length_found(state: *mut PsycParseState) -> bool;
|
||||
fn psyc_parse_value_length(state: *mut PsycParseState) -> usize;
|
||||
fn psyc_parse_value_length_found(state: *mut PsycParseState) -> bool;
|
||||
fn psyc_parse_cursor(state: *mut PsycParseState) -> usize;
|
||||
fn psyc_parse_buffer_length(state: *mut PsycParseState) -> usize;
|
||||
fn psyc_parse_remaining_length(state: *mut PsycParseState) -> usize;
|
||||
fn psyc_parse_remaining_buffer(state: *mut PsycParseState) -> *const c_char;
|
||||
fn psyc_parse_list_state_init(state: *mut PsycParseListState);
|
||||
fn psyc_parse_list_buffer_set(state: *mut PsycParseListState, buffer: *const c_char, length: usize);
|
||||
fn psyc_parse_cursor(state: *const PsycParseState) -> usize;
|
||||
fn psyc_parse_remaining_length(state: *const PsycParseState) -> usize;
|
||||
fn psyc_parse(state: *mut PsycParseState,
|
||||
oper: *mut c_char,
|
||||
name: *mut PsycString,
|
||||
|
@ -33,31 +21,6 @@ extern "C" {
|
|||
list_type: *mut PsycString,
|
||||
elem: *mut PsycString)
|
||||
-> PsycParseListRC;
|
||||
|
||||
fn psyc_parse_dict(state: *mut PsycParseDictState,
|
||||
dict_type: *mut PsycString,
|
||||
elem: *mut PsycString)
|
||||
-> PsycParseDictRC;
|
||||
|
||||
fn psyc_parse_index(state: *mut PsycParseIndexState,
|
||||
idx: *mut PsycString)
|
||||
-> PsycParseIndexRC;
|
||||
|
||||
fn psyc_parse_update(state: *mut PsycParseUpdateState,
|
||||
oper: *mut c_char,
|
||||
value: *mut PsycString)
|
||||
-> PsycParseUpdateRC;
|
||||
|
||||
fn psyc_parse_uint(value: *const c_char, len: usize, n: *mut u64) -> usize;
|
||||
fn psyc_parse_list_index(value: *const c_char, len: usize, n: *mut i64) -> usize;
|
||||
fn psyc_is_oper(g: c_char) -> bool;
|
||||
fn psyc_is_numeric(c: c_char) -> bool;
|
||||
fn psyc_is_alpha(c: c_char) -> bool;
|
||||
fn psyc_is_alpha_numeric(c: c_char) -> bool;
|
||||
fn psyc_is_kw_char(c: c_char) -> bool;
|
||||
fn psyc_is_name_char(c: c_char) -> bool;
|
||||
fn psyc_is_host_char(c: c_char) -> bool;
|
||||
fn psyc_parse_keyword(data: *const c_char, len: usize) -> usize;
|
||||
}
|
||||
|
||||
pub struct PsycParser {
|
||||
|
@ -68,51 +31,65 @@ pub struct PsycListParser {
|
|||
state: PsycParseListState
|
||||
}
|
||||
|
||||
pub struct PsycDictParser {
|
||||
state: PsycParseDictState
|
||||
}
|
||||
|
||||
pub struct PsycIndexParser {
|
||||
state: PsycParseIndexState
|
||||
}
|
||||
|
||||
pub struct PsycUpdateParser {
|
||||
state: PsycParseUpdateState
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycParserResult {
|
||||
pub enum PsycParserResult<'a> {
|
||||
StateSync,
|
||||
StateReset,
|
||||
ParsingComplete,
|
||||
Complete,
|
||||
InsufficientData,
|
||||
RoutingModifier {
|
||||
operator: char,
|
||||
name: String,
|
||||
value: Vec<u8>
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
EntityModifier {
|
||||
operator: char,
|
||||
name: String,
|
||||
value: Vec<u8>
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
IncompleteEntityModifier {
|
||||
EntityModifierStart {
|
||||
operator: char,
|
||||
name: String,
|
||||
value: Vec<u8>,
|
||||
cursor: usize
|
||||
name: &'a [u8],
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
EntityModifierCont {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
EntityModifierEnd {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
Body {
|
||||
name: String,
|
||||
value: Vec<u8>
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
IncompleteBody {
|
||||
name: String,
|
||||
value: Vec<u8>,
|
||||
cursor: usize
|
||||
BodyStart {
|
||||
name: &'a [u8],
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
InsufficientData {
|
||||
cursor: usize
|
||||
BodyCont {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
BodyEnd {
|
||||
value_part: &'a [u8]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycListParserResult<'a> {
|
||||
Complete,
|
||||
InsufficientData,
|
||||
ListElement {
|
||||
value: &'a [u8]
|
||||
},
|
||||
ListElementStart {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
ListElementCont {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
ListElementEnd {
|
||||
value_part: &'a [u8]
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -130,6 +107,17 @@ pub enum PsycParserError {
|
|||
GenericError = PsycParseRC::PSYC_PARSE_ERROR as _,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycListParserError {
|
||||
NoElementLength = PsycParseListRC::PSYC_PARSE_LIST_ERROR_ELEM_NO_LEN as _,
|
||||
InvalidElementLength = PsycParseListRC::PSYC_PARSE_LIST_ERROR_ELEM_LENGTH as _,
|
||||
InvalidElementType = PsycParseListRC::PSYC_PARSE_LIST_ERROR_ELEM_TYPE as _,
|
||||
InvalidElementStart = PsycParseListRC::PSYC_PARSE_LIST_ERROR_ELEM_START as _,
|
||||
InvalidType = PsycParseListRC::PSYC_PARSE_LIST_ERROR_TYPE as _,
|
||||
GenericError = PsycParseListRC::PSYC_PARSE_LIST_ERROR as _,
|
||||
}
|
||||
|
||||
impl PsycParser {
|
||||
/// Create a PsycParser
|
||||
pub fn new() -> Self {
|
||||
|
@ -139,27 +127,24 @@ impl PsycParser {
|
|||
let state_ptr = &mut state as *mut PsycParseState;
|
||||
psyc_parse_state_init(state_ptr, PsycParseFlag::PSYC_PARSE_ALL as u8)
|
||||
}
|
||||
PsycParser{state: state}
|
||||
}
|
||||
|
||||
/// Set a buffer of raw bytes for parsing
|
||||
pub fn set_buffer(&mut self, buffer: &[u8]) {
|
||||
let state_ptr = &mut self.state as *mut PsycParseState;
|
||||
let buffer_ptr = &buffer[0] as *const u8 as *const c_char;
|
||||
unsafe {
|
||||
psyc_parse_buffer_set(state_ptr, buffer_ptr, buffer.len())
|
||||
PsycParser {
|
||||
state: state
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the buffer previously set by set_buffer. Call repeatedly until the
|
||||
/// result is PsycParserResult::ParsingComplete or a PsycParserError.
|
||||
pub fn parse(&mut self) -> Result<PsycParserResult, PsycParserError> {
|
||||
/// result is PsycParserResult::Complete or a PsycParserError.
|
||||
pub fn parse<'a>(&mut self, buffer: &'a [u8]) -> Result<PsycParserResult<'a>, PsycParserError> {
|
||||
let state_ptr = &mut self.state as *mut PsycParseState;
|
||||
let mut operator: char;
|
||||
let buffer_ptr = buffer.as_ptr() as *const c_char;
|
||||
let mut operator = '\0';
|
||||
let mut name: PsycString;
|
||||
let mut value: PsycString;
|
||||
unsafe {
|
||||
operator = mem::uninitialized();
|
||||
if buffer_ptr != self.state.buffer.data ||
|
||||
buffer.len() != self.state.buffer.length {
|
||||
psyc_parse_buffer_set(state_ptr, buffer_ptr, buffer.len())
|
||||
}
|
||||
name = mem::uninitialized();
|
||||
value = mem::uninitialized();
|
||||
let operator_ptr = &mut operator as *mut char as *mut c_char;
|
||||
|
@ -167,68 +152,6 @@ impl PsycParser {
|
|||
let value_ptr = &mut value as *mut PsycString;
|
||||
let parse_result = psyc_parse(state_ptr, operator_ptr, name_ptr, value_ptr);
|
||||
match parse_result {
|
||||
PsycParseRC::PSYC_PARSE_INSUFFICIENT => {
|
||||
let result =
|
||||
PsycParserResult::InsufficientData {
|
||||
cursor: psyc_parse_cursor(state_ptr)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ROUTING => {
|
||||
let result =
|
||||
PsycParserResult::RoutingModifier {
|
||||
operator: operator,
|
||||
name: Self::cstring_to_string(name.data, name.length),
|
||||
value: Self::cstring_to_bytes(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ENTITY |
|
||||
PsycParseRC::PSYC_PARSE_ENTITY_END => {
|
||||
let result =
|
||||
PsycParserResult::EntityModifier {
|
||||
operator: operator,
|
||||
name: Self::cstring_to_string(name.data, name.length),
|
||||
value: Self::cstring_to_bytes(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ENTITY_START |
|
||||
PsycParseRC::PSYC_PARSE_ENTITY_CONT => {
|
||||
let result =
|
||||
PsycParserResult::IncompleteEntityModifier {
|
||||
operator: operator,
|
||||
name: Self::cstring_to_string(name.data, name.length),
|
||||
value: Self::cstring_to_bytes(value.data, value.length),
|
||||
cursor: psyc_parse_cursor(state_ptr)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_BODY |
|
||||
PsycParseRC::PSYC_PARSE_BODY_END => {
|
||||
let result =
|
||||
PsycParserResult::Body {
|
||||
name: Self::cstring_to_string(name.data, name.length),
|
||||
value: Self::cstring_to_bytes(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_BODY_START |
|
||||
PsycParseRC::PSYC_PARSE_BODY_CONT => {
|
||||
let result =
|
||||
PsycParserResult::IncompleteBody {
|
||||
name: Self::cstring_to_string(name.data, name.length),
|
||||
value: Self::cstring_to_bytes(value.data, value.length),
|
||||
cursor: psyc_parse_cursor(state_ptr)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_STATE_RESYNC =>
|
||||
Ok(PsycParserResult::StateSync),
|
||||
|
||||
|
@ -236,19 +159,202 @@ impl PsycParser {
|
|||
Ok(PsycParserResult::StateReset),
|
||||
|
||||
PsycParseRC::PSYC_PARSE_COMPLETE =>
|
||||
Ok(PsycParserResult::ParsingComplete),
|
||||
Ok(PsycParserResult::Complete),
|
||||
|
||||
PsycParseRC::PSYC_PARSE_INSUFFICIENT =>
|
||||
Ok(PsycParserResult::InsufficientData),
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ROUTING => {
|
||||
let result = PsycParserResult::RoutingModifier {
|
||||
operator: operator,
|
||||
name: util::cstring_to_slice(name.data, name.length),
|
||||
value: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ENTITY => {
|
||||
let result = PsycParserResult::EntityModifier {
|
||||
operator: operator,
|
||||
name: util::cstring_to_slice(name.data, name.length),
|
||||
value: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ENTITY_START => {
|
||||
let result = PsycParserResult::EntityModifierStart {
|
||||
operator: operator,
|
||||
name: util::cstring_to_slice(name.data, name.length),
|
||||
value_part: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ENTITY_CONT => {
|
||||
let result = PsycParserResult::EntityModifierCont {
|
||||
value_part: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_ENTITY_END => {
|
||||
let result = PsycParserResult::EntityModifierEnd {
|
||||
value_part: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
PsycParseRC::PSYC_PARSE_BODY => {
|
||||
let result = PsycParserResult::Body {
|
||||
name: util::cstring_to_slice(name.data, name.length),
|
||||
value: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_BODY_START => {
|
||||
let result = PsycParserResult::BodyStart {
|
||||
name: util::cstring_to_slice(name.data, name.length),
|
||||
value_part: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
PsycParseRC::PSYC_PARSE_BODY_CONT => {
|
||||
let result = PsycParserResult::BodyCont {
|
||||
value_part: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
PsycParseRC::PSYC_PARSE_BODY_END => {
|
||||
let result = PsycParserResult::BodyEnd {
|
||||
value_part: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
_error => Err(mem::transmute(_error)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn cstring_to_string(cstring: *const c_char, length: usize) -> String {
|
||||
let vec = Self::cstring_to_bytes(cstring, length);
|
||||
String::from_utf8(vec).unwrap()
|
||||
}
|
||||
|
||||
unsafe fn cstring_to_bytes(cstring: *const c_char, length: usize) -> Vec<u8> {
|
||||
slice::from_raw_parts(cstring as *const u8, length).to_vec()
|
||||
impl Parser for PsycParser {
|
||||
fn unparsed_position(&self) -> usize {
|
||||
unsafe {
|
||||
psyc_parse_cursor(&self.state as *const PsycParseState)
|
||||
}
|
||||
}
|
||||
|
||||
fn unparsed_length(&self) -> usize {
|
||||
unsafe {
|
||||
psyc_parse_remaining_length(&self.state as *const PsycParseState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PsycListParser {
|
||||
pub fn new() -> Self {
|
||||
let mut state: PsycParseListState;
|
||||
unsafe {
|
||||
state = mem::uninitialized();
|
||||
let state_ptr = &mut state as *mut PsycParseListState;
|
||||
psyc_parse_list_state_init(state_ptr)
|
||||
}
|
||||
PsycListParser {
|
||||
state: state
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse<'a>(&mut self, buffer: &'a [u8]) -> Result<PsycListParserResult<'a>, PsycListParserError> {
|
||||
let state_ptr = &mut self.state as *mut PsycParseListState;
|
||||
let buffer_ptr = buffer.as_ptr() as *const c_char;
|
||||
let mut list_type: PsycString;
|
||||
let mut element: PsycString;
|
||||
unsafe {
|
||||
if buffer_ptr != self.state.buffer.data ||
|
||||
buffer.len() != self.state.buffer.length {
|
||||
psyc_parse_list_buffer_set(state_ptr, buffer_ptr, buffer.len())
|
||||
}
|
||||
list_type = mem::uninitialized();
|
||||
element = mem::uninitialized();
|
||||
let list_type_ptr = &mut list_type as *mut PsycString;
|
||||
let element_ptr = &mut element as *mut PsycString;
|
||||
loop {
|
||||
let parse_result = psyc_parse_list(state_ptr, list_type_ptr, element_ptr);
|
||||
match parse_result {
|
||||
PsycParseListRC::PSYC_PARSE_LIST_END =>
|
||||
return Ok(PsycListParserResult::Complete),
|
||||
|
||||
PsycParseListRC::PSYC_PARSE_LIST_INSUFFICIENT =>
|
||||
return Ok(PsycListParserResult::InsufficientData),
|
||||
|
||||
PsycParseListRC::PSYC_PARSE_LIST_ELEM_LAST |
|
||||
PsycParseListRC::PSYC_PARSE_LIST_ELEM => {
|
||||
let result = PsycListParserResult::ListElement {
|
||||
value: util::cstring_to_slice(element.data, element.length)
|
||||
};
|
||||
return Ok(result)
|
||||
},
|
||||
|
||||
PsycParseListRC::PSYC_PARSE_LIST_ELEM_START => {
|
||||
let result = PsycListParserResult::ListElementStart {
|
||||
value_part: util::cstring_to_slice(element.data, element.length)
|
||||
};
|
||||
return Ok(result)
|
||||
},
|
||||
|
||||
PsycParseListRC::PSYC_PARSE_LIST_ELEM_CONT => {
|
||||
let result = PsycListParserResult::ListElementCont {
|
||||
value_part: util::cstring_to_slice(element.data, element.length)
|
||||
};
|
||||
return Ok(result)
|
||||
},
|
||||
|
||||
PsycParseListRC::PSYC_PARSE_LIST_ELEM_END => {
|
||||
let result = PsycListParserResult::ListElementEnd {
|
||||
value_part: util::cstring_to_slice(element.data, element.length)
|
||||
};
|
||||
return Ok(result)
|
||||
},
|
||||
|
||||
PsycParseListRC::PSYC_PARSE_LIST_TYPE => (),
|
||||
|
||||
_error => {
|
||||
return Err(mem::transmute(_error))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parser for PsycListParser {
|
||||
fn unparsed_position(&self) -> usize {
|
||||
self.state.cursor
|
||||
}
|
||||
|
||||
fn unparsed_length(&self) -> usize {
|
||||
self.state.buffer.length - self.state.cursor
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Parser {
|
||||
/// copies the remaining unparsed bytes to the beginning of the given buffer.
|
||||
/// Returns the number of copied bytes. Must be called when parse() returned
|
||||
/// InsufficientData as Result.
|
||||
fn copy_unparsed_into_buffer<'a>(&self, buffer: &'a mut [u8]) -> usize {
|
||||
let unparsed_pos = self.unparsed_position();
|
||||
let unparsed_len = self.unparsed_length();
|
||||
if unparsed_pos != 0 {
|
||||
let copy_pos_second = unparsed_pos - unparsed_len;
|
||||
let (part1, part2) = buffer.split_at_mut(unparsed_len);
|
||||
part1.copy_from_slice(&part2[copy_pos_second .. copy_pos_second + unparsed_len]);
|
||||
}
|
||||
unparsed_len
|
||||
}
|
||||
|
||||
fn unparsed_position(&self) -> usize;
|
||||
fn unparsed_length(&self) -> usize;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ enum PsycUpdatePart { }
|
|||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseState {
|
||||
buffer: PsycString,
|
||||
pub buffer: PsycString,
|
||||
cursor: usize,
|
||||
startc: usize,
|
||||
routinglen: usize,
|
||||
|
@ -25,8 +25,8 @@ pub struct PsycParseState {
|
|||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseListState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
pub buffer: PsycString,
|
||||
pub cursor: usize,
|
||||
startc: usize,
|
||||
list_type: PsycString,
|
||||
elemlen: usize,
|
||||
|
@ -37,8 +37,8 @@ pub struct PsycParseListState {
|
|||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseDictState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
pub buffer: PsycString,
|
||||
pub cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
|
@ -49,7 +49,7 @@ pub struct PsycParseDictState {
|
|||
#[repr(C)]
|
||||
pub struct PsycParseIndexState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
pub cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
|
@ -60,7 +60,7 @@ pub struct PsycParseIndexState {
|
|||
#[repr(C)]
|
||||
pub struct PsycParseUpdateState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
pub cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
|
@ -79,6 +79,7 @@ pub enum PsycParseFlag {
|
|||
PSYC_PARSE_START_AT_CONTENT = 2,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub enum PsycParseRC {
|
||||
/// Error, no length is set for a modifier which is longer than PSYC_MODIFIER_SIZE_THRESHOLD.
|
||||
|
@ -150,6 +151,7 @@ pub enum PsycParseRC {
|
|||
PSYC_PARSE_COMPLETE = 13,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub enum PsycParseListRC {
|
||||
/// Error, no length is set for an element which is longer than PSYC_ELEM_SIZE_THRESHOLD.
|
||||
|
@ -180,6 +182,7 @@ pub enum PsycParseListRC {
|
|||
PSYC_PARSE_LIST_END = 8,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub enum PsycParseDictRC {
|
||||
PSYC_PARSE_DICT_ERROR_VALUE = -9,
|
||||
|
|
20
rust/src/util.rs
Normal file
20
rust/src/util.rs
Normal file
|
@ -0,0 +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
|
||||
}
|
103
rust/tests/test_list_parser.rs
Normal file
103
rust/tests/test_list_parser.rs
Normal file
|
@ -0,0 +1,103 @@
|
|||
extern crate psyc;
|
||||
use psyc::parser::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
let test_data = "| element1| element2| element3".to_string().into_bytes();
|
||||
|
||||
let expected1 = PsycListParserResult::ListElement {
|
||||
value: b"element1"
|
||||
};
|
||||
|
||||
let expected2 = PsycListParserResult::ListElement {
|
||||
value: b"element2"
|
||||
};
|
||||
|
||||
let expected3 = PsycListParserResult::ListElement {
|
||||
value: b"element3"
|
||||
};
|
||||
|
||||
let expected4 = PsycListParserResult::Complete;
|
||||
|
||||
let mut parser = PsycListParser::new();
|
||||
|
||||
//parser.set_buffer(&test_data);
|
||||
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), expected1);
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), expected2);
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), expected3);
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), expected4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let test_data = "".to_string().into_bytes();
|
||||
|
||||
let mut parser = PsycListParser::new();
|
||||
|
||||
//parser.set_buffer(&test_data);
|
||||
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), PsycListParserResult::Complete);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_element() {
|
||||
let test_data = "|".to_string().into_bytes();
|
||||
|
||||
let mut parser = PsycListParser::new();
|
||||
|
||||
let expected = PsycListParserResult::ListElement {
|
||||
value: b""
|
||||
};
|
||||
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_incomplete() {
|
||||
let test_data1 = "|8 element".to_string().into_bytes();
|
||||
let test_data2 = "1| element2|".to_string().into_bytes();
|
||||
|
||||
let expected = vec![PsycListParserResult::ListElementStart {
|
||||
value_part: b"element"
|
||||
},
|
||||
PsycListParserResult::ListElementEnd {
|
||||
value_part: b"1"
|
||||
},
|
||||
PsycListParserResult::ListElement {
|
||||
value: b"element2"
|
||||
}];
|
||||
|
||||
let mut parser = PsycListParser::new();
|
||||
|
||||
//parser.set_buffer(&test_data1);
|
||||
assert_eq!(parser.parse(&test_data1).unwrap(), expected[0]);
|
||||
|
||||
//parser.set_buffer(&test_data2);
|
||||
assert_eq!(parser.parse(&test_data2).unwrap(), expected[1]);
|
||||
|
||||
assert_eq!(parser.parse(&test_data2).unwrap(), expected[2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insufficient() {
|
||||
let mut test_data1 = "|4".to_string().into_bytes();
|
||||
let mut test_data2 = " foo1".to_string().into_bytes();
|
||||
|
||||
let expected = vec![PsycListParserResult::InsufficientData,
|
||||
PsycListParserResult::ListElement {
|
||||
value: b"foo1"
|
||||
}];
|
||||
|
||||
let mut parser = PsycListParser::new();
|
||||
|
||||
//parser.set_buffer(&test_data1);
|
||||
|
||||
assert_eq!(parser.parse(&test_data1).unwrap(), expected[0]);
|
||||
|
||||
let unparsed_length = parser.copy_unparsed_into_buffer(&mut test_data1);
|
||||
test_data1.resize(unparsed_length, 0);
|
||||
test_data1.append(&mut test_data2);
|
||||
//parser.set_buffer(&test_data1);
|
||||
assert_eq!(parser.parse(&test_data1).unwrap(), expected[1]);
|
||||
}
|
|
@ -62,36 +62,3 @@ fn test_list() {
|
|||
|
||||
assert_eq!(rendered_packet, Ok(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dict() {
|
||||
let r1 = PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
|
||||
"_target",
|
||||
"psyc://ve.symlynx.com/@blog".as_bytes());
|
||||
|
||||
let dict = PsycDict::from_strings(&[("key1", "value1"),
|
||||
("key2", "value2"),
|
||||
("key3", "value3")]);
|
||||
|
||||
let e1 = PsycModifier::with_dict_value(PsycOperator::PSYC_OPERATOR_SET,
|
||||
"_dict_test",
|
||||
&dict);
|
||||
|
||||
let routing_modifiers = vec![r1];
|
||||
let entity_modifiers = vec![e1];
|
||||
let data = vec![];
|
||||
|
||||
let packet = PsycPacket::new(&routing_modifiers,
|
||||
&entity_modifiers,
|
||||
"",
|
||||
&data,
|
||||
PsycStateOp::PSYC_STATE_NOOP);
|
||||
|
||||
let expected = ":_target\tpsyc://ve.symlynx.com/@blog\n58\n:_dict_test 42\t{ key1} value1{ key2} value2{ key3} value3\n|\n".as_bytes().to_vec();
|
||||
|
||||
let rendered_packet = packet.render();
|
||||
|
||||
//println!("rendered: {}", String::from_utf8(rendered_packet.unwrap()).unwrap());
|
||||
|
||||
assert_eq!(rendered_packet, Ok(expected));
|
||||
}
|
||||
|
|
49
rust/tests/test_packet_id.rs
Normal file
49
rust/tests/test_packet_id.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
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
|
||||
};
|
||||
|
||||
let packet_id = packet.packet_id();
|
||||
|
||||
assert_eq!(packet_id, expected_id);
|
||||
|
||||
let expected_rendered = b"|| psyc://ve.symlynx.com/~alice| psyc://ve.symlynx.com/~bob| 42|";
|
||||
|
||||
let rendered_id = packet_id.render();
|
||||
|
||||
assert_eq!(rendered_id, expected_rendered.to_vec());
|
||||
|
||||
let parsed_id = PacketId::from_bytes(&rendered_id);
|
||||
|
||||
assert_eq!(parsed_id.unwrap(), packet_id);
|
||||
}
|
|
@ -1,26 +1,88 @@
|
|||
extern crate psyc;
|
||||
|
||||
use psyc::parser::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
let test_data = ":_target\tpsyc://ve.symlynx.com/@blog\n\n?\n|\n".to_string().into_bytes();
|
||||
|
||||
let expected1 =
|
||||
PsycParserResult::RoutingModifier{
|
||||
let expected = vec![PsycParserResult::RoutingModifier{
|
||||
operator: ':',
|
||||
name: "_target".to_string(),
|
||||
value: "psyc://ve.symlynx.com/@blog".to_string().into_bytes()
|
||||
};
|
||||
|
||||
let expected2 = PsycParserResult::StateSync;
|
||||
name: "_target".as_bytes(),
|
||||
value: "psyc://ve.symlynx.com/@blog".as_bytes(),
|
||||
},
|
||||
PsycParserResult::StateSync];
|
||||
|
||||
let mut parser = PsycParser::new();
|
||||
parser.set_buffer(&test_data);
|
||||
|
||||
let result1 = parser.parse();
|
||||
let result2 = parser.parse();
|
||||
|
||||
assert_eq!(result1, Ok(expected1));
|
||||
assert_eq!(result2, Ok(expected2));
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), expected[0]);
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), expected[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let test_data = "".to_string().into_bytes();
|
||||
|
||||
let mut parser = PsycParser::new();
|
||||
|
||||
// FIXME: InsufficientData or Complete?
|
||||
assert_eq!(parser.parse(&test_data).unwrap(), PsycParserResult::InsufficientData);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_incomplete() {
|
||||
let test_data1 = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_nick 6\t".to_string().into_bytes();
|
||||
|
||||
let test_data2 = "lurchi".to_string().into_bytes();
|
||||
|
||||
let expected = vec![PsycParserResult::EntityModifierStart {
|
||||
operator: ':',
|
||||
name: b"_nick",
|
||||
value_part: b""
|
||||
},
|
||||
PsycParserResult::EntityModifierEnd {
|
||||
value_part: b"lurchi"
|
||||
}];
|
||||
|
||||
let mut parser = PsycParser::new();
|
||||
|
||||
let _ = parser.parse(&test_data1);
|
||||
assert_eq!(parser.parse(&test_data1).unwrap(), expected[0]);
|
||||
|
||||
assert_eq!(parser.parse(&test_data2).unwrap(), expected[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insufficient() {
|
||||
let mut test_data1 = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_nick".to_string().into_bytes();
|
||||
let mut test_data2 = "\tlurchi\n|\n".to_string().into_bytes();
|
||||
|
||||
let expected = vec![PsycParserResult::InsufficientData,
|
||||
PsycParserResult::RoutingModifier {
|
||||
operator: ':',
|
||||
name: b"_target",
|
||||
value: b"psyc://ve.symlynx.com/@blog"
|
||||
},
|
||||
PsycParserResult::InsufficientData,
|
||||
PsycParserResult::EntityModifier{
|
||||
operator: ':',
|
||||
name: b"_nick",
|
||||
value: b"lurchi"
|
||||
},
|
||||
PsycParserResult::Complete];
|
||||
|
||||
let mut parser = PsycParser::new();
|
||||
|
||||
assert_eq!(parser.parse(&test_data1[.. 1]).unwrap(), expected[0]);
|
||||
|
||||
let unparsed_length = parser.copy_unparsed_into_buffer(&mut test_data1);
|
||||
assert_eq!(unparsed_length, 1);
|
||||
assert_eq!(parser.parse(&test_data1[.. 44]).unwrap(), expected[1]);
|
||||
|
||||
assert_eq!(parser.parse(&test_data1[.. 44]).unwrap(), expected[2]);
|
||||
|
||||
let unparsed_length = parser.copy_unparsed_into_buffer(&mut test_data1);
|
||||
test_data1.resize(unparsed_length, 0);
|
||||
test_data1.append(&mut test_data2);
|
||||
assert_eq!(parser.parse(&test_data1).unwrap(), expected[3]);
|
||||
assert_eq!(parser.parse(&test_data1).unwrap(), expected[4]);
|
||||
}
|
||||
|
|
25
src/parse.c
25
src/parse.c
|
@ -119,7 +119,7 @@ psyc_parse_remaining_buffer (PsycParseState *state);
|
|||
*
|
||||
* @return PARSE_ERROR or PARSE_SUCCESS
|
||||
*/
|
||||
static inline ParseRC
|
||||
inline ParseRC
|
||||
parse_keyword (ParseState *state, PsycString *name)
|
||||
{
|
||||
name->data = state->buffer.data + state->cursor;
|
||||
|
@ -138,7 +138,7 @@ parse_keyword (ParseState *state, PsycString *name)
|
|||
*
|
||||
* @return PARSE_SUCCESS, PARSE_ERROR or PARSE_INSUFFICIENT
|
||||
*/
|
||||
static inline ParseRC
|
||||
inline ParseRC
|
||||
parse_length (ParseState *state, size_t *len)
|
||||
{
|
||||
ParseRC ret = PARSE_ERROR;
|
||||
|
@ -165,7 +165,7 @@ parse_length (ParseState *state, size_t *len)
|
|||
*
|
||||
* @return PARSE_SUCCESS or PARSE_INCOMPLETE
|
||||
*/
|
||||
static inline ParseRC
|
||||
inline ParseRC
|
||||
parse_binary (ParseState *state, size_t length, PsycString *value, size_t *parsed)
|
||||
{
|
||||
size_t remaining = length - *parsed;
|
||||
|
@ -197,7 +197,7 @@ parse_binary (ParseState *state, size_t length, PsycString *value, size_t *parse
|
|||
*
|
||||
* @return PARSE_SUCCESS or PARSE_INSUFFICIENT
|
||||
*/
|
||||
static inline ParseRC
|
||||
inline ParseRC
|
||||
parse_until (ParseState *state, const char end, PsycString *value)
|
||||
{
|
||||
value->data = state->buffer.data + state->cursor;
|
||||
|
@ -215,7 +215,7 @@ parse_until (ParseState *state, const char end, PsycString *value)
|
|||
* @return PARSE_ERROR or PARSE_SUCCESS
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
extern inline
|
||||
inline
|
||||
#endif
|
||||
ParseRC
|
||||
psyc_parse_modifier (PsycParseState *state, char *oper,
|
||||
|
@ -282,7 +282,7 @@ psyc_parse_modifier (PsycParseState *state, char *oper,
|
|||
|
||||
/** Parse PSYC packets. */
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseRC
|
||||
psyc_parse (PsycParseState *state, char *oper,
|
||||
|
@ -566,7 +566,7 @@ psyc_parse (PsycParseState *state, char *oper,
|
|||
* list-value = %x00-7B / %x7D-FF ; any byte except "|"
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
extern inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseListRC
|
||||
psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
||||
|
@ -683,12 +683,14 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
|||
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
||||
&state->elem_parsed)) {
|
||||
case PARSE_SUCCESS:
|
||||
state->part = PSYC_LIST_PART_ELEM_START;
|
||||
if (elem->length == state->elem_parsed)
|
||||
ret = PSYC_PARSE_LIST_ELEM;
|
||||
else
|
||||
ret = PSYC_PARSE_LIST_ELEM_END;
|
||||
break;
|
||||
case PARSE_INCOMPLETE:
|
||||
state->part = PSYC_LIST_PART_ELEM;
|
||||
if (elem->length == state->elem_parsed)
|
||||
ret = PSYC_PARSE_LIST_ELEM_START;
|
||||
else
|
||||
|
@ -700,16 +702,17 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
|||
} else {
|
||||
switch (parse_until((ParseState*)state, '|', elem)) {
|
||||
case PARSE_SUCCESS:
|
||||
state->part = PSYC_LIST_PART_ELEM_START;
|
||||
ret = PSYC_PARSE_LIST_ELEM;
|
||||
break;
|
||||
case PARSE_INSUFFICIENT:
|
||||
state->cursor = state->buffer.length;
|
||||
return PSYC_PARSE_LIST_ELEM_LAST;
|
||||
default: // should not be reached
|
||||
return PSYC_PARSE_LIST_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
state->part = PSYC_LIST_PART_ELEM_START;
|
||||
state->startc = state->cursor;
|
||||
return ret;
|
||||
}
|
||||
|
@ -727,7 +730,7 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
|||
* dict-value = %x00-7A / %x7C-FF ; any byte except "}"
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
extern inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseDictRC
|
||||
psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
||||
|
@ -951,7 +954,7 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
|||
}
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
extern inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseIndexRC
|
||||
psyc_parse_index (PsycParseIndexState *state, PsycString *idx)
|
||||
|
@ -1079,7 +1082,7 @@ psyc_parse_index (PsycParseIndexState *state, PsycString *idx)
|
|||
}
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
extern inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseUpdateRC
|
||||
psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value)
|
||||
|
|
|
@ -105,7 +105,7 @@ psyc_render_list (PsycList *list, char *buffer, size_t buflen)
|
|||
}
|
||||
|
||||
#ifdef __INLINE_PSYC_RENDER
|
||||
static inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycRenderRC
|
||||
psyc_render_dict (PsycDict *dict, char *buffer, size_t buflen)
|
||||
|
|
|
@ -43,6 +43,9 @@ psyc_text_buffer_set (PsycTextState *state, char *buffer, size_t length);
|
|||
extern inline size_t
|
||||
psyc_text_bytes_written (PsycTextState *state);
|
||||
|
||||
extern inline const char *
|
||||
psyc_template (PsycMethod mc, size_t *len);
|
||||
|
||||
PsycTextRC
|
||||
psyc_text (PsycTextState *state, PsycTextCB get_value, void *get_value_cls)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue