use crate::{ffi, CorrelationId, Element, Name};
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use std::rc::Rc;
#[repr(transparent)]
pub struct Message<'a> {
ptr: *mut ffi::blpapi_Message_t,
_life: PhantomData<&'a ()>,
_marker: PhantomData<Rc<()>>, }
impl<'a> Message<'a> {
#[inline]
pub(crate) unsafe fn from_raw(ptr: *mut ffi::blpapi_Message_t) -> Self {
Self {
ptr,
_life: PhantomData,
_marker: PhantomData,
}
}
#[inline(always)]
pub fn elements(&self) -> Element<'a> {
let ptr = unsafe { ffi::blpapi_Message_elements(self.ptr) };
Element::new(ptr)
}
#[inline(always)]
pub fn message_type(&self) -> Name {
self.name()
}
#[inline(always)]
pub fn name(&self) -> Name {
let ptr = unsafe { ffi::blpapi_Message_messageType(self.ptr) };
unsafe { Name::from_raw(NonNull::new(ffi::blpapi_Name_duplicate(ptr)).unwrap()) }
}
#[inline(always)]
pub fn type_str(&self) -> &'a str {
let ptr = unsafe { ffi::blpapi_Message_typeString(self.ptr) };
unsafe { std::ffi::CStr::from_ptr(ptr) }
.to_str()
.expect("Bloomberg message type contained invalid UTF-8")
}
#[inline(always)]
pub fn name_key(&self) -> usize {
unsafe { ffi::blpapi_Message_messageType(self.ptr) as usize }
}
#[inline(always)]
pub fn name_eq(&self, other: &Name) -> bool {
let ptr = unsafe { ffi::blpapi_Message_messageType(self.ptr) };
ptr == other.as_ptr()
}
#[inline]
pub fn time_received_us(&self) -> Option<i64> {
let mut tp = MaybeUninit::<ffi::blpapi_TimePoint_t>::uninit();
let rc = unsafe { ffi::blpapi_Message_timeReceived(self.ptr as *const _, tp.as_mut_ptr()) };
if rc != 0 {
return None;
}
let tp = unsafe { tp.assume_init() };
let mut dt = MaybeUninit::<ffi::blpapi_HighPrecisionDatetime_t>::uninit();
let rc =
unsafe { ffi::blpapi_HighPrecisionDatetime_fromTimePoint(dt.as_mut_ptr(), &tp, 0) };
if rc != 0 {
return None;
}
let hpdt = crate::HighPrecisionDatetime(unsafe { dt.assume_init() });
Some(hpdt.to_micros())
}
#[inline(always)]
#[allow(dead_code)] pub(crate) fn as_ptr(&self) -> *mut ffi::blpapi_Message_t {
self.ptr
}
#[inline(always)]
pub fn num_correlation_ids(&self) -> usize {
let count = unsafe { ffi::blpapi_Message_numCorrelationIds(self.ptr) };
count.max(0) as usize
}
#[inline]
pub fn correlation_id(&self, index: usize) -> Option<CorrelationId> {
if index >= self.num_correlation_ids() {
return None;
}
unsafe {
let cid = ffi::blpapi_Message_correlationId(self.ptr, index);
Some(CorrelationId::from_ffi(&cid))
}
}
#[inline]
pub fn correlation_ids(&self) -> CorrelationIdIter<'_, 'a> {
CorrelationIdIter {
msg: self,
idx: 0,
len: self.num_correlation_ids(),
}
}
}
pub struct CorrelationIdIter<'m, 'a> {
msg: &'m Message<'a>,
idx: usize,
len: usize,
}
impl Iterator for CorrelationIdIter<'_, '_> {
type Item = CorrelationId;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.idx < self.len {
let i = self.idx;
self.idx += 1;
unsafe {
let cid = ffi::blpapi_Message_correlationId(self.msg.ptr, i);
Some(CorrelationId::from_ffi(&cid))
}
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.len - self.idx;
(remaining, Some(remaining))
}
}
impl ExactSizeIterator for CorrelationIdIter<'_, '_> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_message_size() {
assert_eq!(
std::mem::size_of::<Message>(),
std::mem::size_of::<*mut ()>()
);
}
#[test]
fn test_message_alignment() {
assert_eq!(
std::mem::align_of::<Message>(),
std::mem::align_of::<*mut ()>()
);
}
}