mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
Merge remote-tracking branch 'lurchi/master'
This commit is contained in:
commit
2e82f31f9d
24 changed files with 864 additions and 166 deletions
|
@ -4,3 +4,6 @@ version = "1.0.0"
|
|||
links = "psyc"
|
||||
build = "build.rs"
|
||||
description = "rust bindings for libpsyc"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.7.0"
|
||||
|
|
36
rust/src/keyword.rs
Normal file
36
rust/src/keyword.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use std::os::raw::{c_char, c_int};
|
||||
|
||||
extern "C" {
|
||||
fn psyc_inherits(sho: *const c_char,
|
||||
slen: usize,
|
||||
lon: *const c_char,
|
||||
llen: usize)
|
||||
-> c_int;
|
||||
fn psyc_matches(sho: *const c_char,
|
||||
slen: usize,
|
||||
lon: *const c_char,
|
||||
llen: usize)
|
||||
-> c_int;
|
||||
}
|
||||
|
||||
pub trait Keyword {
|
||||
fn keyword(&self) -> &[u8];
|
||||
|
||||
fn inherits(&self, other: &[u8]) -> bool {
|
||||
let keyword_ptr = self.keyword().as_ptr() as *const c_char;
|
||||
let other_ptr = other.as_ptr() as *const c_char;
|
||||
let result = unsafe {
|
||||
psyc_inherits(other_ptr, other.len(), keyword_ptr, self.keyword().len())
|
||||
};
|
||||
result == 0
|
||||
}
|
||||
|
||||
fn matches(&self, other: &[u8]) -> bool {
|
||||
let keyword_ptr = self.keyword().as_ptr() as *const c_char;
|
||||
let other_ptr = other.as_ptr() as *const c_char;
|
||||
let result = unsafe {
|
||||
psyc_matches(other_ptr, other.len(), keyword_ptr, self.keyword().len())
|
||||
};
|
||||
result == 0
|
||||
}
|
||||
}
|
|
@ -1,12 +1,33 @@
|
|||
#![allow(dead_code)]
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
mod keyword;
|
||||
mod method_types;
|
||||
mod packet_types;
|
||||
mod parser_types;
|
||||
mod types;
|
||||
mod uniform_types;
|
||||
mod util;
|
||||
pub mod parser_types;
|
||||
pub mod packet_types;
|
||||
mod variable_types;
|
||||
pub mod method;
|
||||
pub mod parser;
|
||||
pub mod packet;
|
||||
pub mod packet_id;
|
||||
pub mod uniform;
|
||||
pub mod variable;
|
||||
|
||||
pub use parser::*;
|
||||
pub use packet::*;
|
||||
pub use packet_id::*;
|
||||
pub use keyword::Keyword;
|
||||
pub use method::Method;
|
||||
pub use method_types::{PsycMethod, MethodInfo, PsycMethodFlags};
|
||||
pub use method_types::{PSYC_METHOD_TEMPLATE, PSYC_METHOD_REPLY, PSYC_METHOD_VISIBLE, PSYC_METHOD_LOGGABLE, PSYC_METHOD_MANUAL};
|
||||
pub use parser::{PsycParser, PsycListParser, Parser};
|
||||
pub use parser_types::{PsycParserResult, PsycListParserResult, PsycParserError, PsycListParserError};
|
||||
pub use packet::{PsycList, PsycModifier, PsycPacket};
|
||||
pub use packet_id::PacketId;
|
||||
pub use packet_types::PacketRenderError;
|
||||
pub use uniform::Uniform;
|
||||
pub use uniform_types::{UniformParseError, PsycScheme, PsycEntity};
|
||||
pub use packet_types::{PsycOperator, PsycStateOp};
|
||||
pub use variable::{RoutingVariable, EntityVariable, Variable};
|
||||
pub use variable_types::{PsycRoutingVar, PsycType};
|
||||
|
|
45
rust/src/method.rs
Normal file
45
rust/src/method.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use method_types::{PsycMethod, PsycMethodFlags, MethodInfo};
|
||||
use keyword::Keyword;
|
||||
use std::mem;
|
||||
use std::os::raw::{c_char, c_uint};
|
||||
|
||||
extern "C" {
|
||||
fn psyc_method(method: *const c_char,
|
||||
methodlen: usize,
|
||||
family: *mut PsycMethod,
|
||||
flag: *mut c_uint)
|
||||
-> PsycMethod;
|
||||
}
|
||||
|
||||
pub struct Method<'a> {
|
||||
pub method: &'a [u8]
|
||||
}
|
||||
|
||||
impl<'a> Keyword for Method<'a> {
|
||||
fn keyword(&self) -> &[u8] {
|
||||
self.method
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Method<'a> {
|
||||
pub fn lookup(&self) -> MethodInfo {
|
||||
let method_ptr = self.method.as_ptr() as *const c_char;
|
||||
let lookup_result: PsycMethod;
|
||||
let mut family: PsycMethod;
|
||||
let mut flags: PsycMethodFlags;
|
||||
unsafe {
|
||||
family = mem::uninitialized();
|
||||
flags = mem::uninitialized();
|
||||
let flags_ptr = &mut flags as *mut PsycMethodFlags as *mut c_uint;
|
||||
lookup_result = psyc_method(method_ptr,
|
||||
self.method.len(),
|
||||
&mut family as *mut PsycMethod,
|
||||
flags_ptr)
|
||||
}
|
||||
MethodInfo {
|
||||
lookup_result: lookup_result,
|
||||
family: family,
|
||||
flags: flags
|
||||
}
|
||||
}
|
||||
}
|
60
rust/src/method_types.rs
Normal file
60
rust/src/method_types.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
use std::os::raw::c_int;
|
||||
|
||||
bitflags! {
|
||||
pub flags PsycMethodFlags: c_int {
|
||||
const PSYC_METHOD_TEMPLATE = 1 << 0,
|
||||
const PSYC_METHOD_REPLY = 1 << 1,
|
||||
const PSYC_METHOD_VISIBLE = 1 << 2,
|
||||
const PSYC_METHOD_LOGGABLE = 1 << 3,
|
||||
const PSYC_METHOD_MANUAL = 1 << 4
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycMethod {
|
||||
PSYC_MC_UNKNOWN,
|
||||
|
||||
PSYC_MC_CONVERSE,
|
||||
PSYC_MC_DATA,
|
||||
PSYC_MC_ECHO,
|
||||
PSYC_MC_ECHO_CONTEXT_ENTER,
|
||||
PSYC_MC_ECHO_CONTEXT_LEAVE,
|
||||
PSYC_MC_ECHO_HELLO,
|
||||
PSYC_MC_ERROR,
|
||||
PSYC_MC_FAILURE,
|
||||
PSYC_MC_FAILURE_ALIAS_NONEXISTANT,
|
||||
PSYC_MC_FAILURE_ALIAS_UNAVAILABLE,
|
||||
PSYC_MC_INFO,
|
||||
PSYC_MC_MESSAGE, // deprecated, use _converse
|
||||
PSYC_MC_MESSAGE_ACTION, // deprecated, use _converse
|
||||
PSYC_MC_NOTICE,
|
||||
PSYC_MC_NOTICE_ALIAS_ADD,
|
||||
PSYC_MC_NOTICE_ALIAS_CHANGE,
|
||||
PSYC_MC_NOTICE_ALIAS_REMOVE,
|
||||
PSYC_MC_NOTICE_CONTEXT_ENTER,
|
||||
PSYC_MC_NOTICE_CONTEXT_LEAVE,
|
||||
PSYC_MC_NOTICE_FRIENDSHIP,
|
||||
PSYC_MC_NOTICE_LINK,
|
||||
PSYC_MC_NOTICE_PEER_CONNECT,
|
||||
PSYC_MC_NOTICE_PEER_DISCONNECT,
|
||||
PSYC_MC_NOTICE_SET,
|
||||
PSYC_MC_NOTICE_UNLINK,
|
||||
PSYC_MC_REQUEST,
|
||||
PSYC_MC_REQUEST_CONTEXT_ENTER,
|
||||
PSYC_MC_REQUEST_CONTEXT_LEAVE,
|
||||
PSYC_MC_REQUEST_FRIENDSHIP,
|
||||
PSYC_MC_STATUS,
|
||||
PSYC_MC_STATUS_CONTEXTS_ENTERED,
|
||||
PSYC_MC_STATUS_HELLO,
|
||||
PSYC_MC_WARNING,
|
||||
|
||||
PSYC_METHODS_NUM,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct MethodInfo {
|
||||
pub lookup_result: PsycMethod,
|
||||
pub family: PsycMethod,
|
||||
pub flags: PsycMethodFlags
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use types::*;
|
||||
use types::PsycString;
|
||||
use packet_types::*;
|
||||
use packet_id::*;
|
||||
use packet_id::PacketId;
|
||||
use util;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
@ -70,14 +70,6 @@ pub struct PsycPacket<'a> {
|
|||
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 {
|
||||
|
@ -212,7 +204,7 @@ impl<'a> PsycPacket<'a> {
|
|||
}
|
||||
|
||||
///
|
||||
pub fn render(&self) -> Result<Vec<u8>, PsycRenderError> {
|
||||
pub fn render(&self) -> Result<Vec<u8>, PacketRenderError> {
|
||||
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;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use packet_types::{RawPsycList, PsycElem};
|
||||
use parser::{PsycListParser, PsycListParserResult};
|
||||
use parser::PsycListParser;
|
||||
use parser_types::PsycListParserResult;
|
||||
use util;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
|
|
@ -33,6 +33,16 @@ pub enum PsycPacketFlag {
|
|||
PSYC_PACKET_NO_LENGTH = 2,
|
||||
}
|
||||
|
||||
#[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,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum PsycOperator {
|
||||
|
@ -51,16 +61,6 @@ pub enum PsycStateOp {
|
|||
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,
|
||||
|
@ -116,3 +116,11 @@ pub enum PsycRenderRC {
|
|||
/// Packet is rendered successfully in the buffer.
|
||||
PSYC_RENDER_SUCCESS = 0,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PacketRenderError {
|
||||
MethodMissing = PsycRenderRC::PSYC_RENDER_ERROR_METHOD_MISSING as _,
|
||||
ModifierNameMissing = PsycRenderRC::PSYC_RENDER_ERROR_MODIFIER_NAME_MISSING as _,
|
||||
GenericError = PsycRenderRC::PSYC_RENDER_ERROR as _
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use types::*;
|
||||
use types::PsycString;
|
||||
use parser_types::*;
|
||||
use util;
|
||||
use std::mem;
|
||||
|
@ -31,93 +31,6 @@ pub struct PsycListParser {
|
|||
state: PsycParseListState
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycParserResult<'a> {
|
||||
StateSync,
|
||||
StateReset,
|
||||
Complete,
|
||||
InsufficientData,
|
||||
RoutingModifier {
|
||||
operator: char,
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
EntityModifier {
|
||||
operator: char,
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
EntityModifierStart {
|
||||
operator: char,
|
||||
name: &'a [u8],
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
EntityModifierCont {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
EntityModifierEnd {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
Body {
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
BodyStart {
|
||||
name: &'a [u8],
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
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)]
|
||||
#[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 _,
|
||||
}
|
||||
|
||||
#[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 {
|
||||
|
@ -207,29 +120,29 @@ impl PsycParser {
|
|||
|
||||
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)
|
||||
method: util::cstring_to_slice(name.data, name.length),
|
||||
data: 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)
|
||||
method: util::cstring_to_slice(name.data, name.length),
|
||||
data_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)
|
||||
data_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)
|
||||
data_part: util::cstring_to_slice(value.data, value.length)
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
@ -300,21 +213,24 @@ impl PsycListParser {
|
|||
|
||||
PsycParseListRC::PSYC_PARSE_LIST_ELEM_START => {
|
||||
let result = PsycListParserResult::ListElementStart {
|
||||
value_part: util::cstring_to_slice(element.data, element.length)
|
||||
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)
|
||||
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)
|
||||
value_part: util::cstring_to_slice(element.data,
|
||||
element.length)
|
||||
};
|
||||
return Ok(result)
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
use types::*;
|
||||
use types::PsycString;
|
||||
|
||||
enum PsycPart { }
|
||||
enum PsycListPart { }
|
||||
|
@ -35,39 +35,6 @@ pub struct PsycParseListState {
|
|||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseDictState {
|
||||
pub buffer: PsycString,
|
||||
pub cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
part: PsycDictPart,
|
||||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseIndexState {
|
||||
buffer: PsycString,
|
||||
pub cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
part: PsycIndexPart,
|
||||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PsycParseUpdateState {
|
||||
buffer: PsycString,
|
||||
pub cursor: usize,
|
||||
startc: usize,
|
||||
elemlen: usize,
|
||||
elem_parsed: usize,
|
||||
part: PsycUpdatePart,
|
||||
elemlen_found: u8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycParseFlag {
|
||||
/// Default Flag. Parse everything.
|
||||
|
@ -298,6 +265,89 @@ pub enum PsycParseUpdateRC {
|
|||
PSYC_PARSE_UPDATE_END = 27,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycParserResult<'a> {
|
||||
StateSync,
|
||||
StateReset,
|
||||
Complete,
|
||||
InsufficientData,
|
||||
RoutingModifier {
|
||||
operator: char,
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
EntityModifier {
|
||||
operator: char,
|
||||
name: &'a [u8],
|
||||
value: &'a [u8]
|
||||
},
|
||||
EntityModifierStart {
|
||||
operator: char,
|
||||
name: &'a [u8],
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
EntityModifierCont {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
EntityModifierEnd {
|
||||
value_part: &'a [u8]
|
||||
},
|
||||
Body {
|
||||
method: &'a [u8],
|
||||
data: &'a [u8]
|
||||
},
|
||||
BodyStart {
|
||||
method: &'a [u8],
|
||||
data_part: &'a [u8]
|
||||
},
|
||||
BodyCont {
|
||||
data_part: &'a [u8]
|
||||
},
|
||||
BodyEnd {
|
||||
data_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)]
|
||||
#[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 _,
|
||||
}
|
||||
|
||||
#[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 _,
|
||||
}
|
||||
|
|
|
@ -1,9 +1,30 @@
|
|||
use std::os::raw::c_char;
|
||||
|
||||
/// Return code: OK/error.
|
||||
#[repr(C)]
|
||||
pub enum PsycRC {
|
||||
PSYC_OK = 1,
|
||||
PSYC_ERROR = -1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycBool {
|
||||
PSYC_FALSE = 0,
|
||||
PSYC_TRUE = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct PsycString {
|
||||
pub length: usize,
|
||||
pub data: *const c_char
|
||||
}
|
||||
|
||||
|
||||
impl PsycBool {
|
||||
pub fn to_bool(self) -> bool {
|
||||
match self {
|
||||
PsycBool::PSYC_FALSE => false,
|
||||
PsycBool::PSYC_TRUE => true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
188
rust/src/uniform.rs
Normal file
188
rust/src/uniform.rs
Normal file
|
@ -0,0 +1,188 @@
|
|||
use types::PsycRC;
|
||||
use uniform_types::*;
|
||||
use std::os::raw::c_char;
|
||||
use std::os::raw::c_int;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use util;
|
||||
|
||||
extern "C" {
|
||||
fn psyc_uniform_parse(uniform: *mut PsycUniform,
|
||||
buffer: *const c_char,
|
||||
length: usize)
|
||||
-> c_int;
|
||||
|
||||
fn psyc_entity_type(entity: c_char) -> c_int;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Uniform<'a> {
|
||||
uniform: PsycUniform,
|
||||
phantom: PhantomData<&'a Vec<u8>>
|
||||
}
|
||||
|
||||
impl<'a> Uniform<'a> {
|
||||
pub fn from_bytes(buffer: &'a [u8]) -> Result<Self, UniformParseError> {
|
||||
let buffer_ptr = buffer.as_ptr() as *const c_char;
|
||||
let mut uniform: PsycUniform;
|
||||
unsafe {
|
||||
uniform = mem::zeroed();
|
||||
let uniform_ptr = &mut uniform as *mut PsycUniform;
|
||||
let parse_result = psyc_uniform_parse(uniform_ptr, buffer_ptr, buffer.len());
|
||||
if parse_result < PsycScheme::PSYC_SCHEME_PSYC as _ {
|
||||
return Err(mem::transmute(parse_result))
|
||||
}
|
||||
}
|
||||
let result = Uniform {
|
||||
uniform: uniform,
|
||||
phantom: PhantomData
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
//pub fn from_raw_uniform(uniform: PsycUniform) -> Self {
|
||||
// UniformRef {
|
||||
// uniform: uniform,
|
||||
// phantom: PhantomData
|
||||
// }
|
||||
//}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.uniform.valid
|
||||
}
|
||||
|
||||
pub fn entity(&self) -> PsycEntity<'a> {
|
||||
match self.resource() {
|
||||
"" => PsycEntity::Root,
|
||||
_resource => unsafe {
|
||||
let type_specifier = *self.uniform.resource.data;
|
||||
let entity_type_int = psyc_entity_type(type_specifier);
|
||||
if entity_type_int == PsycRC::PSYC_ERROR as c_int {
|
||||
return PsycEntity::Unknown {
|
||||
object: self.resource(),
|
||||
channel: self.channel()
|
||||
}
|
||||
}
|
||||
|
||||
let entity_type: PsycEntityType = mem::transmute(entity_type_int);
|
||||
|
||||
match entity_type {
|
||||
PsycEntityType::PSYC_ENTITY_PERSON => PsycEntity::Person {
|
||||
name: self.nick(),
|
||||
channel: self.channel()
|
||||
},
|
||||
|
||||
PsycEntityType::PSYC_ENTITY_PLACE => PsycEntity::Place {
|
||||
name: self.nick(),
|
||||
channel: self.channel()
|
||||
},
|
||||
|
||||
PsycEntityType::PSYC_ENTITY_SERVICE => PsycEntity::Service {
|
||||
name: self.nick(),
|
||||
channel: self.channel()
|
||||
},
|
||||
|
||||
PsycEntityType::PSYC_ENTITY_ROOT => PsycEntity::Root
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scheme(&self) -> PsycScheme {
|
||||
self.uniform.uniform_type
|
||||
}
|
||||
|
||||
pub fn password(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.pass.data, self.uniform.pass.length)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn host(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.host.data, self.uniform.host.length)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn port(&self) -> Option<i32> {
|
||||
let slice: &'a str;
|
||||
unsafe {
|
||||
slice = util::cstring_to_str(self.uniform.port.data,
|
||||
self.uniform.port.length)
|
||||
}
|
||||
match slice {
|
||||
"" => None,
|
||||
s => Some(s.parse::<i32>().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transport(&self) -> Option<PsycTransport> {
|
||||
let slice: &'a str;
|
||||
unsafe {
|
||||
slice = util::cstring_to_str(self.uniform.transport.data,
|
||||
self.uniform.transport.length)
|
||||
}
|
||||
match slice {
|
||||
"" => None,
|
||||
tcp if tcp.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_TCP as u8 =>
|
||||
Some(PsycTransport::PSYC_TRANSPORT_TCP),
|
||||
udp if udp.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_UDP as u8 =>
|
||||
Some(PsycTransport::PSYC_TRANSPORT_UDP),
|
||||
tls if tls.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_TLS as u8 =>
|
||||
Some(PsycTransport::PSYC_TRANSPORT_TLS),
|
||||
gnunet if gnunet.as_bytes()[0] == PsycTransport::PSYC_TRANSPORT_GNUNET as u8 =>
|
||||
Some(PsycTransport::PSYC_TRANSPORT_GNUNET),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resource(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.resource.data,
|
||||
self.uniform.resource.length)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.query.data, self.uniform.query.length)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn full(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.full.data, self.uniform.full.length)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.body.data, self.uniform.body.length)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.root.data, self.uniform.root.length)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.path.data, self.uniform.path.length)
|
||||
}
|
||||
}
|
||||
|
||||
/* private functions */
|
||||
fn nick(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.nick.data, self.uniform.nick.length)
|
||||
}
|
||||
}
|
||||
|
||||
fn channel(&self) -> &'a str {
|
||||
unsafe {
|
||||
util::cstring_to_str(self.uniform.channel.data, self.uniform.channel.length)
|
||||
}
|
||||
}
|
||||
}
|
88
rust/src/uniform_types.rs
Normal file
88
rust/src/uniform_types.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use types::PsycString;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycEntity<'a> {
|
||||
Root,
|
||||
Person {
|
||||
name: &'a str,
|
||||
channel: &'a str
|
||||
},
|
||||
Place {
|
||||
name: &'a str,
|
||||
channel: &'a str
|
||||
},
|
||||
Service {
|
||||
name: &'a str,
|
||||
channel: &'a str
|
||||
},
|
||||
Unknown {
|
||||
object: &'a str,
|
||||
channel: &'a str
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub enum PsycScheme {
|
||||
PSYC_SCHEME_PSYC = 0,
|
||||
PSYC_SCHEME_IRC = 1,
|
||||
PSYC_SCHEME_XMPP = 2,
|
||||
PSYC_SCHEME_SIP = 3
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycEntityType {
|
||||
PSYC_ENTITY_ROOT = 0,
|
||||
PSYC_ENTITY_PERSON = '~' as _,
|
||||
PSYC_ENTITY_PLACE = '@' as _,
|
||||
PSYC_ENTITY_SERVICE = '$' as _
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub enum PsycTransport {
|
||||
PSYC_TRANSPORT_TCP = 'c' as _,
|
||||
PSYC_TRANSPORT_UDP = 'd' as _,
|
||||
PSYC_TRANSPORT_TLS = 's' as _,
|
||||
PSYC_TRANSPORT_GNUNET = 'g' as _,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub enum UniformParseError {
|
||||
PSYC_PARSE_UNIFORM_INVALID_SLASHES = -7,
|
||||
PSYC_PARSE_UNIFORM_INVALID_CHANNEL = -6,
|
||||
PSYC_PARSE_UNIFORM_INVALID_RESOURCE = -5,
|
||||
PSYC_PARSE_UNIFORM_INVALID_TRANSPORT = -4,
|
||||
PSYC_PARSE_UNIFORM_INVALID_PORT = -3,
|
||||
PSYC_PARSE_UNIFORM_INVALID_HOST = -2,
|
||||
PSYC_PARSE_UNIFORM_INVALID_SCHEME = -1,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct PsycUniform {
|
||||
pub valid: bool,
|
||||
pub uniform_type: PsycScheme,
|
||||
pub scheme: PsycString,
|
||||
pub user: PsycString,
|
||||
pub pass: PsycString,
|
||||
pub host: PsycString,
|
||||
pub port: PsycString,
|
||||
pub transport: PsycString,
|
||||
pub resource: PsycString,
|
||||
pub query: PsycString,
|
||||
pub channel: PsycString,
|
||||
|
||||
pub full: PsycString,
|
||||
pub body: PsycString,
|
||||
pub user_host: PsycString,
|
||||
pub host_port: PsycString,
|
||||
pub root: PsycString,
|
||||
pub entity: PsycString,
|
||||
pub slashes: PsycString,
|
||||
pub slash: PsycString,
|
||||
pub path: PsycString,
|
||||
pub nick: PsycString
|
||||
}
|
|
@ -1,13 +1,23 @@
|
|||
use packet_types::{RawPsycList, PsycRenderRC};
|
||||
use std::slice;
|
||||
use std::os::raw::c_char;
|
||||
use std::str;
|
||||
|
||||
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 cstring_to_slice<'a>(cstring: *const c_char, length: usize)
|
||||
-> &'a[u8] {
|
||||
match cstring {
|
||||
p if p.is_null() => &[],
|
||||
_ => slice::from_raw_parts(cstring as *const u8, length)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn cstring_to_str<'a>(cstring: *const c_char, length: usize)
|
||||
-> &'a str {
|
||||
str::from_utf8_unchecked(cstring_to_slice(cstring, length))
|
||||
}
|
||||
|
||||
pub unsafe fn render_list(list: &RawPsycList) -> Vec<u8> {
|
||||
|
|
69
rust/src/variable.rs
Normal file
69
rust/src/variable.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
use types::PsycBool;
|
||||
use variable_types::*;
|
||||
use keyword::Keyword;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
extern "C" {
|
||||
fn psyc_var_routing(name: *const c_char, len: usize) -> PsycRoutingVar;
|
||||
fn psyc_var_type(name: *const c_char, len: usize) -> PsycType;
|
||||
fn psyc_var_is_list(name: *const c_char, len: usize) -> PsycBool;
|
||||
}
|
||||
|
||||
pub struct RoutingVariable<'a> {
|
||||
pub variable: &'a [u8]
|
||||
}
|
||||
|
||||
pub struct EntityVariable<'a> {
|
||||
pub variable: &'a [u8]
|
||||
}
|
||||
|
||||
impl<'a> Variable for RoutingVariable<'a> {
|
||||
fn variable(&self) -> &[u8] {
|
||||
self.variable
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Variable for EntityVariable<'a> {
|
||||
fn variable(&self) -> &[u8] {
|
||||
self.variable
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Keyword for RoutingVariable<'a> {
|
||||
fn keyword(&self) -> &[u8] {
|
||||
self.variable
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Keyword for EntityVariable<'a> {
|
||||
fn keyword(&self) -> &[u8] {
|
||||
self.variable
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RoutingVariable<'a> {
|
||||
pub fn lookup(&self) -> PsycRoutingVar {
|
||||
let variable_ptr = self.variable().as_ptr() as *const c_char;
|
||||
unsafe {
|
||||
psyc_var_routing(variable_ptr, self.variable().len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Variable {
|
||||
fn variable(&self) -> &[u8];
|
||||
|
||||
fn datatype(&self) -> PsycType {
|
||||
let variable_ptr = self.variable().as_ptr() as *const c_char;
|
||||
unsafe {
|
||||
psyc_var_type(variable_ptr, self.variable().len())
|
||||
}
|
||||
}
|
||||
|
||||
fn is_list(&self) -> bool {
|
||||
let variable_ptr = self.variable().as_ptr() as *const c_char;
|
||||
unsafe {
|
||||
psyc_var_is_list(variable_ptr, self.variable().len()).to_bool()
|
||||
}
|
||||
}
|
||||
}
|
39
rust/src/variable_types.rs
Normal file
39
rust/src/variable_types.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycRoutingVar {
|
||||
PSYC_RVAR_UNKNOWN,
|
||||
|
||||
PSYC_RVAR_AMOUNT_FRAGMENTS,
|
||||
PSYC_RVAR_CONTEXT,
|
||||
PSYC_RVAR_COUNTER,
|
||||
PSYC_RVAR_FRAGMENT,
|
||||
PSYC_RVAR_SOURCE,
|
||||
PSYC_RVAR_SOURCE_RELAY,
|
||||
PSYC_RVAR_TAG,
|
||||
PSYC_RVAR_TAG_RELAY,
|
||||
PSYC_RVAR_TARGET,
|
||||
PSYC_RVAR_TARGET_RELAY,
|
||||
|
||||
PSYC_RVARS_NUM,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum PsycType {
|
||||
PSYC_TYPE_UNKNOWN,
|
||||
PSYC_TYPE_AMOUNT,
|
||||
PSYC_TYPE_COLOR,
|
||||
PSYC_TYPE_COUNTER,
|
||||
PSYC_TYPE_DATE,
|
||||
PSYC_TYPE_DEGREE,
|
||||
PSYC_TYPE_DICT,
|
||||
PSYC_TYPE_ENTITY,
|
||||
PSYC_TYPE_FLAG,
|
||||
PSYC_TYPE_LANGUAGE,
|
||||
PSYC_TYPE_LIST,
|
||||
PSYC_TYPE_NICK,
|
||||
PSYC_TYPE_PAGE,
|
||||
PSYC_TYPE_STRUCT,
|
||||
PSYC_TYPE_TIME,
|
||||
PSYC_TYPE_UNIFORM,
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
extern crate psyc;
|
||||
use psyc::parser::*;
|
||||
use psyc::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
|
|
38
rust/tests/test_method.rs
Normal file
38
rust/tests/test_method.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
extern crate psyc;
|
||||
use psyc::*;
|
||||
|
||||
#[test]
|
||||
fn test_method_matching() {
|
||||
let m = Method {method: b"_notice_context_enter"};
|
||||
|
||||
assert!(m.inherits(b"_notice_context"));
|
||||
assert!(m.matches(b"_context"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_lookup() {
|
||||
let m = Method {method: b"_notice_context_enter"};
|
||||
|
||||
let expected_flags = PSYC_METHOD_TEMPLATE |
|
||||
PSYC_METHOD_VISIBLE |
|
||||
PSYC_METHOD_LOGGABLE;
|
||||
|
||||
assert_eq!(m.lookup(),
|
||||
MethodInfo {
|
||||
lookup_result: PsycMethod::PSYC_MC_NOTICE_CONTEXT_ENTER,
|
||||
family: PsycMethod::PSYC_MC_NOTICE,
|
||||
flags: expected_flags
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lookup_empty() {
|
||||
let m = Method {method: b""};
|
||||
|
||||
assert_eq!(m.lookup(),
|
||||
MethodInfo {
|
||||
lookup_result: PsycMethod::PSYC_MC_UNKNOWN,
|
||||
family: PsycMethod::PSYC_MC_UNKNOWN,
|
||||
flags: PsycMethodFlags::empty()
|
||||
});
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
extern crate psyc;
|
||||
|
||||
use psyc::*;
|
||||
use psyc::packet_types::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_render() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
extern crate psyc;
|
||||
|
||||
use psyc::*;
|
||||
use psyc::packet_types::*;
|
||||
|
||||
#[test]
|
||||
fn test_packet_id() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
extern crate psyc;
|
||||
use psyc::parser::*;
|
||||
use psyc::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
|
|
71
rust/tests/test_uniform.rs
Normal file
71
rust/tests/test_uniform.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
extern crate psyc;
|
||||
|
||||
use psyc::*;
|
||||
|
||||
#[test]
|
||||
fn test_person() {
|
||||
let uniform = Uniform::from_bytes(b"psyc://ve.symlynx.com:4404/~lurchi");
|
||||
|
||||
let unwrapped = uniform.unwrap();
|
||||
let entity = unwrapped.entity();
|
||||
|
||||
assert!(unwrapped.is_valid());
|
||||
assert_eq!(unwrapped.full(), "psyc://ve.symlynx.com:4404/~lurchi");
|
||||
assert_eq!(unwrapped.scheme(), PsycScheme::PSYC_SCHEME_PSYC);
|
||||
assert_eq!(unwrapped.host(), "ve.symlynx.com");
|
||||
assert_eq!(unwrapped.port(), Some(4404));
|
||||
assert_eq!(unwrapped.resource(), "~lurchi");
|
||||
|
||||
assert_eq!(entity, PsycEntity::Person {name: "lurchi", channel: ""});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_place() {
|
||||
let uniform = Uniform::from_bytes(b"psyc://ve.symlynx.com/@_strange_place");
|
||||
|
||||
let unwrapped = uniform.unwrap();
|
||||
|
||||
assert!(unwrapped.is_valid());
|
||||
assert_eq!(unwrapped.resource(), "@_strange_place");
|
||||
assert_eq!(unwrapped.entity(),
|
||||
PsycEntity::Place {name: "_strange_place", channel: ""});
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_host_only() {
|
||||
let uniform = Uniform::from_bytes(b"psyc://ve.symlynx.com");
|
||||
|
||||
let unwrapped = uniform.unwrap();
|
||||
|
||||
assert!(unwrapped.is_valid());
|
||||
assert_eq!(unwrapped.resource(), "");
|
||||
assert_eq!(unwrapped.entity(), PsycEntity::Root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unknown_resource() {
|
||||
let uniform = Uniform::from_bytes(b"psyc://ve.symlynx.com/%unknown#a");
|
||||
|
||||
let unwrapped = uniform.unwrap();
|
||||
|
||||
assert!(unwrapped.is_valid());
|
||||
assert_eq!(unwrapped.entity(),
|
||||
PsycEntity::Unknown {object: "%unknown", channel: "a"});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_channel() {
|
||||
let uniform = Uniform::from_bytes(b"psyc://ve.symlynx.com:4404/~lurchi#test");
|
||||
|
||||
let unwrapped = uniform.unwrap();
|
||||
|
||||
assert_eq!(unwrapped.entity(), PsycEntity::Person {name: "lurchi", channel: "test"});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let uniform = Uniform::from_bytes(b"");
|
||||
assert_eq!(uniform.unwrap_err(),
|
||||
UniformParseError::PSYC_PARSE_UNIFORM_INVALID_SCHEME);
|
||||
}
|
44
rust/tests/test_variable.rs
Normal file
44
rust/tests/test_variable.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
extern crate psyc;
|
||||
use psyc::*;
|
||||
|
||||
#[test]
|
||||
fn test_routing_variable() {
|
||||
let r = RoutingVariable {variable: b"_amount_fragments"};
|
||||
|
||||
assert_eq!(r.lookup(), PsycRoutingVar::PSYC_RVAR_AMOUNT_FRAGMENTS);
|
||||
assert_eq!(r.datatype(), PsycType::PSYC_TYPE_AMOUNT);
|
||||
assert_eq!(r.is_list(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entity_variable() {
|
||||
let e = EntityVariable {variable: b"_nick_family"};
|
||||
|
||||
assert_eq!(e.datatype(), PsycType::PSYC_TYPE_NICK);
|
||||
assert!(! e.is_list());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let r = RoutingVariable {variable: b""};
|
||||
|
||||
assert_eq!(r.lookup(), PsycRoutingVar::PSYC_RVAR_UNKNOWN);
|
||||
assert_eq!(r.datatype(), PsycType::PSYC_TYPE_UNKNOWN);
|
||||
assert!(! r.is_list());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inherits() {
|
||||
let r = RoutingVariable {variable: b"_target_relay"};
|
||||
|
||||
assert!(r.inherits(b"_target"));
|
||||
assert!(! r.inherits(b""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_matches() {
|
||||
let r = RoutingVariable {variable: b"_target_relay"};
|
||||
|
||||
assert!(r.matches(b"_relay"));
|
||||
assert!(! r.matches(b""));
|
||||
}
|
|
@ -184,7 +184,7 @@ psyc_uniform_parse (PsycUniform *uni, const char *buffer, size_t length)
|
|||
}
|
||||
|
||||
if (uni->resource.length)
|
||||
uni->nick = PSYC_STRING(uni->resource.data + 1, uni->resource.length);
|
||||
uni->nick = PSYC_STRING(uni->resource.data + 1, uni->resource.length - 1);
|
||||
|
||||
} else
|
||||
return PSYC_PARSE_UNIFORM_INVALID_SCHEME;
|
||||
|
|
Loading…
Reference in a new issue