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:
2021-04-10 14:25:19 +01:00
parent 6237b9421d
commit dedd12c66a
21 changed files with 2788 additions and 0 deletions

View 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 })
}
}

View 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()
}
}

View 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,
}