use std::ffi::CStr;
use std::marker::PhantomData;
use std::rc::Rc;
use crate::errors::{BlpError, Result};
use crate::ffi;
use super::element_def::SchemaElementDefinition;
#[derive(Clone, Copy)]
pub struct Operation<'service> {
ptr: *mut ffi::blpapi_Operation_t,
_service: PhantomData<&'service ()>,
_not_send_sync: PhantomData<Rc<()>>,
}
impl<'service> Operation<'service> {
pub(crate) unsafe fn from_raw(ptr: *mut ffi::blpapi_Operation_t) -> Option<Self> {
if ptr.is_null() {
None
} else {
Some(Self {
ptr,
_service: PhantomData,
_not_send_sync: PhantomData,
})
}
}
pub fn name(&self) -> &str {
unsafe {
let name_ptr = ffi::blpapi_Operation_name(self.ptr);
if name_ptr.is_null() {
return "";
}
CStr::from_ptr(name_ptr).to_str().unwrap_or("")
}
}
pub fn description(&self) -> &str {
unsafe {
let desc_ptr = ffi::blpapi_Operation_description(self.ptr);
if desc_ptr.is_null() {
return "";
}
CStr::from_ptr(desc_ptr).to_str().unwrap_or("")
}
}
pub fn request_definition(&self) -> Result<SchemaElementDefinition<'service>> {
let mut def_ptr: *mut ffi::blpapi_SchemaElementDefinition_t = std::ptr::null_mut();
let rc = unsafe { ffi::blpapi_Operation_requestDefinition(self.ptr, &mut def_ptr) };
if rc != 0 || def_ptr.is_null() {
return Err(BlpError::Internal {
detail: format!("Failed to get request definition, rc={}", rc),
});
}
Ok(unsafe { SchemaElementDefinition::from_raw_unchecked(def_ptr) })
}
pub fn num_response_definitions(&self) -> usize {
let count = unsafe { ffi::blpapi_Operation_numResponseDefinitions(self.ptr) };
count.max(0) as usize
}
pub fn response_definition(&self, index: usize) -> Result<SchemaElementDefinition<'service>> {
let mut def_ptr: *mut ffi::blpapi_SchemaElementDefinition_t = std::ptr::null_mut();
let rc = unsafe { ffi::blpapi_Operation_responseDefinition(self.ptr, &mut def_ptr, index) };
if rc != 0 || def_ptr.is_null() {
return Err(BlpError::Internal {
detail: format!(
"Failed to get response definition at index {}, rc={}",
index, rc
),
});
}
Ok(unsafe { SchemaElementDefinition::from_raw_unchecked(def_ptr) })
}
pub fn is_valid(&self) -> bool {
!self.ptr.is_null()
}
}
impl std::fmt::Debug for Operation<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Operation")
.field("name", &self.name())
.field("num_response_definitions", &self.num_response_definitions())
.finish()
}
}