mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
Merging rust bindings from lurchi, thxaloz!
This commit is contained in:
commit
8b2d725514
24 changed files with 1406 additions and 54 deletions
|
@ -77,7 +77,7 @@ psyc_map_lookup (const PsycMap *map, size_t size,
|
|||
* Look up value associated with a key in a map with integer values.
|
||||
* @see psyc_map_lookup
|
||||
*/
|
||||
static inline intptr_t
|
||||
inline intptr_t
|
||||
psyc_map_lookup_int (const PsycMapInt *map, size_t size,
|
||||
const char *key, size_t keylen, PsycBool inherit)
|
||||
{
|
||||
|
|
|
@ -253,7 +253,7 @@ typedef struct {
|
|||
/**
|
||||
* Return the number of digits a number has in its base 10 representation.
|
||||
*/
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_num_length (size_t n)
|
||||
{
|
||||
return n < 10 ? 1 : log10(n) + 1;
|
||||
|
@ -263,7 +263,7 @@ psyc_num_length (size_t n)
|
|||
* \internal
|
||||
* Check if a modifier needs length.
|
||||
*/
|
||||
static inline PsycModifierFlag
|
||||
inline PsycModifierFlag
|
||||
psyc_modifier_length_check (PsycModifier *m)
|
||||
{
|
||||
if (m->value.length > 0
|
||||
|
@ -275,7 +275,7 @@ psyc_modifier_length_check (PsycModifier *m)
|
|||
}
|
||||
|
||||
/** Initialize modifier */
|
||||
static inline void
|
||||
inline void
|
||||
psyc_modifier_init (PsycModifier *m, PsycOperator oper,
|
||||
char *name, size_t namelen,
|
||||
char *value, size_t valuelen, PsycModifierFlag flag)
|
||||
|
|
|
@ -510,7 +510,7 @@ typedef struct {
|
|||
* @param flags Flags to be set for the parser, see PsycParseFlag.
|
||||
* @see PsycParseFlag
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_state_init (PsycParseState *state, uint8_t flags)
|
||||
{
|
||||
memset(state, 0, sizeof(PsycParseState));
|
||||
|
@ -531,7 +531,7 @@ psyc_parse_state_init (PsycParseState *state, uint8_t flags)
|
|||
* @param length length of the data in bytes
|
||||
* @see PsycString
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_buffer_set (PsycParseState *state, const char *buffer, size_t length)
|
||||
{
|
||||
state->buffer = (PsycString) {length, (char*)buffer};
|
||||
|
@ -546,7 +546,7 @@ psyc_parse_buffer_set (PsycParseState *state, const char *buffer, size_t length)
|
|||
/**
|
||||
* Initializes the list parser state.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_list_state_init (PsycParseListState *state)
|
||||
{
|
||||
memset(state, 0, sizeof(PsycParseListState));
|
||||
|
@ -555,7 +555,7 @@ psyc_parse_list_state_init (PsycParseListState *state)
|
|||
/**
|
||||
* Sets a new buffer in the list parser state struct with data to be parsed.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_list_buffer_set (PsycParseListState *state,
|
||||
const char *buffer, size_t length)
|
||||
{
|
||||
|
@ -566,7 +566,7 @@ psyc_parse_list_buffer_set (PsycParseListState *state,
|
|||
/**
|
||||
* Initializes the dict parser state.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_dict_state_init (PsycParseDictState *state)
|
||||
{
|
||||
memset(state, 0, sizeof(PsycParseDictState));
|
||||
|
@ -575,7 +575,7 @@ psyc_parse_dict_state_init (PsycParseDictState *state)
|
|||
/**
|
||||
* Sets a new buffer in the dict parser state struct with data to be parsed.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_dict_buffer_set (PsycParseDictState *state,
|
||||
const char *buffer, size_t length)
|
||||
{
|
||||
|
@ -586,7 +586,7 @@ psyc_parse_dict_buffer_set (PsycParseDictState *state,
|
|||
/**
|
||||
* Initializes the index parser state.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_index_state_init (PsycParseIndexState *state)
|
||||
{
|
||||
memset(state, 0, sizeof(PsycParseIndexState));
|
||||
|
@ -595,7 +595,7 @@ psyc_parse_index_state_init (PsycParseIndexState *state)
|
|||
/**
|
||||
* Sets a new buffer in the index parser state struct with data to be parsed.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_index_buffer_set (PsycParseIndexState *state,
|
||||
const char *buffer, size_t length)
|
||||
{
|
||||
|
@ -606,7 +606,7 @@ psyc_parse_index_buffer_set (PsycParseIndexState *state,
|
|||
/**
|
||||
* Initializes the update modifier parser state.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_update_state_init (PsycParseUpdateState *state)
|
||||
{
|
||||
memset(state, 0, sizeof(PsycParseUpdateState));
|
||||
|
@ -615,7 +615,7 @@ psyc_parse_update_state_init (PsycParseUpdateState *state)
|
|||
/**
|
||||
* Sets a new buffer in the update modifier parser state struct with data to be parsed.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_parse_update_buffer_set (PsycParseUpdateState *state,
|
||||
const char *buffer, size_t length)
|
||||
{
|
||||
|
@ -623,49 +623,49 @@ psyc_parse_update_buffer_set (PsycParseUpdateState *state,
|
|||
state->cursor = 0;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_content_length (PsycParseState *state)
|
||||
{
|
||||
return state->contentlen;
|
||||
}
|
||||
|
||||
static inline PsycBool
|
||||
inline PsycBool
|
||||
psyc_parse_content_length_found (PsycParseState *state)
|
||||
{
|
||||
return (PsycBool) state->contentlen_found;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_value_length (PsycParseState *state)
|
||||
{
|
||||
return state->valuelen;
|
||||
}
|
||||
|
||||
static inline PsycBool
|
||||
inline PsycBool
|
||||
psyc_parse_value_length_found (PsycParseState *state)
|
||||
{
|
||||
return (PsycBool) state->valuelen_found;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_cursor (PsycParseState *state)
|
||||
{
|
||||
return state->cursor;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_buffer_length (PsycParseState *state)
|
||||
{
|
||||
return state->buffer.length;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_remaining_length (PsycParseState *state)
|
||||
{
|
||||
return state->buffer.length - state->cursor;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
inline const char *
|
||||
psyc_parse_remaining_buffer (PsycParseState *state)
|
||||
{
|
||||
return state->buffer.data + state->cursor;
|
||||
|
@ -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
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseRC
|
||||
psyc_parse (PsycParseState *state, char *oper,
|
||||
|
@ -706,30 +706,30 @@ psyc_parse (PsycParseState *state, char *oper,
|
|||
* @param elem It will point to the next element in the list.
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseListRC
|
||||
psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem);
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseDictRC
|
||||
psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem);
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseIndexRC
|
||||
psyc_parse_index (PsycParseIndexState *state, PsycString *idx);
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycParseUpdateRC
|
||||
psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value);
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_int (const char *value, size_t len, int64_t *n)
|
||||
{
|
||||
size_t c = 0;
|
||||
|
@ -754,7 +754,7 @@ psyc_parse_int (const char *value, size_t len, int64_t *n)
|
|||
return c;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_uint (const char *value, size_t len, uint64_t *n)
|
||||
{
|
||||
size_t c = 0;
|
||||
|
@ -768,7 +768,7 @@ psyc_parse_uint (const char *value, size_t len, uint64_t *n)
|
|||
return c;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_list_index (const char *value, size_t len, int64_t *n)
|
||||
{
|
||||
if (!value || len == 0 || value[0] != '#')
|
||||
|
@ -780,7 +780,7 @@ psyc_parse_list_index (const char *value, size_t len, int64_t *n)
|
|||
* Determines if the argument is a glyph.
|
||||
* Glyphs are: : = + - ? !
|
||||
*/
|
||||
static inline PsycBool
|
||||
inline PsycBool
|
||||
psyc_is_oper (char g)
|
||||
{
|
||||
switch (g) {
|
||||
|
@ -800,7 +800,7 @@ psyc_is_oper (char g)
|
|||
/**
|
||||
* Determines if the argument is numeric.
|
||||
*/
|
||||
static inline char
|
||||
inline char
|
||||
psyc_is_numeric (char c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
|
@ -809,7 +809,7 @@ psyc_is_numeric (char c)
|
|||
/**
|
||||
* Determines if the argument is alphabetic.
|
||||
*/
|
||||
static inline char
|
||||
inline char
|
||||
psyc_is_alpha (char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
|
@ -818,7 +818,7 @@ psyc_is_alpha (char c)
|
|||
/**
|
||||
* Determines if the argument is alphanumeric.
|
||||
*/
|
||||
static inline char
|
||||
inline char
|
||||
psyc_is_alpha_numeric (char c)
|
||||
{
|
||||
return psyc_is_alpha(c) || psyc_is_numeric(c);
|
||||
|
@ -828,7 +828,7 @@ psyc_is_alpha_numeric (char c)
|
|||
* Determines if the argument is a keyword character.
|
||||
* Keyword characters are: alphanumeric and _
|
||||
*/
|
||||
static inline char
|
||||
inline char
|
||||
psyc_is_kw_char (char c)
|
||||
{
|
||||
return psyc_is_alpha_numeric(c) || c == '_';
|
||||
|
@ -838,7 +838,7 @@ psyc_is_kw_char (char c)
|
|||
* Determines if the argument is a name character.
|
||||
* Name characters are: see opaque_part in RFC 2396
|
||||
*/
|
||||
static inline char
|
||||
inline char
|
||||
psyc_is_name_char (char c)
|
||||
{
|
||||
return psyc_is_alpha(c) || (c >= '$' && c <= ';')
|
||||
|
@ -849,7 +849,7 @@ psyc_is_name_char (char c)
|
|||
* Determines if the argument is a hostname character.
|
||||
* Hostname characters are: alphanumeric and -
|
||||
*/
|
||||
static inline char
|
||||
inline char
|
||||
psyc_is_host_char (char c)
|
||||
{
|
||||
return psyc_is_alpha_numeric(c) || c == '.' || c == '-';
|
||||
|
@ -860,7 +860,7 @@ psyc_is_host_char (char c)
|
|||
* It should contain one or more keyword characters.
|
||||
* @return Number of characters parsed.
|
||||
*/
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_parse_keyword (const char *data, size_t len)
|
||||
{
|
||||
size_t c = 0;
|
||||
|
|
|
@ -66,7 +66,7 @@ typedef enum {
|
|||
* @see psyc_packet_length_set()
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_RENDER
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycRenderRC
|
||||
psyc_render (PsycPacket *packet, char *buffer, size_t buflen);
|
||||
|
@ -84,7 +84,7 @@ psyc_render_dict_key (PsycDictKey *elem, char *buffer, size_t buflen);
|
|||
* Render a PSYC list into a buffer.
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_RENDER
|
||||
static inline
|
||||
inline
|
||||
#endif
|
||||
PsycRenderRC
|
||||
psyc_render_list (PsycList *list, char *buffer, size_t buflen);
|
||||
|
|
|
@ -94,7 +94,7 @@ typedef PsycTextValueRC (*PsycTextCB) (void *cls, const char *name, size_t namel
|
|||
* @param buffer Output buffer where the rendered text is going to be written.
|
||||
* @param buflen Length of output buffer.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_text_state_init (PsycTextState *state,
|
||||
char *tmpl, size_t tmplen,
|
||||
char *buffer, size_t buflen)
|
||||
|
@ -120,7 +120,7 @@ psyc_text_state_init (PsycTextState *state,
|
|||
* @param clo Closing brace.
|
||||
* @param clolen Length of closing brace.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_text_state_init_custom (PsycTextState *state,
|
||||
char *tmpl, size_t tmplen,
|
||||
char *buffer, size_t buflen,
|
||||
|
@ -138,7 +138,7 @@ psyc_text_state_init_custom (PsycTextState *state,
|
|||
/**
|
||||
* Sets a new output buffer in the PSYC text state struct.
|
||||
*/
|
||||
static inline void
|
||||
inline void
|
||||
psyc_text_buffer_set (PsycTextState *state, char *buffer, size_t length)
|
||||
{
|
||||
state->buffer = (PsycString) {
|
||||
|
@ -146,7 +146,7 @@ psyc_text_buffer_set (PsycTextState *state, char *buffer, size_t length)
|
|||
state->written = 0;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
inline size_t
|
||||
psyc_text_bytes_written (PsycTextState *state)
|
||||
{
|
||||
return state->written;
|
||||
|
|
|
@ -117,7 +117,7 @@ psyc_uniform_parse (PsycUniform *uni, const char *buffer, size_t length);
|
|||
*
|
||||
* @return PsycEntityType on success, PSYC_ERROR on error.
|
||||
*/
|
||||
static inline int
|
||||
inline int
|
||||
psyc_entity_type (char entity)
|
||||
{
|
||||
switch (entity) {
|
||||
|
|
|
@ -88,7 +88,7 @@ typedef enum {
|
|||
/**
|
||||
* Look up routing variable.
|
||||
*/
|
||||
static inline PsycRoutingVar
|
||||
inline PsycRoutingVar
|
||||
psyc_var_routing (const char *name, size_t len)
|
||||
{
|
||||
return (PsycRoutingVar)
|
||||
|
@ -99,7 +99,7 @@ psyc_var_routing (const char *name, size_t len)
|
|||
/**
|
||||
* Get the type of variable name.
|
||||
*/
|
||||
static inline PsycType
|
||||
inline PsycType
|
||||
psyc_var_type (const char *name, size_t len)
|
||||
{
|
||||
return (PsycType)
|
||||
|
@ -110,7 +110,7 @@ psyc_var_type (const char *name, size_t len)
|
|||
/**
|
||||
* Is this a list variable name?
|
||||
*/
|
||||
static inline PsycBool
|
||||
inline PsycBool
|
||||
psyc_var_is_list (const char *name, size_t len)
|
||||
{
|
||||
return len < 5 || memcmp(name, "_list", 5) != 0 || (len > 5 && name[5] != '_')
|
||||
|
|
6
rust/Cargo.toml
Normal file
6
rust/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "psyc"
|
||||
version = "1.0.0"
|
||||
links = "psyc"
|
||||
build = "build.rs"
|
||||
description = "rust bindings for libpsyc"
|
18
rust/build.rs
Normal file
18
rust/build.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::path::*;
|
||||
|
||||
fn main() {
|
||||
Command::new("make")
|
||||
.arg("-C")
|
||||
.arg("..")
|
||||
.output()
|
||||
.unwrap_or_else(|e| panic!("failed to execute process: {}", e));
|
||||
|
||||
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let path = Path::new(&manifest_dir).parent().unwrap().join("lib");
|
||||
|
||||
println!("cargo:rustc-link-search=native={}", path.display());
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
println!("cargo:rustc-link-lib=static=psyc");
|
||||
}
|
9
rust/src/lib.rs
Normal file
9
rust/src/lib.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
#![allow(dead_code)]
|
||||
mod types;
|
||||
pub mod parser_types;
|
||||
pub mod packet_types;
|
||||
pub mod parser;
|
||||
pub mod packet;
|
||||
|
||||
pub use parser::*;
|
||||
pub use packet::*;
|
347
rust/src/packet.rs
Normal file
347
rust/src/packet.rs
Normal file
|
@ -0,0 +1,347 @@
|
|||
use types::*;
|
||||
use packet_types::*;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
extern "C" {
|
||||
/// functions from packet.h
|
||||
fn psyc_num_length(n: usize) -> usize;
|
||||
fn psyc_modifier_length_check(m: *const RawPsycModifier) -> PsycModifierFlag;
|
||||
fn psyc_modifier_init(m: *mut RawPsycModifier,
|
||||
oper: PsycOperator,
|
||||
name: *const c_char,
|
||||
namelen: usize,
|
||||
value: *const c_char,
|
||||
valuelen: usize,
|
||||
flag: PsycModifierFlag);
|
||||
|
||||
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,
|
||||
entity: *const RawPsycModifier,
|
||||
entitylen: usize,
|
||||
method: *const c_char,
|
||||
methodlen: usize,
|
||||
data: *const c_char,
|
||||
datalen: usize,
|
||||
stateop: c_char,
|
||||
flag: PsycPacketFlag);
|
||||
|
||||
fn psyc_packet_init_raw(packet: *mut RawPsycPacket,
|
||||
routing: *const RawPsycModifier,
|
||||
routinglen: usize,
|
||||
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_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],
|
||||
operator: PsycOperator,
|
||||
}
|
||||
|
||||
pub struct PsycPacket<'a> {
|
||||
raw_packet: RawPsycPacket,
|
||||
routing_modifiers: &'a [PsycModifier<'a>],
|
||||
entity_modifiers: &'a [PsycModifier<'a>],
|
||||
raw_routing_modifiers: Vec<RawPsycModifier>,
|
||||
raw_entity_modifiers: Vec<RawPsycModifier>,
|
||||
method: &'a str,
|
||||
body: &'a [u8]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycRenderError {
|
||||
MethodMissing = PsycRenderRC::PSYC_RENDER_ERROR_METHOD_MISSING as _,
|
||||
ModifierNameMissing = PsycRenderRC::PSYC_RENDER_ERROR_MODIFIER_NAME_MISSING as _,
|
||||
GenericError = PsycRenderRC::PSYC_RENDER_ERROR as _
|
||||
}
|
||||
|
||||
impl PsycList {
|
||||
/// Construct a PsycList from a list of byte lists
|
||||
pub fn new(list: &[&[u8]]) -> Self {
|
||||
let mut psyc_list: RawPsycList;
|
||||
let elements: Vec<PsycElem>;
|
||||
let mut 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);
|
||||
}
|
||||
PsycList {
|
||||
rendered_list: buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a PsycList from a list of strings (comfort function)
|
||||
pub fn from_strings(list: &[&str]) -> Self {
|
||||
let list_slices: Vec<&[u8]> = list.iter().map(|e| e.as_bytes()).collect();
|
||||
Self::new(&list_slices)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
PsycModifier {name: name, value: value, operator: operator}
|
||||
}
|
||||
|
||||
/// construct a PsycModifier with string value (comfort function)
|
||||
pub fn with_string_value(operator: PsycOperator,
|
||||
name: &'a str,
|
||||
value: &'a str)
|
||||
-> Self {
|
||||
PsycModifier {
|
||||
name: name,
|
||||
value: value.as_bytes(),
|
||||
operator: operator
|
||||
}
|
||||
}
|
||||
|
||||
/// construct a PsycModifier with list value
|
||||
pub fn with_list_value(operator: PsycOperator,
|
||||
name: &'a str,
|
||||
value: &'a PsycList)
|
||||
-> Self {
|
||||
PsycModifier {
|
||||
name: name,
|
||||
value: &value.rendered_list,
|
||||
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> {
|
||||
///
|
||||
pub fn new(routing_modifiers: &'a [PsycModifier],
|
||||
entity_modifiers: &'a [PsycModifier],
|
||||
method: &'a str,
|
||||
data: &'a [u8],
|
||||
state_operator: PsycStateOp)
|
||||
-> Self {
|
||||
let mut packet: RawPsycPacket;
|
||||
let raw_routing_modifiers: Vec<RawPsycModifier>;
|
||||
let raw_entity_modifiers: Vec<RawPsycModifier>;
|
||||
unsafe{
|
||||
packet = mem::uninitialized();
|
||||
let packet_ptr = &mut packet as *mut RawPsycPacket;
|
||||
raw_routing_modifiers = routing_modifiers.iter().map(
|
||||
|m| Self::make_raw_modifier(m, PsycModifierFlag::PSYC_MODIFIER_ROUTING)
|
||||
).collect();
|
||||
raw_entity_modifiers = entity_modifiers.iter().map(
|
||||
|m| Self::make_raw_modifier(m, PsycModifierFlag::PSYC_MODIFIER_CHECK_LENGTH)
|
||||
).collect();
|
||||
psyc_packet_init(packet_ptr,
|
||||
raw_routing_modifiers.as_ptr() as *const RawPsycModifier,
|
||||
raw_routing_modifiers.len(),
|
||||
raw_entity_modifiers.as_ptr() as *const RawPsycModifier,
|
||||
raw_entity_modifiers.len(),
|
||||
method.as_ptr() as *const c_char,
|
||||
method.len(),
|
||||
data.as_ptr() as *const c_char,
|
||||
data.len(),
|
||||
state_operator as c_char,
|
||||
PsycPacketFlag::PSYC_PACKET_CHECK_LENGTH);
|
||||
}
|
||||
PsycPacket {
|
||||
raw_packet: packet,
|
||||
routing_modifiers: routing_modifiers,
|
||||
entity_modifiers: entity_modifiers,
|
||||
raw_routing_modifiers: raw_routing_modifiers,
|
||||
raw_entity_modifiers: raw_entity_modifiers,
|
||||
method: method,
|
||||
body: data
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_raw(routing_modifiers: &'a [PsycModifier],
|
||||
content: &'a [u8]) -> Self {
|
||||
let mut packet: RawPsycPacket;
|
||||
let raw_routing_modifiers: Vec<RawPsycModifier>;
|
||||
unsafe {
|
||||
packet = mem::uninitialized();
|
||||
let packet_ptr = &mut packet as *mut RawPsycPacket;
|
||||
raw_routing_modifiers = routing_modifiers.iter().map(
|
||||
|m| Self::make_raw_modifier(m, PsycModifierFlag::PSYC_MODIFIER_ROUTING)
|
||||
).collect();
|
||||
psyc_packet_init_raw(packet_ptr,
|
||||
raw_routing_modifiers.as_ptr() as *const RawPsycModifier,
|
||||
raw_routing_modifiers.len(),
|
||||
content.as_ptr() as *const c_char,
|
||||
content.len(),
|
||||
PsycPacketFlag::PSYC_PACKET_CHECK_LENGTH);
|
||||
}
|
||||
PsycPacket {
|
||||
raw_packet: packet,
|
||||
routing_modifiers: routing_modifiers,
|
||||
entity_modifiers: &[],
|
||||
raw_routing_modifiers: raw_routing_modifiers,
|
||||
raw_entity_modifiers: vec![],
|
||||
method: "",
|
||||
body: content
|
||||
}
|
||||
}
|
||||
|
||||
/// the length of the rendered packet
|
||||
pub fn length(&self) -> usize {
|
||||
self.raw_packet.length
|
||||
}
|
||||
|
||||
///
|
||||
pub fn render(&self) -> Result<Vec<u8>, PsycRenderError> {
|
||||
let raw_packet_ptr = & self.raw_packet as *const RawPsycPacket;
|
||||
let mut buffer = Vec::with_capacity(self.length());
|
||||
let buffer_ptr = buffer.as_mut_ptr() as *mut c_char;
|
||||
unsafe {
|
||||
buffer.set_len(self.length());
|
||||
let result = psyc_render(raw_packet_ptr, buffer_ptr, buffer.capacity());
|
||||
match result {
|
||||
PsycRenderRC::PSYC_RENDER_SUCCESS => Ok(buffer),
|
||||
_error => Err(mem::transmute(_error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_raw_modifier(modifier: &'a PsycModifier,
|
||||
flag: PsycModifierFlag)
|
||||
-> RawPsycModifier {
|
||||
let mut raw_modifier: RawPsycModifier;
|
||||
unsafe {
|
||||
raw_modifier = mem::uninitialized();
|
||||
let raw_modifier_ptr = &mut raw_modifier as *mut RawPsycModifier;
|
||||
let name_ptr = modifier.name.as_ptr() as *const c_char;
|
||||
let value_ptr = modifier.value.as_ptr() as *const c_char;
|
||||
psyc_modifier_init(raw_modifier_ptr,
|
||||
modifier.operator,
|
||||
name_ptr,
|
||||
modifier.name.len(),
|
||||
value_ptr,
|
||||
modifier.value.len(),
|
||||
flag);
|
||||
}
|
||||
raw_modifier
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn make_psyc_elem(list_element: &[u8]) -> PsycElem {
|
||||
let list_element_ptr = list_element.as_ptr() as *const c_char;
|
||||
PsycElem {
|
||||
elem_type: PsycString {length: 0, data: ptr::null()},
|
||||
value: PsycString {length: list_element.len(), data: list_element_ptr},
|
||||
length: 0,
|
||||
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
|
||||
}
|
||||
}
|
142
rust/src/packet_types.rs
Normal file
142
rust/src/packet_types.rs
Normal file
|
@ -0,0 +1,142 @@
|
|||
use std::os::raw::c_char;
|
||||
use types::*;
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycModifierFlag {
|
||||
/// Modifier needs to be checked if it needs length.
|
||||
PSYC_MODIFIER_CHECK_LENGTH = 0,
|
||||
/// Modifier needs length.
|
||||
PSYC_MODIFIER_NEED_LENGTH = 1,
|
||||
/// Modifier doesn't need length.
|
||||
PSYC_MODIFIER_NO_LENGTH = 2,
|
||||
/// Routing modifier, which implies that it doesn't need length.
|
||||
PSYC_MODIFIER_ROUTING = 4,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycElemFlag {
|
||||
/// Element needs to be checked if it needs length.
|
||||
PSYC_ELEM_CHECK_LENGTH = 0,
|
||||
/// Element needs length.
|
||||
PSYC_ELEM_NEED_LENGTH = 1,
|
||||
/// Element doesn't need length.
|
||||
PSYC_ELEM_NO_LENGTH = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycPacketFlag {
|
||||
/// Packet needs to be checked if it needs content length.
|
||||
PSYC_PACKET_CHECK_LENGTH = 0,
|
||||
/// Packet needs content length.
|
||||
PSYC_PACKET_NEED_LENGTH = 1,
|
||||
/// Packet doesn't need content length.
|
||||
PSYC_PACKET_NO_LENGTH = 2,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum PsycOperator {
|
||||
PSYC_OPERATOR_SET = ':' as _,
|
||||
PSYC_OPERATOR_ASSIGN = '=' as _,
|
||||
PSYC_OPERATOR_AUGMENT = '+' as _,
|
||||
PSYC_OPERATOR_DIMINISH = '-' as _,
|
||||
PSYC_OPERATOR_UPDATE = '@' as _,
|
||||
PSYC_OPERATOR_QUERY = '?' as _,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycStateOp {
|
||||
PSYC_STATE_NOOP = 0,
|
||||
PSYC_STATE_RESET = '=' as _,
|
||||
PSYC_STATE_RESYNC = '?' as _,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycPacketId {
|
||||
PSYC_PACKET_ID_CONTEXT = 0,
|
||||
PSYC_PACKET_ID_SOURCE = 1,
|
||||
PSYC_PACKET_ID_TARGET = 2,
|
||||
PSYC_PACKET_ID_COUNTER = 3,
|
||||
PSYC_PACKET_ID_FRAGMENT = 4,
|
||||
PSYC_PACKET_ID_ELEMS = 5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycElem {
|
||||
pub elem_type: PsycString,
|
||||
pub value: PsycString,
|
||||
pub length: usize,
|
||||
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,
|
||||
elems: *const PsycElem,
|
||||
num_elems: usize,
|
||||
pub length: usize
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RawPsycModifier {
|
||||
name: PsycString,
|
||||
value: PsycString,
|
||||
flag: PsycModifierFlag,
|
||||
oper: c_char
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycHeader {
|
||||
lines: usize,
|
||||
modifiers: *mut RawPsycModifier
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RawPsycPacket {
|
||||
routing: PsycHeader,
|
||||
entity: PsycHeader,
|
||||
method: PsycString,
|
||||
data: PsycString,
|
||||
content: PsycString,
|
||||
routinglen: usize,
|
||||
contentlen: usize,
|
||||
pub length: usize,
|
||||
stateop: PsycStateOp,
|
||||
flag: PsycPacketFlag
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycRenderRC {
|
||||
/// Error, method is missing, but data is present.
|
||||
PSYC_RENDER_ERROR_METHOD_MISSING = -3,
|
||||
/// Error, a modifier name is missing.
|
||||
PSYC_RENDER_ERROR_MODIFIER_NAME_MISSING = -2,
|
||||
/// Error, buffer is too small to render the packet.
|
||||
PSYC_RENDER_ERROR = -1,
|
||||
/// Packet is rendered successfully in the buffer.
|
||||
PSYC_RENDER_SUCCESS = 0,
|
||||
}
|
||||
|
||||
|
||||
|
254
rust/src/parser.rs
Normal file
254
rust/src/parser.rs
Normal file
|
@ -0,0 +1,254 @@
|
|||
use types::*;
|
||||
use parser_types::*;
|
||||
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(state: *mut PsycParseState,
|
||||
oper: *mut c_char,
|
||||
name: *mut PsycString,
|
||||
value: *mut PsycString)
|
||||
-> PsycParseRC;
|
||||
|
||||
fn psyc_parse_list(state: *mut PsycParseListState,
|
||||
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 {
|
||||
state: PsycParseState
|
||||
}
|
||||
|
||||
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 {
|
||||
StateSync,
|
||||
StateReset,
|
||||
ParsingComplete,
|
||||
RoutingModifier {
|
||||
operator: char,
|
||||
name: String,
|
||||
value: Vec<u8>
|
||||
},
|
||||
EntityModifier {
|
||||
operator: char,
|
||||
name: String,
|
||||
value: Vec<u8>
|
||||
},
|
||||
IncompleteEntityModifier {
|
||||
operator: char,
|
||||
name: String,
|
||||
value: Vec<u8>,
|
||||
cursor: usize
|
||||
},
|
||||
Body {
|
||||
name: String,
|
||||
value: Vec<u8>
|
||||
},
|
||||
IncompleteBody {
|
||||
name: String,
|
||||
value: Vec<u8>,
|
||||
cursor: usize
|
||||
},
|
||||
InsufficientData {
|
||||
cursor: usize
|
||||
},
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycParserError {
|
||||
NoModifierLength = PsycParseRC::PSYC_PARSE_ERROR_MOD_NO_LEN as _,
|
||||
NoContentLength = PsycParseRC::PSYC_PARSE_ERROR_NO_LEN as _,
|
||||
NoEndDelimiter = PsycParseRC::PSYC_PARSE_ERROR_END as _,
|
||||
NoNewlineAfterMethod = PsycParseRC::PSYC_PARSE_ERROR_METHOD as _,
|
||||
NoNewlineAfterModifier = PsycParseRC::PSYC_PARSE_ERROR_MOD_NL as _,
|
||||
InvalidModifierLength = PsycParseRC::PSYC_PARSE_ERROR_MOD_LEN as _,
|
||||
NoTabBeforeModifierValue = PsycParseRC::PSYC_PARSE_ERROR_MOD_TAB as _,
|
||||
NoModifierName = PsycParseRC::PSYC_PARSE_ERROR_MOD_NAME as _,
|
||||
NoNewlineAfterContentLength = PsycParseRC::PSYC_PARSE_ERROR_LENGTH as _,
|
||||
GenericError = PsycParseRC::PSYC_PARSE_ERROR as _,
|
||||
}
|
||||
|
||||
impl PsycParser {
|
||||
/// Create a PsycParser
|
||||
pub fn new() -> Self {
|
||||
let mut state: PsycParseState;
|
||||
unsafe {
|
||||
state = mem::uninitialized();
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
let state_ptr = &mut self.state as *mut PsycParseState;
|
||||
let mut operator: char;
|
||||
let mut name: PsycString;
|
||||
let mut value: PsycString;
|
||||
unsafe {
|
||||
operator = mem::uninitialized();
|
||||
name = mem::uninitialized();
|
||||
value = mem::uninitialized();
|
||||
let operator_ptr = &mut operator as *mut char as *mut c_char;
|
||||
let name_ptr = &mut name as *mut PsycString;
|
||||
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),
|
||||
|
||||
PsycParseRC::PSYC_PARSE_STATE_RESET =>
|
||||
Ok(PsycParserResult::StateReset),
|
||||
|
||||
PsycParseRC::PSYC_PARSE_COMPLETE =>
|
||||
Ok(PsycParserResult::ParsingComplete),
|
||||
|
||||
_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()
|
||||
}
|
||||
}
|
300
rust/src/parser_types.rs
Normal file
300
rust/src/parser_types.rs
Normal file
|
@ -0,0 +1,300 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
use types::*;
|
||||
|
||||
enum PsycPart { }
|
||||
enum PsycListPart { }
|
||||
enum PsycDictPart { }
|
||||
enum PsycIndexPart { }
|
||||
enum PsycUpdatePart { }
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
startc: usize,
|
||||
routinglen: usize,
|
||||
contentlen: usize,
|
||||
content_parsed: usize,
|
||||
valuelen: usize,
|
||||
value_parsed: usize,
|
||||
part: PsycPart,
|
||||
flags: u8,
|
||||
contentlen_found: u8,
|
||||
valuelen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseListState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
startc: usize,
|
||||
list_type: PsycString,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
part: PsycListPart,
|
||||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseDictState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
part: PsycDictPart,
|
||||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseIndexState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
part: PsycIndexPart,
|
||||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseUpdateState {
|
||||
buffer: PsycString,
|
||||
cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
part: PsycUpdatePart,
|
||||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycParseFlag {
|
||||
/// Default Flag. Parse everything.
|
||||
PSYC_PARSE_ALL = 0,
|
||||
/// Parse only the header
|
||||
PSYC_PARSE_ROUTING_ONLY = 1,
|
||||
/// Parse only the content.
|
||||
/// Parsing starts at the content and the content must be complete.
|
||||
PSYC_PARSE_START_AT_CONTENT = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycParseRC {
|
||||
/// Error, no length is set for a modifier which is longer than PSYC_MODIFIER_SIZE_THRESHOLD.
|
||||
PSYC_PARSE_ERROR_MOD_NO_LEN = -10,
|
||||
/// Error, no length is set for the content but it is longer than PSYC_CONTENT_SIZE_THRESHOLD.
|
||||
PSYC_PARSE_ERROR_NO_LEN = -9,
|
||||
/// Error, packet is not ending with a valid delimiter.
|
||||
PSYC_PARSE_ERROR_END = -8,
|
||||
/// Error, expected NL after the method.
|
||||
PSYC_PARSE_ERROR_METHOD = -7,
|
||||
/// Error, expected NL after a modifier.
|
||||
PSYC_PARSE_ERROR_MOD_NL = -6,
|
||||
/// Error, modifier length is not numeric.
|
||||
PSYC_PARSE_ERROR_MOD_LEN = -5,
|
||||
/// Error, expected TAB before modifier value.
|
||||
PSYC_PARSE_ERROR_MOD_TAB = -4,
|
||||
/// Error, modifier name is missing.
|
||||
PSYC_PARSE_ERROR_MOD_NAME = -3,
|
||||
/// Error, expected NL after the content length.
|
||||
PSYC_PARSE_ERROR_LENGTH = -2,
|
||||
/// Error in packet.
|
||||
PSYC_PARSE_ERROR = -1,
|
||||
/// Buffer contains insufficient amount of data.
|
||||
/// Fill another buffer and concatenate it with the end of the current buffer,
|
||||
/// from the cursor position to the end.
|
||||
PSYC_PARSE_INSUFFICIENT = 1,
|
||||
/// Routing modifier parsing done.
|
||||
/// Operator, name & value contains the respective parts.
|
||||
PSYC_PARSE_ROUTING = 2,
|
||||
/// State sync operation.
|
||||
PSYC_PARSE_STATE_RESYNC = 3,
|
||||
/// State reset operation.
|
||||
PSYC_PARSE_STATE_RESET = 4,
|
||||
/// Start of an incomplete entity modifier.
|
||||
/// Operator & name are complete, value is incomplete.
|
||||
PSYC_PARSE_ENTITY_START = 5,
|
||||
/// Continuation of an incomplete entity modifier.
|
||||
PSYC_PARSE_ENTITY_CONT = 6,
|
||||
/// End of an incomplete entity modifier.
|
||||
PSYC_PARSE_ENTITY_END = 7,
|
||||
/// Entity modifier parsing done in one go.
|
||||
/// Operator, name & value contains the respective parts.
|
||||
PSYC_PARSE_ENTITY = 8,
|
||||
/// Start of an incomplete body.
|
||||
/// Name contains method, value contains part of the body.
|
||||
/// Used when packet length is given
|
||||
PSYC_PARSE_BODY_START = 9,
|
||||
/// Continuation of an incomplete body.
|
||||
/// Used when packet length is given
|
||||
PSYC_PARSE_BODY_CONT = 10,
|
||||
/// End of an incomplete body.
|
||||
/// Used when packet length is given
|
||||
PSYC_PARSE_BODY_END = 11,
|
||||
/// Body parsing done in one go, name contains method, value contains body.
|
||||
PSYC_PARSE_BODY = 12,
|
||||
///// Start of an incomplete content, value contains part of content.
|
||||
///// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
||||
//PSYC_PARSE_CONTENT_START = 9,
|
||||
///// Continuation of an incomplete content.
|
||||
///// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
||||
//PSYC_PARSE_CONTENT_CONT = 10,
|
||||
///// End of an incomplete content.
|
||||
///// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
||||
//PSYC_PARSE_CONTENT_END = 11,
|
||||
///// Content parsing done in one go, value contains the whole content.
|
||||
///// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
||||
//PSYC_PARSE_CONTENT = 12,
|
||||
/// Finished parsing packet.
|
||||
PSYC_PARSE_COMPLETE = 13,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycParseListRC {
|
||||
/// Error, no length is set for an element which is longer than PSYC_ELEM_SIZE_THRESHOLD.
|
||||
PSYC_PARSE_LIST_ERROR_ELEM_NO_LEN = -6,
|
||||
PSYC_PARSE_LIST_ERROR_ELEM_LENGTH = -5,
|
||||
PSYC_PARSE_LIST_ERROR_ELEM_TYPE = -4,
|
||||
PSYC_PARSE_LIST_ERROR_ELEM_START = -3,
|
||||
PSYC_PARSE_LIST_ERROR_TYPE = -2,
|
||||
PSYC_PARSE_LIST_ERROR = -1,
|
||||
/// Reached end of buffer.
|
||||
/// Buffer contains insufficient amount of data.
|
||||
/// Fill another buffer and concatenate it with the end of the current buffer,
|
||||
/// from the cursor position to the end.
|
||||
PSYC_PARSE_LIST_INSUFFICIENT = 1,
|
||||
/// Completed parsing the default type of the list.
|
||||
PSYC_PARSE_LIST_TYPE = 2,
|
||||
/// Start of an element is parsed but still not complete.
|
||||
PSYC_PARSE_LIST_ELEM_START = 3,
|
||||
/// Continuation of an incomplete element.
|
||||
PSYC_PARSE_LIST_ELEM_CONT = 4,
|
||||
/// Element parsing completed.
|
||||
PSYC_PARSE_LIST_ELEM_END = 5,
|
||||
/// Completed parsing a list element.
|
||||
PSYC_PARSE_LIST_ELEM = 6,
|
||||
/// Completed parsing the last element in the list.
|
||||
PSYC_PARSE_LIST_ELEM_LAST = 7,
|
||||
/// Reached end of buffer.
|
||||
PSYC_PARSE_LIST_END = 8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycParseDictRC {
|
||||
PSYC_PARSE_DICT_ERROR_VALUE = -9,
|
||||
PSYC_PARSE_DICT_ERROR_VALUE_LENGTH = -8,
|
||||
PSYC_PARSE_DICT_ERROR_VALUE_TYPE = -7,
|
||||
PSYC_PARSE_DICT_ERROR_VALUE_START = -6,
|
||||
PSYC_PARSE_DICT_ERROR_KEY = -5,
|
||||
PSYC_PARSE_DICT_ERROR_KEY_LENGTH = -4,
|
||||
PSYC_PARSE_DICT_ERROR_KEY_START = -3,
|
||||
PSYC_PARSE_DICT_ERROR_TYPE = -2,
|
||||
PSYC_PARSE_DICT_ERROR = -1,
|
||||
/// Reached end of buffer.
|
||||
/// Buffer contains insufficient amount of data.
|
||||
/// Fill another buffer and concatenate it with the end of the current buffer,
|
||||
/// from the cursor position to the end.
|
||||
PSYC_PARSE_DICT_INSUFFICIENT = 1,
|
||||
/// Completed parsing the default type of the dict.
|
||||
PSYC_PARSE_DICT_TYPE = 2,
|
||||
/// Start of a key is parsed but still not complete.
|
||||
PSYC_PARSE_DICT_KEY_START = 3,
|
||||
/// Continuation of an incomplete key.
|
||||
PSYC_PARSE_DICT_KEY_CONT = 4,
|
||||
/// Last continuation of a key.
|
||||
PSYC_PARSE_DICT_KEY_END = 5,
|
||||
/// Completed parsing a key in one go.
|
||||
PSYC_PARSE_DICT_KEY = 6,
|
||||
/// Start of a value is parsed but still not complete.
|
||||
PSYC_PARSE_DICT_VALUE_START = 7,
|
||||
/// Continuation of an incomplete value.
|
||||
PSYC_PARSE_DICT_VALUE_CONT = 8,
|
||||
/// Last continuation of a value.
|
||||
PSYC_PARSE_DICT_VALUE_END = 9,
|
||||
/// Completed parsing a value.
|
||||
PSYC_PARSE_DICT_VALUE = 10,
|
||||
/// Completed parsing the last value.
|
||||
PSYC_PARSE_DICT_VALUE_LAST = 11,
|
||||
/// Reached end of buffer.
|
||||
PSYC_PARSE_DICT_END = 12,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycParseIndexRC {
|
||||
PSYC_PARSE_INDEX_ERROR_DICT = -6,
|
||||
PSYC_PARSE_INDEX_ERROR_DICT_LENGTH = -5,
|
||||
PSYC_PARSE_INDEX_ERROR_STRUCT = -4,
|
||||
PSYC_PARSE_INDEX_ERROR_LIST = -3,
|
||||
PSYC_PARSE_INDEX_ERROR_TYPE = -2,
|
||||
PSYC_PARSE_INDEX_ERROR = -1,
|
||||
/// Reached end of buffer.
|
||||
/// Buffer contains insufficient amount of data.
|
||||
/// Fill another buffer and concatenate it with the end of the current buffer,
|
||||
/// from the cursor position to the end.
|
||||
PSYC_PARSE_INDEX_INSUFFICIENT = 1,
|
||||
// Completed parsing a list index.
|
||||
PSYC_PARSE_INDEX_LIST = 3,
|
||||
// Completed parsing a list index at the end of the buffer.
|
||||
PSYC_PARSE_INDEX_LIST_LAST = 4,
|
||||
// Completed parsing a struct element name.
|
||||
PSYC_PARSE_INDEX_STRUCT = 5,
|
||||
// Completed parsing a struct element name at the end of the buffer.
|
||||
PSYC_PARSE_INDEX_STRUCT_LAST = 6,
|
||||
/// Start of a dict key is parsed but still not complete.
|
||||
PSYC_PARSE_INDEX_DICT_START = 7,
|
||||
/// Continuation of an incomplete dict key.
|
||||
PSYC_PARSE_INDEX_DICT_CONT = 8,
|
||||
/// Last continuation of a dict key.
|
||||
PSYC_PARSE_INDEX_DICT_END = 9,
|
||||
/// Completed parsing a dict key in one go.
|
||||
PSYC_PARSE_INDEX_DICT = 10,
|
||||
/// Reached end of buffer.
|
||||
PSYC_PARSE_INDEX_END = 11,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycParseUpdateRC {
|
||||
PSYC_PARSE_UPDATE_ERROR_VALUE = -24,
|
||||
PSYC_PARSE_UPDATE_ERROR_LENGTH = -23,
|
||||
PSYC_PARSE_UPDATE_ERROR_TYPE = -22,
|
||||
PSYC_PARSE_UPDATE_ERROR_OPER = -21,
|
||||
PSYC_PARSE_UPDATE_ERROR = -1,
|
||||
/// Reached end of buffer.
|
||||
/// Buffer contains insufficient amount of data.
|
||||
/// Fill another buffer and concatenate it with the end of the current buffer,
|
||||
/// from the cursor position to the end.
|
||||
PSYC_PARSE_UPDATE_INSUFFICIENT = 1,
|
||||
|
||||
// Completed parsing a list index.
|
||||
PSYC_PARSE_UPDATE_INDEX_LIST = 3,
|
||||
// Completed parsing a struct element name.
|
||||
PSYC_PARSE_UPDATE_INDEX_STRUCT = 5,
|
||||
/// Start of a dict key is parsed but still not complete.
|
||||
PSYC_PARSE_UPDATE_INDEX_DICT_START = 7,
|
||||
/// Continuation of an incomplete dict key.
|
||||
PSYC_PARSE_UPDATE_INDEX_DICT_CONT = 8,
|
||||
/// Last continuation of a dict key.
|
||||
PSYC_PARSE_UPDATE_INDEX_DICT_END = 9,
|
||||
/// Completed parsing a dict key in one go.
|
||||
PSYC_PARSE_UPDATE_INDEX_DICT = 10,
|
||||
|
||||
/// Completed parsing the type.
|
||||
PSYC_PARSE_UPDATE_TYPE = 21,
|
||||
/// Completed parsing the type and reached end of buffer.
|
||||
PSYC_PARSE_UPDATE_TYPE_END = 22,
|
||||
/// Start of the value is parsed but still not complete.
|
||||
PSYC_PARSE_UPDATE_VALUE_START = 23,
|
||||
/// Continuation of incomplete value.
|
||||
PSYC_PARSE_UPDATE_VALUE_CONT = 24,
|
||||
/// Last continuation of the value.
|
||||
PSYC_PARSE_UPDATE_VALUE_END = 25,
|
||||
/// Completed parsing the value in one go.
|
||||
PSYC_PARSE_UPDATE_VALUE = 26,
|
||||
/// Reached end of buffer.
|
||||
PSYC_PARSE_UPDATE_END = 27,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
9
rust/src/types.rs
Normal file
9
rust/src/types.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
use std::os::raw::c_char;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycString {
|
||||
pub length: usize,
|
||||
pub data: *const c_char
|
||||
}
|
||||
|
||||
|
97
rust/tests/test_packet.rs
Normal file
97
rust/tests/test_packet.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
extern crate psyc;
|
||||
|
||||
use psyc::*;
|
||||
use psyc::packet_types::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_render() {
|
||||
let r1 = PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
|
||||
"_target",
|
||||
"psyc://ve.symlynx.com/@blog".as_bytes());
|
||||
|
||||
let r2 = PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
|
||||
"_tag",
|
||||
"666666".as_bytes());
|
||||
|
||||
let e1 = PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
|
||||
"_nick",
|
||||
"lurchi".as_bytes());
|
||||
|
||||
let routing_modifiers = vec![r1, r2];
|
||||
let entity_modifiers = vec![e1];
|
||||
let data = vec![];
|
||||
|
||||
let packet = PsycPacket::new(&routing_modifiers,
|
||||
&entity_modifiers,
|
||||
"_request_context_enter",
|
||||
&data,
|
||||
PsycStateOp::PSYC_STATE_NOOP);
|
||||
|
||||
let expected = ":_target\tpsyc://ve.symlynx.com/@blog\n:_tag\t666666\n\n:_nick\tlurchi\n_request_context_enter\n|\n".as_bytes().to_vec();
|
||||
|
||||
let rendered_packet = packet.render();
|
||||
|
||||
assert_eq!(rendered_packet, Ok(expected))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list() {
|
||||
let r1 = PsycModifier::new(PsycOperator::PSYC_OPERATOR_SET,
|
||||
"_target",
|
||||
"psyc://ve.symlynx.com/@blog".as_bytes());
|
||||
|
||||
let list = PsycList::from_strings(&["str1", "str2", "str3"]);
|
||||
|
||||
let e1 = PsycModifier::with_list_value(PsycOperator::PSYC_OPERATOR_SET,
|
||||
"_list_test",
|
||||
&list);
|
||||
|
||||
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\n34\n:_list_test 18\t| str1| str2| str3\n|\n".as_bytes().to_vec();
|
||||
|
||||
let rendered_packet = packet.render();
|
||||
|
||||
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));
|
||||
}
|
26
rust/tests/test_parser.rs
Normal file
26
rust/tests/test_parser.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
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{
|
||||
operator: ':',
|
||||
name: "_target".to_string(),
|
||||
value: "psyc://ve.symlynx.com/@blog".to_string().into_bytes()
|
||||
};
|
||||
|
||||
let expected2 = 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));
|
||||
}
|
|
@ -166,6 +166,10 @@ psyc_map_lookup(const PsycMap * map, size_t size,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
extern inline intptr_t
|
||||
psyc_map_lookup_int (const PsycMapInt *map, size_t size,
|
||||
const char *key, size_t keylen, PsycBool inherit);
|
||||
|
||||
#ifdef CMDTOOL
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
|
11
src/packet.c
11
src/packet.c
|
@ -21,6 +21,17 @@
|
|||
#include "lib.h"
|
||||
#include <psyc/packet.h>
|
||||
|
||||
extern inline size_t
|
||||
psyc_num_length (size_t n);
|
||||
|
||||
extern inline PsycModifierFlag
|
||||
psyc_modifier_length_check (PsycModifier *m);
|
||||
|
||||
extern inline void
|
||||
psyc_modifier_init (PsycModifier *m, PsycOperator oper,
|
||||
char *name, size_t namelen,
|
||||
char *value, size_t valuelen, PsycModifierFlag flag);
|
||||
|
||||
inline PsycElemFlag
|
||||
psyc_elem_length_check (PsycString *value, const char end)
|
||||
{
|
||||
|
|
107
src/parse.c
107
src/parse.c
|
@ -53,6 +53,65 @@ typedef struct {
|
|||
size_t startc;
|
||||
} ParseState;
|
||||
|
||||
extern inline void
|
||||
psyc_parse_state_init (PsycParseState *state, uint8_t flags);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_buffer_set (PsycParseState *state, const char *buffer, size_t length);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_list_state_init (PsycParseListState *state);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_list_buffer_set (PsycParseListState *state,
|
||||
const char *buffer, size_t length);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_dict_state_init (PsycParseDictState *state);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_dict_buffer_set (PsycParseDictState *state,
|
||||
const char *buffer, size_t length);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_index_state_init (PsycParseIndexState *state);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_index_buffer_set (PsycParseIndexState *state,
|
||||
const char *buffer, size_t length);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_update_state_init (PsycParseUpdateState *state);
|
||||
|
||||
extern inline void
|
||||
psyc_parse_update_buffer_set (PsycParseUpdateState *state,
|
||||
const char *buffer, size_t length);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_content_length (PsycParseState *state);
|
||||
|
||||
extern inline PsycBool
|
||||
psyc_parse_content_length_found (PsycParseState *state);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_value_length (PsycParseState *state);
|
||||
|
||||
extern inline PsycBool
|
||||
psyc_parse_value_length_found (PsycParseState *state);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_cursor (PsycParseState *state);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_buffer_length (PsycParseState *state);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_remaining_length (PsycParseState *state);
|
||||
|
||||
extern inline const char *
|
||||
psyc_parse_remaining_buffer (PsycParseState *state);
|
||||
|
||||
|
||||
/**
|
||||
* Parse variable name or method name.
|
||||
*
|
||||
|
@ -155,7 +214,10 @@ parse_until (ParseState *state, const char end, PsycString *value)
|
|||
* Parse simple or binary variable.
|
||||
* @return PARSE_ERROR or PARSE_SUCCESS
|
||||
*/
|
||||
static inline ParseRC
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
extern inline
|
||||
#endif
|
||||
ParseRC
|
||||
psyc_parse_modifier (PsycParseState *state, char *oper,
|
||||
PsycString *name, PsycString *value)
|
||||
{
|
||||
|
@ -504,7 +566,7 @@ psyc_parse (PsycParseState *state, char *oper,
|
|||
* list-value = %x00-7B / %x7D-FF ; any byte except "|"
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseListRC
|
||||
psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
||||
|
@ -664,6 +726,9 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
|||
* dict-key = %x00-7C / %x7E-FF ; any byte except "{"
|
||||
* dict-value = %x00-7A / %x7C-FF ; any byte except "}"
|
||||
*/
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseDictRC
|
||||
psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
||||
{
|
||||
|
@ -886,7 +951,7 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
|||
}
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseIndexRC
|
||||
psyc_parse_index (PsycParseIndexState *state, PsycString *idx)
|
||||
|
@ -1014,7 +1079,7 @@ psyc_parse_index (PsycParseIndexState *state, PsycString *idx)
|
|||
}
|
||||
|
||||
#ifdef __INLINE_PSYC_PARSE
|
||||
static inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycParseUpdateRC
|
||||
psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value)
|
||||
|
@ -1146,3 +1211,37 @@ psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value)
|
|||
|
||||
return PSYC_PARSE_INDEX_ERROR; // should not be reached
|
||||
}
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_int (const char *value, size_t len, int64_t *n);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_uint (const char *value, size_t len, uint64_t *n);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_list_index (const char *value, size_t len, int64_t *n);
|
||||
|
||||
extern inline PsycBool
|
||||
psyc_is_oper (char g);
|
||||
|
||||
extern inline char
|
||||
psyc_is_numeric (char c);
|
||||
|
||||
extern inline char
|
||||
psyc_is_alpha (char c);
|
||||
|
||||
extern inline char
|
||||
psyc_is_alpha_numeric (char c);
|
||||
|
||||
extern inline char
|
||||
psyc_is_kw_char (char c);
|
||||
|
||||
extern inline char
|
||||
psyc_is_name_char (char c);
|
||||
|
||||
extern inline char
|
||||
psyc_is_host_char (char c);
|
||||
|
||||
extern inline size_t
|
||||
psyc_parse_keyword (const char *data, size_t len);
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ psyc_render_dict_key (PsycDictKey *elem, char *buffer, size_t buflen)
|
|||
}
|
||||
|
||||
#ifdef __INLINE_PSYC_RENDER
|
||||
static inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycRenderRC
|
||||
psyc_render_list (PsycList *list, char *buffer, size_t buflen)
|
||||
|
@ -162,7 +162,7 @@ psyc_render_modifier (PsycModifier *mod, char *buffer)
|
|||
}
|
||||
|
||||
#ifdef __INLINE_PSYC_RENDER
|
||||
static inline
|
||||
extern inline
|
||||
#endif
|
||||
PsycRenderRC
|
||||
psyc_render (PsycPacket *p, char *buffer, size_t buflen)
|
||||
|
|
18
src/text.c
18
src/text.c
|
@ -25,6 +25,24 @@ const PsycTemplates psyc_templates = { .s = {
|
|||
#include "templates.h"
|
||||
}};
|
||||
|
||||
extern inline void
|
||||
psyc_text_state_init (PsycTextState *state,
|
||||
char *tmpl, size_t tmplen,
|
||||
char *buffer, size_t buflen);
|
||||
|
||||
extern inline void
|
||||
psyc_text_state_init_custom (PsycTextState *state,
|
||||
char *tmpl, size_t tmplen,
|
||||
char *buffer, size_t buflen,
|
||||
char *ope, size_t opelen,
|
||||
char *clo, size_t clolen);
|
||||
|
||||
extern inline void
|
||||
psyc_text_buffer_set (PsycTextState *state, char *buffer, size_t length);
|
||||
|
||||
extern inline size_t
|
||||
psyc_text_bytes_written (PsycTextState *state);
|
||||
|
||||
PsycTextRC
|
||||
psyc_text (PsycTextState *state, PsycTextCB get_value, void *get_value_cls)
|
||||
{
|
||||
|
|
|
@ -195,3 +195,6 @@ psyc_uniform_parse (PsycUniform *uni, const char *buffer, size_t length)
|
|||
uni->valid = 1;
|
||||
return uni->type;
|
||||
}
|
||||
|
||||
extern inline int
|
||||
psyc_entity_type (char entity);
|
||||
|
|
|
@ -104,6 +104,15 @@ const PsycMapInt psyc_methods[] = {
|
|||
};
|
||||
const size_t psyc_methods_num = PSYC_NUM_ELEM(psyc_methods);
|
||||
|
||||
extern inline PsycRoutingVar
|
||||
psyc_var_routing (const char *name, size_t len);
|
||||
|
||||
extern inline PsycType
|
||||
psyc_var_type (const char *name, size_t len);
|
||||
|
||||
extern inline PsycBool
|
||||
psyc_var_is_list (const char *name, size_t len);
|
||||
|
||||
/**
|
||||
* Get the method, its family and its flags.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue