Vendor in a purple-sys wrapper
This code comes from https://github.com/Flared/purple-icq/tree/master/src/purple It is GPL-3 licensed
This commit is contained in:
45
src/purple/connection/connections.rs
Normal file
45
src/purple/connection/connections.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use super::protocol_data::ProtocolData;
|
||||
use crate::purple::ffi::AsMutPtr;
|
||||
use crate::purple::Connection;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
pub struct Connections<T> {
|
||||
protocol_datas: std::collections::HashSet<*mut ProtocolData<T>>,
|
||||
}
|
||||
|
||||
impl<T> Connections<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
protocol_datas: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn add(&mut self, connection: Connection, data: T) {
|
||||
let account = connection.get_account();
|
||||
let data_ptr = Box::new(ProtocolData::<T> {
|
||||
account,
|
||||
connection,
|
||||
data,
|
||||
});
|
||||
let data_raw_ptr = Box::into_raw(data_ptr);
|
||||
connection.set_protocol_data(data_raw_ptr as *mut c_void);
|
||||
self.protocol_datas.insert(data_raw_ptr);
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, connection: Connection) {
|
||||
let protocol_data_ptr = connection.get_protocol_data() as *mut ProtocolData<T>;
|
||||
self.protocol_datas.remove(&protocol_data_ptr);
|
||||
// Retake ownership of the protocol data to drop its data.
|
||||
unsafe { Box::from_raw(protocol_data_ptr) };
|
||||
}
|
||||
|
||||
pub fn get<'b, P>(&mut self, mut ptr: P) -> Option<&'b mut ProtocolData<T>>
|
||||
where
|
||||
P: AsMutPtr<PtrType = ProtocolData<T>>,
|
||||
{
|
||||
self.protocol_datas
|
||||
.get(&ptr.as_mut_ptr())
|
||||
.cloned()
|
||||
.map(|p| unsafe { &mut *p })
|
||||
}
|
||||
}
|
100
src/purple/connection/mod.rs
Normal file
100
src/purple/connection/mod.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
use super::ffi::AsPtr;
|
||||
use super::{Conversation, Plugin};
|
||||
use crate::purple;
|
||||
use crate::purple::PurpleMessageFlags;
|
||||
use crate::MsgInfo;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
pub mod connections;
|
||||
pub mod protocol_data;
|
||||
|
||||
pub use self::connections::Connections;
|
||||
pub use self::protocol_data::Handle;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Connection(NonNull<purple_sys::PurpleConnection>);
|
||||
|
||||
impl Connection {
|
||||
pub unsafe fn from_raw(ptr: *mut purple_sys::PurpleConnection) -> Option<Self> {
|
||||
NonNull::new(ptr).map(Self)
|
||||
}
|
||||
|
||||
pub fn get_protocol_plugin(self) -> Option<Plugin> {
|
||||
let plugin_ptr = unsafe { purple_sys::purple_connection_get_prpl(self.0.as_ptr()) };
|
||||
if plugin_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { Plugin::from_raw(plugin_ptr) })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_protocol_data(self, data: *mut c_void) {
|
||||
unsafe { purple_sys::purple_connection_set_protocol_data(self.0.as_ptr(), data) };
|
||||
}
|
||||
|
||||
pub fn get_protocol_data(self) -> *mut c_void {
|
||||
unsafe { purple_sys::purple_connection_get_protocol_data(self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
pub fn get_account(self) -> purple::Account {
|
||||
unsafe {
|
||||
purple::Account::from_raw(purple_sys::purple_connection_get_account(self.0.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_state(self, state: purple::PurpleConnectionState) {
|
||||
log::info!("Connection state: {:?}", state);
|
||||
unsafe { purple_sys::purple_connection_set_state(self.0.as_ptr(), state) };
|
||||
}
|
||||
|
||||
pub fn error_reason(self, reason: purple::PurpleConnectionError, description: &str) {
|
||||
let c_description = CString::new(description).unwrap();
|
||||
unsafe {
|
||||
purple_sys::purple_connection_error_reason(
|
||||
self.0.as_ptr(),
|
||||
reason,
|
||||
c_description.as_ptr(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serv_got_chat_in(self, chat_input: MsgInfo) {
|
||||
unsafe {
|
||||
let c_sn = CString::new(chat_input.chat_sn).unwrap();
|
||||
let sn_hash = glib_sys::g_str_hash(c_sn.as_ptr() as *mut c_void);
|
||||
let c_sender = CString::new(chat_input.author_sn).unwrap();
|
||||
let c_text = CString::new(chat_input.text).unwrap();
|
||||
|
||||
purple_sys::serv_got_chat_in(
|
||||
self.0.as_ptr(),
|
||||
sn_hash as i32,
|
||||
c_sender.as_ptr(),
|
||||
PurpleMessageFlags::PURPLE_MESSAGE_RECV,
|
||||
c_text.as_ptr(),
|
||||
chat_input.time as i64,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serv_got_joined_chat(self, name: &str) -> Option<Conversation> {
|
||||
unsafe {
|
||||
let c_name = CString::new(name).unwrap();
|
||||
let name_hash = glib_sys::g_str_hash(c_name.as_ptr() as *mut c_void);
|
||||
let conv = purple_sys::serv_got_joined_chat(
|
||||
self.0.as_ptr(),
|
||||
name_hash as i32,
|
||||
c_name.as_ptr(),
|
||||
);
|
||||
Conversation::from_ptr(conv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsPtr for Connection {
|
||||
type PtrType = purple_sys::PurpleConnection;
|
||||
fn as_ptr(&self) -> *const purple_sys::PurpleConnection {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
}
|
51
src/purple/connection/protocol_data.rs
Normal file
51
src/purple/connection/protocol_data.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
use crate::purple::ffi::AsPtr;
|
||||
use crate::purple::{Account, Connection};
|
||||
|
||||
pub struct Handle<T>(*mut ProtocolData<T>);
|
||||
|
||||
impl<T> std::fmt::Debug for Handle<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Handle({:?})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<&mut Connection> for Handle<T> {
|
||||
fn from(connection: &mut Connection) -> Handle<T> {
|
||||
Handle(connection.get_protocol_data() as *mut ProtocolData<T>)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<&mut Account> for Handle<T> {
|
||||
fn from(account: &mut Account) -> Handle<T> {
|
||||
Handle(account.get_connection().unwrap().get_protocol_data() as *mut ProtocolData<T>)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for Handle<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for Handle<T> {}
|
||||
unsafe impl<T> Sync for Handle<T> {}
|
||||
|
||||
impl<T> AsPtr for Handle<T> {
|
||||
type PtrType = ProtocolData<T>;
|
||||
fn as_ptr(&self) -> *const ProtocolData<T> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsPtr for &Handle<T> {
|
||||
type PtrType = ProtocolData<T>;
|
||||
fn as_ptr(&self) -> *const ProtocolData<T> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProtocolData<T> {
|
||||
pub account: Account,
|
||||
pub connection: Connection,
|
||||
pub data: T,
|
||||
}
|
Reference in New Issue
Block a user