chorus/src/gateway.rs

130 lines
3.5 KiB
Rust
Raw Normal View History

2023-04-28 12:31:59 +02:00
use crate::{api::WebSocketEvent, errors::ObserverError};
2023-04-27 22:38:41 +02:00
2023-04-16 23:03:24 +02:00
#[derive(Debug)]
2023-04-28 13:40:29 +02:00
/**
Represents a Gateway connection.
*/
2023-04-27 17:57:10 +02:00
pub struct Gateway {}
2023-04-28 13:40:29 +02:00
/**
Trait which defines the behaviour of an Observer. An Observer is an object which is subscribed to
an Observable. The Observer is notified when the Observable's data changes.
In this case, the Observable is a GatewayEvent, which is a wrapper around a WebSocketEvent.
*/
2023-04-28 12:31:59 +02:00
pub trait Observer<T: WebSocketEvent> {
fn update(&self, data: &T);
2023-04-27 17:57:10 +02:00
}
2023-04-28 13:40:29 +02:00
/** GatewayEvent is a wrapper around a WebSocketEvent. It is used to notify the observers of a
* change in the WebSocketEvent.
*/
2023-04-28 12:31:59 +02:00
pub struct GatewayEvent<'a, T: WebSocketEvent> {
observers: Vec<&'a dyn Observer<T>>,
pub event_data: T,
2023-04-27 22:29:07 +02:00
pub is_observed: bool,
2023-04-27 17:57:10 +02:00
}
2023-04-28 12:31:59 +02:00
impl<'a, T: WebSocketEvent> GatewayEvent<'a, T> {
fn new(event_data: T) -> Self {
2023-04-27 17:57:10 +02:00
Self {
2023-04-27 22:29:07 +02:00
is_observed: false,
2023-04-27 17:57:10 +02:00
observers: Vec::new(),
2023-04-28 12:31:59 +02:00
event_data,
2023-04-27 17:57:10 +02:00
}
}
2023-04-28 13:40:29 +02:00
/**
Returns true if the GatewayEvent is observed by at least one Observer.
*/
2023-04-27 22:29:07 +02:00
pub fn is_observed(&self) -> bool {
self.is_observed
}
2023-04-28 13:40:29 +02:00
/**
Subscribes an Observer to the GatewayEvent. Returns an error if the GatewayEvent is already
observed.
# Errors
Returns an error if the GatewayEvent is already observed.
Error type: [`ObserverError::AlreadySubscribedError`]
*/
2023-04-28 12:31:59 +02:00
pub fn subscribe(&mut self, observable: &'a dyn Observer<T>) -> Option<ObserverError> {
2023-04-27 22:29:07 +02:00
if self.is_observed {
2023-04-27 22:38:41 +02:00
return Some(ObserverError::AlreadySubscribedError);
2023-04-27 22:29:07 +02:00
}
self.is_observed = true;
2023-04-27 22:38:41 +02:00
self.observers.push(observable);
None
2023-04-27 17:57:10 +02:00
}
2023-04-28 13:40:29 +02:00
/**
Unsubscribes an Observer from the GatewayEvent.
*/
2023-04-28 12:31:59 +02:00
pub fn unsubscribe(&mut self, observable: &'a dyn Observer<T>) {
// .retain()'s closure retains only those elements of the vector, which have a different
// pointer value than observable.
self.observers.retain(|obs| !std::ptr::eq(*obs, observable));
self.is_observed = !self.observers.is_empty();
2023-04-27 22:29:07 +02:00
return;
2023-04-27 17:57:10 +02:00
}
2023-04-28 13:40:29 +02:00
/**
Updates the GatewayEvent's data and notifies the observers.
*/
2023-04-28 12:31:59 +02:00
fn update_data(&mut self, new_event_data: T) {
self.event_data = new_event_data;
2023-04-27 17:57:10 +02:00
self.notify();
}
2023-04-28 13:40:29 +02:00
/**
Notifies the observers of the GatewayEvent.
*/
2023-04-27 22:29:07 +02:00
fn notify(&self) {
2023-04-27 17:57:10 +02:00
for observer in &self.observers {
2023-04-28 12:31:59 +02:00
observer.update(&self.event_data);
}
}
}
#[cfg(test)]
2023-04-28 12:39:58 +02:00
mod example {
2023-04-28 12:31:59 +02:00
use super::*;
use crate::api::types::GatewayResume;
struct Consumer;
impl Observer<GatewayResume> for Consumer {
fn update(&self, data: &GatewayResume) {
println!("{}", data.token)
}
}
#[test]
fn test_observer_behaviour() {
let mut event = GatewayEvent::new(GatewayResume {
token: "start".to_string(),
session_id: "start".to_string(),
seq: "start".to_string(),
});
let new_data = GatewayResume {
token: "token_3276ha37am3".to_string(),
session_id: "89346671230".to_string(),
seq: "3".to_string(),
};
let consumer = Consumer;
event.subscribe(&consumer);
event.notify();
event.update_data(new_data);
let second_consumer = Consumer;
match event.subscribe(&second_consumer) {
2023-04-28 12:39:58 +02:00
None => assert!(false),
2023-04-28 12:31:59 +02:00
Some(err) => println!("You cannot subscribe twice: {}", err),
2023-04-27 17:57:10 +02:00
}
}
2023-04-25 17:21:27 +02:00
}