use crate::session::Session;
use std::{borrow::Cow, ops::Deref, option::NoneError};
use widestring::{WideCStr, WideCString, WideChar};
pub use std::{marker::PhantomData, ptr::NonNull};
#[cfg(feature = "visualobject")]
pub use winapi::shared::{minwindef::HINSTANCE, windef::HWND};
pub mod ffi;
pub type pbint = i16;
pub type pbuint = u16;
pub type pblong = i32;
pub type pbulong = u32;
pub type pblonglong = i64;
pub type pbbyte = u8;
pub type pbreal = f32;
pub type pbdouble = f64;
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq, Eq, Default)]
pub struct pbboolean(i16);
impl pbboolean {
#[inline]
pub fn to_bool(self) -> bool {
if self.0 == 1 {
true
} else {
false
}
}
}
impl PartialEq<bool> for pbboolean {
fn eq(&self, other: &bool) -> bool { self.to_bool() == *other }
}
impl From<bool> for pbboolean {
fn from(b: bool) -> Self {
pbboolean(if b {
1
} else {
0
})
}
}
impl From<pbboolean> for bool {
fn from(b: pbboolean) -> Self { b.to_bool() }
}
pub type LPCTSTR = *const WideChar;
pub type PBChar = WideChar;
pub type PBStr = WideCStr;
pub type PBString = WideCString;
pub trait AsPBStr {
fn as_pbstr(&self) -> Cow<'_, PBStr>;
}
impl AsPBStr for &PBStr {
fn as_pbstr(&self) -> Cow<'_, PBStr> { (*self).into() }
}
impl AsPBStr for PBString {
fn as_pbstr(&self) -> Cow<'_, PBStr> { self.deref().into() }
}
impl AsPBStr for String {
fn as_pbstr(&self) -> Cow<'_, PBStr> {
PBString::from_str(self).expect("incompatible utf-8 string").into()
}
}
impl AsPBStr for &str {
fn as_pbstr(&self) -> Cow<'_, PBStr> {
PBString::from_str(self).expect("incompatible utf-8 string").into()
}
}
impl AsPBStr for Cow<'_, PBStr> {
fn as_pbstr(&self) -> Cow<'_, PBStr> { self.as_ref().into() }
}
pub trait FromPBStrPtr {
unsafe fn from_pbstr_unchecked(ptr: LPCTSTR) -> Self;
}
impl FromPBStrPtr for String {
unsafe fn from_pbstr_unchecked(ptr: LPCTSTR) -> Self { PBStr::from_ptr_str(ptr).to_string_lossy() }
}
impl FromPBStrPtr for PBString {
unsafe fn from_pbstr_unchecked(ptr: LPCTSTR) -> Self { PBStr::from_ptr_str(ptr).to_ucstring() }
}
macro_rules! declare_handle {
($name:ident, $inner:ident) => {
#[repr(C)]
pub struct $inner([u8; 0]);
pub type $name = NonNull<$inner>;
};
}
declare_handle!(pbvm, _IPB_VM);
declare_handle!(pbsession, _IPB_Session);
declare_handle!(pbvalue, _IPB_Value);
declare_handle!(pbarguments, _IPB_Arguments);
declare_handle!(pbclass, _pbclass);
declare_handle!(pbgroup, _pbgroup);
declare_handle!(pbstring, _pbstring);
declare_handle!(pbobject, _pbobject);
declare_handle!(pbarray, _pbarray);
declare_handle!(pbdec, _pbdec);
declare_handle!(pbdate, _pbdate);
declare_handle!(pbtime, _pbtime);
declare_handle!(pbdatetime, _pbdatetime);
declare_handle!(pbblob, _pbblob);
declare_handle!(pbuserobject, _IUserObject);
#[cfg(feature = "nonvisualobject")]
#[repr(C)]
pub struct NVOM<T: Sized> {
pub ctx: NonNull<T>,
pub type_id: u64,
pub destory: unsafe extern "C" fn(NonNull<T>),
pub invoke: unsafe extern "C" fn(NonNull<T>, Session, pbobject, MethodId, pbcallinfo) -> PBXRESULT
}
#[cfg(feature = "visualobject")]
#[repr(C)]
pub struct VOM<T: Sized> {
pub ctx: NonNull<T>,
pub type_id: u64,
pub cls_name: LPCTSTR,
pub destory: unsafe extern "C" fn(NonNull<T>),
pub invoke: unsafe extern "C" fn(NonNull<T>, Session, pbobject, MethodId, pbcallinfo) -> PBXRESULT,
pub create_control:
unsafe extern "C" fn(NonNull<T>, u32, LPCTSTR, u32, i32, i32, i32, i32, HWND, HINSTANCE) -> HWND,
pub get_event_id: unsafe extern "C" fn(NonNull<T>, HWND, u16, u32, u32) -> i32
}
#[repr(C)]
pub struct _PBCallInfo {
pub pArgs: pbarguments,
pub returnValue: pbvalue,
pub returnClass: pbclass
}
pub type pbcallinfo = NonNull<_PBCallInfo>;
#[repr(C)]
pub struct _PBArrayInfo {
pub arrayType: ArrayType,
pub itemGroup: pbgroup,
pub valueType: ValueType,
pub numDimensions: pbuint,
pub bounds: [ArrayBound; 0]
}
pub type pbarrayinfo = NonNull<_PBArrayInfo>;
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ArrayType {
BoundedArray,
UnboundedArray
}
#[repr(C)]
pub struct ArrayBound {
pub upperBound: pblong,
pub lowerBound: pblong
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct MethodId(u16);
impl MethodId {
pub unsafe fn new(id: u16) -> MethodId { MethodId(id) }
pub fn value(self) -> u16 { self.0 }
pub(crate) fn is_undefined(self) -> bool {
const kUndefinedMethodID: u16 = 0xffff;
self.0 == kUndefinedMethodID
}
}
impl PartialEq<u16> for MethodId {
fn eq(&self, other: &u16) -> bool { self.0.eq(other) }
}
impl PartialOrd<u16> for MethodId {
fn partial_cmp(&self, other: &u16) -> Option<std::cmp::Ordering> { self.0.partial_cmp(other) }
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct FieldId(u16);
impl FieldId {
pub unsafe fn new(id: u16) -> FieldId { FieldId(id) }
pub fn value(self) -> u16 { self.0 }
pub(crate) fn is_undefined(self) -> bool {
const kUndefinedFieldID: u16 = 0xffff;
self.0 == kUndefinedFieldID
}
}
impl PartialEq<u16> for FieldId {
fn eq(&self, other: &u16) -> bool { self.0.eq(other) }
}
impl PartialOrd<u16> for FieldId {
fn partial_cmp(&self, other: &u16) -> Option<std::cmp::Ordering> { self.0.partial_cmp(other) }
}
#[repr(i32)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum GroupType {
Application = 0,
DataWindow,
Function,
Menu,
Proxy,
Structure,
UserObject,
Window,
Unknown
}
impl From<i32> for GroupType {
fn from(v: i32) -> Self { unsafe { std::mem::transmute(v) } }
}
#[repr(u16)]
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ValueType {
NoType = 0,
Int,
Long,
Real,
Double,
Decimal,
String,
Boolean,
Any,
Uint,
Ulong,
Blob,
Date,
Time,
DateTime,
Dummy1,
Dummy2,
Dummy3,
Char,
Dummy4,
LongLong,
Byte
}
impl From<pbuint> for ValueType {
fn from(v: pbuint) -> Self { unsafe { std::mem::transmute(v) } }
}
impl From<i32> for ValueType {
fn from(v: i32) -> Self { unsafe { std::mem::transmute(v as u16) } }
}
#[repr(i32)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum RoutineType {
Function = 0,
Event,
Any
}
impl From<i32> for RoutineType {
fn from(v: i32) -> Self { unsafe { std::mem::transmute(v) } }
}
#[repr(i32)]
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum PBXRESULT {
OK = 0,
E_NO_REGISTER_FUNCTION = -1,
E_REGISTRATION_FAILED = -2,
E_BUILD_GROUP_FAILED = -3,
E_INVALID_ARGUMENT = -4,
E_INVOKE_METHOD_INACCESSABLE = -5,
E_INVOKE_WRONG_NUM_ARGS = -6,
E_INVOKE_REFARG_ERROR = -7,
E_INVOKE_METHOD_AMBIGUOUS = -8,
E_INVOKE_FAILURE = -9,
E_MISMATCHED_DATA_TYPE = -10,
E_OUTOF_MEMORY = -11,
E_GET_PBVM_FAILED = -12,
E_NO_SUCH_CLASS = -13,
E_CAN_NOT_LOCATE_APPLICATION = -14,
E_INVALID_METHOD_ID = -15,
E_READONLY_ARGS = -16,
E_ARRAY_INDEX_OUTOF_BOUNDS = -100,
E_NULL_ERROR = -10000
}
impl PBXRESULT {
pub fn is_ok(self) -> bool { self == PBXRESULT::OK }
pub fn is_err(self) -> bool { self != PBXRESULT::OK }
}
impl From<i32> for PBXRESULT {
fn from(v: i32) -> Self { unsafe { std::mem::transmute(v) } }
}
impl From<NoneError> for PBXRESULT {
fn from(_: NoneError) -> Self { PBXRESULT::E_NULL_ERROR }
}
impl<T: Default> From<PBXRESULT> for crate::Result<T> {
fn from(pbxr: PBXRESULT) -> Self {
if pbxr == PBXRESULT::OK {
Ok(Default::default())
} else {
Err(pbxr)
}
}
}
impl<T> From<crate::Result<T>> for PBXRESULT {
fn from(pbxr: crate::Result<T>) -> Self {
if let Err(e) = pbxr {
e
} else {
PBXRESULT::OK
}
}
}