use error::{ErrorKind, Result};
use odpi::externs;
use odpi::opaque::ODPILob;
use std::convert::TryFrom;
use std::ptr;
use util::ODPIStr;
pub struct Lob {
inner: *mut ODPILob,
}
impl Lob {
#[doc(hidden)]
pub fn inner(&self) -> *mut ODPILob {
self.inner
}
pub fn close_resource(&self) -> Result<()> {
try_dpi!(
externs::dpiLob_closeResource(self.inner),
Ok(()),
ErrorKind::Lob("dpiLob_closeResource".to_string())
)
}
pub fn copy(&self, dst: &mut Self) -> Result<()> {
try_dpi!(
externs::dpiLob_copy(self.inner, &mut dst.inner),
Ok(()),
ErrorKind::Lob("dpiLob_copy".to_string())
)
}
pub fn flush_buffer(&self) -> Result<()> {
try_dpi!(
externs::dpiLob_flushBuffer(self.inner),
Ok(()),
ErrorKind::Lob("dpiLob_flushBuffer".to_string())
)
}
pub fn get_buffer_size(&self, size_in_chars: u64) -> Result<u64> {
let mut size_in_bytes = 0;
try_dpi!(
externs::dpiLob_getBufferSize(self.inner, size_in_chars, &mut size_in_bytes),
Ok(size_in_bytes),
ErrorKind::Lob("dpiLob_getBufferSize".to_string())
)
}
pub fn get_chunk_size(&self) -> Result<u32> {
let mut size = 0;
try_dpi!(
externs::dpiLob_getChunkSize(self.inner, &mut size),
Ok(size),
ErrorKind::Lob("dpiLob_getChunkSize".to_string())
)
}
pub fn get_directory_and_filename(&self) -> Result<(String, String)> {
let mut dir_alias = ptr::null();
let mut dir_alias_len = 0;
let mut filename = ptr::null();
let mut filename_len = 0;
try_dpi!(
externs::dpiLob_getDirectoryAndFileName(
self.inner,
&mut dir_alias,
&mut dir_alias_len,
&mut filename,
&mut filename_len
),
{
let da = if dir_alias.is_null() {
"".to_string()
} else {
let dir_alias_s = ODPIStr::new(dir_alias, dir_alias_len);
dir_alias_s.into()
};
let fn_str = if filename.is_null() {
"".to_string()
} else {
let filename_s = ODPIStr::new(filename, filename_len);
filename_s.into()
};
Ok((da, fn_str))
},
ErrorKind::Lob("dpiLog_getDirectoryAndFilename".to_string())
)
}
pub fn get_file_exists(&self) -> Result<bool> {
let mut exists = 0;
try_dpi!(
externs::dpiLob_getFileExists(self.inner, &mut exists),
Ok(exists == 1),
ErrorKind::Lob("dpiLob_getFileExists".to_string())
)
}
pub fn get_is_resource_open(&self) -> Result<bool> {
let mut open = 0;
try_dpi!(
externs::dpiLob_getIsResourceOpen(self.inner, &mut open),
Ok(open == 1),
ErrorKind::Lob("dpiLob_getIsResourceOpen".to_string())
)
}
pub fn get_size(&self) -> Result<u64> {
let mut size = 0;
try_dpi!(
externs::dpiLob_getSize(self.inner, &mut size),
Ok(size),
ErrorKind::Lob("dpiLob_getSize".to_string())
)
}
pub fn open_resource(&self) -> Result<()> {
try_dpi!(
externs::dpiLob_openResource(self.inner),
Ok(()),
ErrorKind::Lob("dpiLob_openResource".to_string())
)
}
#[cfg_attr(feature = "cargo-clippy", allow(cast_possible_truncation))]
pub fn read_bytes(&self, offset: u64, length: u64) -> Result<Vec<i8>> {
let length_usize: usize = length as usize;
let mut buffer: Vec<i8> = Vec::with_capacity(length_usize);
let buf_ptr = buffer.as_mut_ptr();
let mut buf_len = length;
try_dpi!(
externs::dpiLob_readBytes(self.inner, offset, length, buf_ptr, &mut buf_len),
{
unsafe { buffer.set_len(buf_len as usize) };
Ok(buffer)
},
ErrorKind::Lob("dpiLob_readBytes".to_string())
)
}
pub fn set_directory_and_filename(&self, directory: &str, filename: &str) -> Result<()> {
let dir_s: ODPIStr = TryFrom::try_from(directory)?;
let fn_s: ODPIStr = TryFrom::try_from(filename)?;
try_dpi!(
externs::dpiLob_setDirectoryAndFileName(
self.inner,
dir_s.ptr(),
dir_s.len(),
fn_s.ptr(),
fn_s.len()
),
Ok(()),
ErrorKind::Lob("dpiLob_setDirectoryAndFileName".to_string())
)
}
pub fn set_from_bytes(&self, buffer: &[i8]) -> Result<()> {
let buf_ptr = buffer.as_ptr();
let buf_len = buffer.len() as u64;
try_dpi!(
externs::dpiLob_setFromBytes(self.inner, buf_ptr, buf_len),
Ok(()),
ErrorKind::Lob("dpiLob_setFromBytes".to_string())
)
}
pub fn trim(&self, length: u64) -> Result<()> {
try_dpi!(
externs::dpiLob_trim(self.inner, length),
Ok(()),
ErrorKind::Lob("dpiLob_trim".to_string())
)
}
pub fn write_bytes(&self, buffer: &[i8], offset: u64) -> Result<()> {
let buf_ptr = buffer.as_ptr();
let buf_len = buffer.len() as u64;
try_dpi!(
externs::dpiLob_writeBytes(self.inner, offset, buf_ptr, buf_len),
Ok(()),
ErrorKind::Lob("dpiLob_writeBytes".to_string())
)
}
}
impl From<*mut ODPILob> for Lob {
fn from(inner: *mut ODPILob) -> Self {
Self { inner }
}
}
impl Drop for Lob {
fn drop(&mut self) {
if !self.inner.is_null() {
unsafe {
externs::dpiLob_release(self.inner);
}
}
}
}