use std::os::raw::c_void;
use crate::correlation::CorrelationId;
use crate::errors::{BlpError, Result};
use crate::event::Event;
use crate::options::SessionOptions;
use crate::request::Request;
use crate::service::Service;
use crate::session_operations::SessionOperations;
struct HandlerShared {
f: Box<dyn Fn(Event) + Send + Sync + 'static>,
}
unsafe extern "C" fn event_trampoline(
event: *mut crate::ffi::blpapi_Event_t,
_session: *mut crate::ffi::blpapi_Session_t,
user_data: *mut c_void,
) {
if event.is_null() || user_data.is_null() {
return;
}
let shared = unsafe { &*(user_data as *const HandlerShared) };
let event = unsafe { Event::from_raw(event) };
(shared.f)(event);
}
pub struct AsyncSession {
ptr: *mut crate::ffi::blpapi_Session_t,
_handler: Box<HandlerShared>,
}
unsafe impl Send for AsyncSession {}
unsafe impl Sync for AsyncSession {}
impl AsyncSession {
fn operations(&self) -> SessionOperations<'_> {
unsafe { SessionOperations::new(&self.ptr) }
}
pub fn new(
options: &SessionOptions,
handler: impl Fn(Event) + Send + Sync + 'static,
) -> Result<Self> {
let shared = Box::new(HandlerShared {
f: Box::new(handler),
});
let user_data = &*shared as *const HandlerShared as *mut c_void;
let ptr = unsafe {
crate::ffi::blpapi_Session_create(
options.as_raw(),
Some(event_trampoline),
std::ptr::null_mut(),
user_data,
)
};
if ptr.is_null() {
return Err(BlpError::SessionStart {
source: None,
label: None,
});
}
Ok(Self {
ptr,
_handler: shared,
})
}
pub fn start(&self) -> Result<()> {
let rc = unsafe { crate::ffi::blpapi_Session_start(self.ptr) };
if rc != 0 {
return Err(BlpError::SessionStart {
source: None,
label: None,
});
}
Ok(())
}
pub fn stop(&self) {
unsafe {
crate::ffi::blpapi_Session_stop(self.ptr);
}
}
pub fn stop_async(&self) {
unsafe {
crate::ffi::blpapi_Session_stopAsync(self.ptr);
}
}
pub fn open_service(&self, name: &str) -> Result<()> {
self.operations().open_service(name)
}
pub fn open_service_async(&self, name: &str, cid: &CorrelationId) -> Result<CorrelationId> {
self.operations().open_service_async(name, cid)
}
pub fn get_service(&self, name: &str) -> Result<Service<'_>> {
self.operations().get_service(name)
}
pub fn send_request(
&self,
req: &Request,
cid: Option<&CorrelationId>,
) -> Result<CorrelationId> {
self.send_request_with_label(req, cid, None)
}
pub fn send_request_with_label(
&self,
req: &Request,
cid: Option<&CorrelationId>,
label: Option<&str>,
) -> Result<CorrelationId> {
self.operations().send_request(req, None, cid, label)
}
pub fn cancel(&self, cid: &CorrelationId) -> Result<()> {
self.operations().cancel(cid)
}
pub fn subscribe(&self, subs: &crate::SubscriptionList, label: Option<&str>) -> Result<()> {
self.operations()
.subscribe(subs, None, label, "subscription label")
}
pub fn resubscribe(&self, subs: &crate::SubscriptionList, label: Option<&str>) -> Result<()> {
self.operations()
.resubscribe(subs, label, "subscription label")
}
pub fn unsubscribe(&self, subs: &crate::SubscriptionList) -> Result<()> {
self.operations().unsubscribe(subs)
}
pub fn generate_authorized_identity_async(
&self,
auth_options: &crate::auth::AuthOptions,
cid: &CorrelationId,
) -> Result<()> {
let mut cid_ffi = cid.to_ffi();
let rc = unsafe {
let abstract_session = crate::ffi::blpapi_Session_getAbstractSession(self.ptr);
crate::ffi::blpapi_AbstractSession_generateAuthorizedIdentityAsync(
abstract_session,
auth_options.as_ptr(),
&mut cid_ffi,
)
};
if rc != 0 {
return Err(BlpError::Internal {
detail: format!("generateAuthorizedIdentityAsync failed with rc={rc}"),
});
}
Ok(())
}
pub fn authorized_identity(&self, cid: &CorrelationId) -> Result<crate::Identity> {
let cid_ffi = cid.to_ffi();
let mut identity_ptr: *mut crate::ffi::blpapi_Identity_t = std::ptr::null_mut();
let rc = unsafe {
let abstract_session = crate::ffi::blpapi_Session_getAbstractSession(self.ptr);
crate::ffi::blpapi_AbstractSession_getAuthorizedIdentity(
abstract_session,
&cid_ffi,
&mut identity_ptr,
)
};
if rc != 0 {
return Err(BlpError::Internal {
detail: format!("getAuthorizedIdentity failed with rc={rc}"),
});
}
crate::Identity::from_raw(identity_ptr)
}
pub fn generate_token(&self, cid: &CorrelationId) -> Result<()> {
self.operations().generate_token(Some(cid)).map(|_| ())
}
pub fn create_identity(&self) -> Result<crate::Identity> {
self.operations().create_identity()
}
pub fn send_authorization_request(
&self,
request: &Request,
identity: &mut crate::Identity,
cid: &CorrelationId,
) -> Result<()> {
self.operations()
.send_authorization_request(request, identity, Some(cid))
.map(|_| ())
}
}
impl Drop for AsyncSession {
fn drop(&mut self) {
if !self.ptr.is_null() {
unsafe {
crate::ffi::blpapi_Session_stop(self.ptr);
crate::ffi::blpapi_Session_destroy(self.ptr);
}
self.ptr = std::ptr::null_mut();
}
}
}