use crate::{ffi, Message};
use std::marker::PhantomData;
use std::rc::Rc;
#[repr(transparent)]
pub struct Event {
ptr: *mut ffi::blpapi_Event_t,
_marker: PhantomData<Rc<()>>, }
impl Event {
#[inline]
pub(crate) unsafe fn from_raw(ptr: *mut ffi::blpapi_Event_t) -> Self {
Self {
ptr,
_marker: PhantomData,
}
}
#[inline(always)]
pub fn event_type(&self) -> EventType {
let ty = unsafe { ffi::blpapi_Event_eventType(self.ptr) };
EventType::from_raw(ty)
}
#[inline]
pub fn messages(&self) -> MessageIterator<'_> {
let iter_ptr = unsafe { ffi::blpapi_MessageIterator_create(self.ptr) };
MessageIterator {
ptr: iter_ptr,
_life: PhantomData,
_marker: PhantomData,
}
}
#[inline]
pub fn iter(&self) -> MessageIterator<'_> {
self.messages()
}
#[inline(always)]
#[allow(dead_code)] pub(crate) fn as_ptr(&self) -> *mut ffi::blpapi_Event_t {
self.ptr
}
}
impl Drop for Event {
fn drop(&mut self) {
unsafe {
ffi::blpapi_Event_release(self.ptr);
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum EventType {
Admin = 1,
SessionStatus = 2,
SubscriptionStatus = 3,
RequestStatus = 4,
Response = 5,
PartialResponse = 6,
SubscriptionData = 8,
ServiceStatus = 9,
Timeout = 10,
AuthorizationStatus = 11,
ResolutionStatus = 12,
TopicStatus = 13,
TokenStatus = 14,
Request = 15,
Unknown(i32),
}
impl EventType {
#[inline]
pub fn from_raw(v: i32) -> Self {
match v {
1 => Self::Admin,
2 => Self::SessionStatus,
3 => Self::SubscriptionStatus,
4 => Self::RequestStatus,
5 => Self::Response,
6 => Self::PartialResponse,
8 => Self::SubscriptionData,
9 => Self::ServiceStatus,
10 => Self::Timeout,
11 => Self::AuthorizationStatus,
12 => Self::ResolutionStatus,
13 => Self::TopicStatus,
14 => Self::TokenStatus,
15 => Self::Request,
_ => Self::Unknown(v),
}
}
#[inline]
pub fn to_raw(&self) -> i32 {
match self {
Self::Admin => 1,
Self::SessionStatus => 2,
Self::SubscriptionStatus => 3,
Self::RequestStatus => 4,
Self::Response => 5,
Self::PartialResponse => 6,
Self::SubscriptionData => 8,
Self::ServiceStatus => 9,
Self::Timeout => 10,
Self::AuthorizationStatus => 11,
Self::ResolutionStatus => 12,
Self::TopicStatus => 13,
Self::TokenStatus => 14,
Self::Request => 15,
Self::Unknown(v) => *v,
}
}
}
pub struct MessageIterator<'a> {
ptr: *mut ffi::blpapi_MessageIterator_t,
_life: PhantomData<&'a Event>,
_marker: PhantomData<Rc<()>>, }
impl<'a> Iterator for MessageIterator<'a> {
type Item = Message<'a>;
fn next(&mut self) -> Option<Self::Item> {
let mut msg_ptr: *mut ffi::blpapi_Message_t = std::ptr::null_mut();
let rc = unsafe { ffi::blpapi_MessageIterator_next(self.ptr, &mut msg_ptr) };
if rc == 0 && !msg_ptr.is_null() {
Some(unsafe { Message::from_raw(msg_ptr) })
} else {
None
}
}
}
impl<'a> Drop for MessageIterator<'a> {
fn drop(&mut self) {
unsafe {
ffi::blpapi_MessageIterator_destroy(self.ptr);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_event_type_from_raw_known() {
assert_eq!(EventType::from_raw(1), EventType::Admin);
assert_eq!(EventType::from_raw(2), EventType::SessionStatus);
assert_eq!(EventType::from_raw(5), EventType::Response);
assert_eq!(EventType::from_raw(6), EventType::PartialResponse);
assert_eq!(EventType::from_raw(8), EventType::SubscriptionData);
assert_eq!(EventType::from_raw(10), EventType::Timeout);
assert_eq!(EventType::from_raw(15), EventType::Request);
}
#[test]
fn test_event_type_from_raw_unknown() {
assert_eq!(EventType::from_raw(999), EventType::Unknown(999));
assert_eq!(EventType::from_raw(-1), EventType::Unknown(-1));
assert_eq!(EventType::from_raw(100), EventType::Unknown(100));
}
#[test]
fn test_event_type_to_raw() {
assert_eq!(EventType::Response.to_raw(), 5);
assert_eq!(EventType::PartialResponse.to_raw(), 6);
assert_eq!(EventType::SubscriptionData.to_raw(), 8);
assert_eq!(EventType::Unknown(999).to_raw(), 999);
}
#[test]
fn test_event_type_roundtrip() {
for i in [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15] {
let ty = EventType::from_raw(i);
assert_eq!(ty.to_raw(), i);
}
}
#[test]
fn test_event_size() {
assert_eq!(std::mem::size_of::<Event>(), std::mem::size_of::<*mut ()>());
}
#[test]
fn test_event_alignment() {
assert_eq!(
std::mem::align_of::<Event>(),
std::mem::align_of::<*mut ()>()
);
}
#[test]
fn test_message_iterator_size() {
assert_eq!(
std::mem::size_of::<MessageIterator>(),
std::mem::size_of::<*mut ()>()
);
}
}