mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
add variable and method modules
This commit is contained in:
parent
27dc1292ba
commit
749d0abf79
10 changed files with 365 additions and 4 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,17 +1,30 @@
|
|||
#![allow(dead_code)]
|
||||
mod types;
|
||||
mod util;
|
||||
mod uniform_types;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
mod keyword;
|
||||
mod method_types;
|
||||
mod packet_types;
|
||||
mod parser_types;
|
||||
mod types;
|
||||
mod uniform_types;
|
||||
mod util;
|
||||
mod variable_types;
|
||||
pub mod method;
|
||||
pub mod parser;
|
||||
pub mod packet;
|
||||
pub mod packet_id;
|
||||
pub mod uniform;
|
||||
pub mod variable;
|
||||
|
||||
pub use keyword::Keyword;
|
||||
pub use method::Method;
|
||||
pub use method_types::*;
|
||||
pub use parser::*;
|
||||
pub use packet::*;
|
||||
pub use packet_id::*;
|
||||
pub use uniform::*;
|
||||
pub use uniform_types::{UniformParseError, PsycScheme, PsycEntity};
|
||||
pub use packet_types::{PsycOperator, PsycStateOp};
|
||||
pub use 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
|
||||
}
|
||||
}
|
||||
}
|
61
rust/src/method_types.rs
Normal file
61
rust/src/method_types.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
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
|
||||
}
|
|
@ -7,6 +7,12 @@ pub enum PsycRC {
|
|||
PSYC_ERROR = -1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum PsycBool {
|
||||
PSYC_FALSE = 0,
|
||||
PSYC_TRUE = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct PsycString {
|
||||
|
@ -14,4 +20,11 @@ pub struct PsycString {
|
|||
pub data: *const c_char
|
||||
}
|
||||
|
||||
|
||||
impl PsycBool {
|
||||
pub fn to_bool(self) -> bool {
|
||||
match self {
|
||||
PsycBool::PSYC_FALSE => false,
|
||||
PsycBool::PSYC_TRUE => true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
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,
|
||||
}
|
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()
|
||||
});
|
||||
}
|
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""));
|
||||
}
|
Loading…
Reference in a new issue