88 lines
3.3 KiB
Rust
88 lines
3.3 KiB
Rust
|
|
use kordophoned::daemon::signals::Signal;
|
||
|
|
use std::collections::HashMap;
|
||
|
|
use std::ffi::CString;
|
||
|
|
use xpc_connection::Message;
|
||
|
|
|
||
|
|
pub type XpcMap = HashMap<CString, Message>;
|
||
|
|
|
||
|
|
pub fn cstr(s: &str) -> CString { CString::new(s).unwrap_or_else(|_| CString::new("").unwrap()) }
|
||
|
|
|
||
|
|
pub fn get_dictionary_field<'a>(
|
||
|
|
map: &'a HashMap<CString, Message>,
|
||
|
|
key: &str,
|
||
|
|
) -> Option<&'a HashMap<CString, Message>> {
|
||
|
|
let k = CString::new(key).ok()?;
|
||
|
|
map.get(&k).and_then(|v| match v { Message::Dictionary(d) => Some(d), _ => None })
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn dict_get_str(map: &HashMap<CString, Message>, key: &str) -> Option<String> {
|
||
|
|
let k = CString::new(key).ok()?;
|
||
|
|
match map.get(&k) { Some(Message::String(v)) => Some(v.to_string_lossy().into_owned()), _ => None }
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn dict_get_i64_from_str(map: &HashMap<CString, Message>, key: &str) -> Option<i64> {
|
||
|
|
dict_get_str(map, key).and_then(|s| s.parse::<i64>().ok())
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn dict_put_str(map: &mut XpcMap, key: &str, value: impl AsRef<str>) {
|
||
|
|
map.insert(cstr(key), Message::String(cstr(value.as_ref())));
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn dict_put_i64_as_str(map: &mut XpcMap, key: &str, value: i64) { dict_put_str(map, key, value.to_string()); }
|
||
|
|
|
||
|
|
pub fn array_from_strs(values: impl IntoIterator<Item = String>) -> Message {
|
||
|
|
let arr = values.into_iter().map(|s| Message::String(cstr(&s))).collect();
|
||
|
|
Message::Array(arr)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn make_ok_reply() -> Message {
|
||
|
|
let mut reply: XpcMap = HashMap::new();
|
||
|
|
dict_put_str(&mut reply, "type", "Ok");
|
||
|
|
Message::Dictionary(reply)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn make_error_reply(code: &str, message: &str) -> Message {
|
||
|
|
let mut reply: HashMap<CString, Message> = HashMap::new();
|
||
|
|
reply.insert(cstr("type"), Message::String(cstr("Error")));
|
||
|
|
reply.insert(cstr("error"), Message::String(cstr(code)));
|
||
|
|
reply.insert(cstr("message"), Message::String(cstr(message)));
|
||
|
|
Message::Dictionary(reply)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn attach_request_id(mut message: Message, request_id: Option<String>) -> Message {
|
||
|
|
if let (Some(id), Message::Dictionary(ref mut m)) = (request_id, &mut message) {
|
||
|
|
dict_put_str(m, "request_id", &id);
|
||
|
|
}
|
||
|
|
message
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn signal_to_message(signal: Signal) -> Message {
|
||
|
|
let mut root: XpcMap = HashMap::new();
|
||
|
|
let mut args: XpcMap = HashMap::new();
|
||
|
|
match signal {
|
||
|
|
Signal::ConversationsUpdated => {
|
||
|
|
dict_put_str(&mut root, "name", "ConversationsUpdated");
|
||
|
|
}
|
||
|
|
Signal::MessagesUpdated(conversation_id) => {
|
||
|
|
dict_put_str(&mut root, "name", "MessagesUpdated");
|
||
|
|
dict_put_str(&mut args, "conversation_id", &conversation_id);
|
||
|
|
}
|
||
|
|
Signal::AttachmentDownloaded(attachment_id) => {
|
||
|
|
dict_put_str(&mut root, "name", "AttachmentDownloadCompleted");
|
||
|
|
dict_put_str(&mut args, "attachment_id", &attachment_id);
|
||
|
|
}
|
||
|
|
Signal::AttachmentUploaded(upload_guid, attachment_guid) => {
|
||
|
|
dict_put_str(&mut root, "name", "AttachmentUploadCompleted");
|
||
|
|
dict_put_str(&mut args, "upload_guid", &upload_guid);
|
||
|
|
dict_put_str(&mut args, "attachment_guid", &attachment_guid);
|
||
|
|
}
|
||
|
|
Signal::UpdateStreamReconnected => {
|
||
|
|
dict_put_str(&mut root, "name", "UpdateStreamReconnected");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if !args.is_empty() {
|
||
|
|
root.insert(cstr("arguments"), Message::Dictionary(args));
|
||
|
|
}
|
||
|
|
Message::Dictionary(root)
|
||
|
|
}
|