nio: Reintroduce futures as callbacks.

master
Damir Jelić 2019-10-30 23:26:26 +01:00
parent b61dc18060
commit 71d8500453
3 changed files with 65 additions and 44 deletions

View File

@ -1,6 +1,10 @@
#![feature(async_closure)] #![feature(async_closure)]
use std::{env, process::exit}; use std::{env, process::exit};
use std::pin::Pin;
use std::future::Future;
use std::rc::Rc;
use std::cell::RefCell;
use matrix_nio::{ use matrix_nio::{
self, self,
@ -12,8 +16,22 @@ use matrix_nio::{
AsyncClient, AsyncClientConfig, SyncSettings, Room AsyncClient, AsyncClientConfig, SyncSettings, Room
}; };
fn callback(room: &Room, event: &RoomEvent) { async fn async_helper(room: Rc<RefCell<Room>>, event: Rc<RoomEvent>) {
println!("{:?}", event); let room = room.borrow();
if let RoomEvent::RoomMessage(MessageEvent {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
sender,
..
}) = &*event
{
let user = room.members.get(&sender.to_string()).unwrap();
println!("{}: {}", user.display_name.as_ref().unwrap_or(&sender.to_string()), msg_body);
}
}
fn async_callback(room: Rc<RefCell<Room>>, event: Rc<RoomEvent>) -> Pin<Box<dyn Future<Output = ()>>> {
Box::pin(async_helper(room, event))
} }
async fn login( async fn login(
@ -26,20 +44,7 @@ async fn login(
.disable_ssl_verification(); .disable_ssl_verification();
let mut client = AsyncClient::new_with_config(&homeserver_url, None, client_config).unwrap(); let mut client = AsyncClient::new_with_config(&homeserver_url, None, client_config).unwrap();
client.add_event_callback(EventType::RoomMessage, Box::new(callback)); client.add_event_future(EventType::RoomMessage, Box::new(async_callback));
// client.add_event_callback(EventType::RoomMessage, Box::new(|event| {
// Box::pin(async {
// if let RoomEvent::RoomMessage(MessageEvent {
// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
// sender,
// ..
// }) = event
// {
// println!("{}: {}", sender, msg_body);
// }
// })
// }));
client.login(username, password, None).await?; client.login(username, password, None).await?;
let response = client.sync(SyncSettings::new()).await?; let response = client.sync(SyncSettings::new()).await?;

View File

@ -1,6 +1,8 @@
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::future::Future; use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc;
use std::cell::RefCell;
use http::Method as HttpMethod; use http::Method as HttpMethod;
use http::Response as HttpResponse; use http::Response as HttpResponse;
@ -20,6 +22,7 @@ use crate::error::{Error, InnerError};
use crate::session::Session; use crate::session::Session;
type RoomEventCallback = Box::<dyn FnMut(&Room, &RoomEvent)>; type RoomEventCallback = Box::<dyn FnMut(&Room, &RoomEvent)>;
type RoomEventCallbackF = Box::<dyn FnMut(Rc<RefCell<Room>>, Rc<RoomEvent>) -> Pin<Box<dyn Future<Output = ()>>>>;
pub struct AsyncClient { pub struct AsyncClient {
/// The URL of the homeserver to connect to. /// The URL of the homeserver to connect to.
@ -30,6 +33,8 @@ pub struct AsyncClient {
base_client: BaseClient, base_client: BaseClient,
/// Event callbacks /// Event callbacks
event_callbacks: Vec<RoomEventCallback>, event_callbacks: Vec<RoomEventCallback>,
/// Event futures
event_futures: Vec<RoomEventCallbackF>,
} }
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -162,6 +167,7 @@ impl AsyncClient {
http_client, http_client,
base_client: BaseClient::new(session), base_client: BaseClient::new(session),
event_callbacks: Vec::new(), event_callbacks: Vec::new(),
event_futures: Vec::new(),
}) })
} }
@ -173,6 +179,14 @@ impl AsyncClient {
self.event_callbacks.push(callback); self.event_callbacks.push(callback);
} }
pub fn add_event_future(
&mut self,
event_type: EventType,
callback: RoomEventCallbackF,
) {
self.event_futures.push(callback);
}
pub async fn login<S: Into<String>>( pub async fn login<S: Into<String>>(
&mut self, &mut self,
user: S, user: S,
@ -232,13 +246,12 @@ impl AsyncClient {
let room = self.base_client.joined_rooms.get(&room_id).unwrap(); let room = self.base_client.joined_rooms.get(&room_id).unwrap();
for mut cb in &mut self.event_callbacks { for mut cb in &mut self.event_callbacks {
cb(&room, &event); cb(&room.borrow(), &event);
} }
// if self.event_callbacks.contains_key(&event_type) { for mut cb in &mut self.event_futures {
// let cb = self.event_callbacks.get_mut(&event_type).unwrap(); cb(room.clone(), Rc::new(event.clone())).await;
// cb(&event).await; }
// }
} }
} }

View File

@ -4,6 +4,8 @@ use crate::api::r0 as api;
use crate::events::collections::all::{RoomEvent, StateEvent}; use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::room::member::{MemberEvent, MembershipState}; use crate::events::room::member::{MemberEvent, MembershipState};
use crate::session::Session; use crate::session::Session;
use std::rc::Rc;
use std::cell::RefCell;
pub type Token = String; pub type Token = String;
pub type RoomId = String; pub type RoomId = String;
@ -13,30 +15,30 @@ pub type UserId = String;
/// A Matrix room member. /// A Matrix room member.
pub struct RoomMember { pub struct RoomMember {
/// The unique mxid of the user. /// The unique mxid of the user.
user_id: UserId, pub user_id: UserId,
/// The human readable name of the user. /// The human readable name of the user.
display_name: Option<String>, pub display_name: Option<String>,
/// The matrix url of the users avatar. /// The matrix url of the users avatar.
avatar_url: Option<String>, pub avatar_url: Option<String>,
/// The users power level. /// The users power level.
power_level: u8, pub power_level: u8,
} }
#[derive(Debug)] #[derive(Debug)]
/// A Matrix rooom. /// A Matrix rooom.
pub struct Room { pub struct Room {
/// The unique id of the room. /// The unique id of the room.
room_id: RoomId, pub room_id: RoomId,
/// The mxid of our own user. /// The mxid of our own user.
own_user_id: UserId, pub own_user_id: UserId,
/// The mxid of the room creator. /// The mxid of the room creator.
creator: Option<UserId>, pub creator: Option<UserId>,
/// The map of room members. /// The map of room members.
members: HashMap<UserId, RoomMember>, pub members: HashMap<UserId, RoomMember>,
/// A list of users that are currently typing. /// A list of users that are currently typing.
typing_users: Vec<UserId>, pub typing_users: Vec<UserId>,
/// A flag indicating if the room is encrypted. /// A flag indicating if the room is encrypted.
encrypted: bool, pub encrypted: bool,
} }
impl Room { impl Room {
@ -148,7 +150,7 @@ pub struct Client {
/// The current sync token that should be used for the next sync call. /// The current sync token that should be used for the next sync call.
pub sync_token: Option<Token>, pub sync_token: Option<Token>,
/// A map of the rooms our user is joined in. /// A map of the rooms our user is joined in.
pub joined_rooms: HashMap<RoomId, Room>, pub joined_rooms: HashMap<RoomId, Rc<RefCell<Room>>>,
} }
impl Client { impl Client {
@ -184,18 +186,19 @@ impl Client {
self.session = Some(session); self.session = Some(session);
} }
fn get_or_create_room(&mut self, room_id: &RoomId) -> &mut Room { fn get_or_create_room(&mut self, room_id: &RoomId) -> &mut Rc<RefCell<Room>> {
self.joined_rooms self.joined_rooms
.entry(room_id.to_string()) .entry(room_id.to_string())
.or_insert(Room::new( .or_insert(
room_id, Rc::new(RefCell::new(Room::new(
&self room_id,
.session &self
.as_ref() .session
.expect("Receiving events while not being logged in") .as_ref()
.user_id .expect("Receiving events while not being logged in")
.to_string(), .user_id
)) .to_string(),
))))
} }
/// Receive a timeline event for a joined room and update the client state. /// Receive a timeline event for a joined room and update the client state.
@ -207,7 +210,7 @@ impl Client {
/// Returns true if the membership list of the room changed, false /// Returns true if the membership list of the room changed, false
/// otherwise. /// otherwise.
pub fn receive_joined_timeline_event(&mut self, room_id: &RoomId, event: &RoomEvent) -> bool { pub fn receive_joined_timeline_event(&mut self, room_id: &RoomId, event: &RoomEvent) -> bool {
let mut room = self.get_or_create_room(room_id); let mut room = self.get_or_create_room(room_id).borrow_mut();
room.receive_timeline_event(event) room.receive_timeline_event(event)
} }
@ -220,7 +223,7 @@ impl Client {
/// Returns true if the membership list of the room changed, false /// Returns true if the membership list of the room changed, false
/// otherwise. /// otherwise.
pub fn receive_joined_state_event(&mut self, room_id: &RoomId, event: &StateEvent) -> bool { pub fn receive_joined_state_event(&mut self, room_id: &RoomId, event: &StateEvent) -> bool {
let mut room = self.get_or_create_room(room_id); let mut room = self.get_or_create_room(room_id).borrow_mut();
room.receive_state_event(event) room.receive_state_event(event)
} }
} }