Skip to content

Commit

Permalink
Wrapper for osdp_pd_info_t to handle dropping of it's fields after us…
Browse files Browse the repository at this point in the history
…e automatically
  • Loading branch information
Sympatron committed Oct 2, 2024
1 parent 909fd41 commit 363eac5
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 45 deletions.
12 changes: 4 additions & 8 deletions libosdp/src/cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,8 @@ where
trampoline::<F>
}

fn cp_setup(info: Vec<libosdp_sys::osdp_pd_info_t>) -> Result<*mut c_void> {
let ctx = unsafe { libosdp_sys::osdp_cp_setup(info.len() as i32, info.as_ptr()) };
for pd in info.into_iter() {
crate::drop_osdp_pd_info(pd);
}
fn cp_setup(info: Vec<crate::OsdpPdInfoHandle>) -> Result<*mut c_void> {
let ctx = unsafe { libosdp_sys::osdp_cp_setup(info.len() as i32, info.as_ptr() as *const _) };
if ctx.is_null() {
Err(OsdpError::Setup)
} else {
Expand All @@ -77,12 +74,11 @@ unsafe impl Send for ControlPanel {}

impl ControlPanel {
/// Create a new CP context for the list of PDs described by the [`PdInfo`] vector.
pub fn new(mut pd_info: Vec<PdInfo>) -> Result<Self> {
pub fn new(pd_info: Vec<PdInfo>) -> Result<Self> {
if pd_info.len() > 126 {
return Err(OsdpError::PdInfo("max PD count exceeded"));
}
let info: Vec<libosdp_sys::osdp_pd_info_t> =
pd_info.iter_mut().map(|i| i.as_struct()).collect();
let info: Vec<crate::OsdpPdInfoHandle> = pd_info.into_iter().map(|i| i.into()).collect();
unsafe { libosdp_sys::osdp_set_log_callback(Some(log_handler)) };
Ok(Self {
ctx: cp_setup(info)?,
Expand Down
8 changes: 4 additions & 4 deletions libosdp/src/pd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ where
trampoline::<F>
}

fn pd_setup(mut info: PdInfo) -> Result<*mut c_void> {
let info_struct = info.as_struct();
let ctx = unsafe { libosdp_sys::osdp_pd_setup(&info_struct) };
crate::drop_osdp_pd_info(info_struct);
fn pd_setup(info: PdInfo) -> Result<*mut c_void> {
let info: crate::OsdpPdInfoHandle = info.into();
let ctx = unsafe { libosdp_sys::osdp_pd_setup(&*info) };
let a = &info.0;

Check failure on line 63 in libosdp/src/pd.rs

View workflow job for this annotation

GitHub Actions / test

unused variable: `a`

Check failure on line 63 in libosdp/src/pd.rs

View workflow job for this annotation

GitHub Actions / lint

unused variable: `a`
if ctx.is_null() {
Err(OsdpError::Setup)
} else {
Expand Down
81 changes: 48 additions & 33 deletions libosdp/src/pdinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//
// SPDX-License-Identifier: Apache-2.0

use core::ops::Deref;

use alloc::ffi::CString;

use crate::{Box, Channel, OsdpError, OsdpFlag, PdCapability, PdId};
Expand Down Expand Up @@ -247,16 +249,26 @@ impl PdInfoBuilder {
}
}

impl PdInfo {
/// Get a C-repr struct for PdInfo that LibOSDP can operate on.
pub fn as_struct(&mut self) -> libosdp_sys::osdp_pd_info_t {
let scbk = if let Some(key) = self.scbk {
#[repr(transparent)]
pub(crate) struct OsdpPdInfoHandle(pub libosdp_sys::osdp_pd_info_t);

impl Deref for OsdpPdInfoHandle {
type Target = libosdp_sys::osdp_pd_info_t;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<PdInfo> for OsdpPdInfoHandle {
fn from(info: PdInfo) -> OsdpPdInfoHandle {
let scbk = if let Some(key) = info.scbk {
Box::into_raw(Box::new(key)) as *mut _
} else {
core::ptr::null_mut::<u8>()
};
let cap = if !self.cap.is_empty() {
let mut cap = self.cap.clone();
let cap = if !info.cap.is_empty() {
let mut cap = info.cap.clone();
cap.reserve(1);
cap.push(libosdp_sys::osdp_pd_cap {
function_code: -1i8 as u8,
Expand All @@ -267,39 +279,42 @@ impl PdInfo {
} else {
core::ptr::null_mut::<libosdp_sys::osdp_pd_cap>()
};
libosdp_sys::osdp_pd_info_t {
name: self.name.clone().into_raw(),
baud_rate: self.baud_rate,
address: self.address,
flags: self.flags.bits() as i32,
id: self.id.into(),
OsdpPdInfoHandle(libosdp_sys::osdp_pd_info_t {
name: info.name.clone().into_raw(),
baud_rate: info.baud_rate,
address: info.address,
flags: info.flags.bits() as i32,
id: info.id.into(),
cap: cap as *mut _,
channel: self.channel.take().unwrap().into(),
channel: info.channel.unwrap().into(),
scbk,
}
})
}
}

pub(crate) fn drop_osdp_pd_info(info: libosdp_sys::osdp_pd_info_t) {
unsafe {
// The name is not copied by LibOSDP, so we cannot drop it here
// if !info.name.is_null() {
// drop(CString::from_raw(info.name as *mut _));
// }
if !info.cap.is_null() {
let mut cap = info.cap as *mut libosdp_sys::osdp_pd_cap;
while (*cap).function_code != -1i8 as u8 {
cap = cap.add(1);
impl Drop for OsdpPdInfoHandle {
fn drop(&mut self) {
unsafe {
let info = self.0;
// LibOSDP versions <= 3.0.6 do not copy the name, so this is only valid for >= 3.0.7
if !info.name.is_null() {
drop(CString::from_raw(info.name as *mut _));
}
if !info.cap.is_null() {
let mut cap = info.cap as *mut libosdp_sys::osdp_pd_cap;
while (*cap).function_code != -1i8 as u8 {
cap = cap.add(1);
}
let len = (cap.offset_from(info.cap) + 1) as usize;
drop(Vec::from_raw_parts(
info.cap as *mut libosdp_sys::osdp_pd_cap,
len,
len,
));
}
if !info.scbk.is_null() {
drop(Box::from_raw(info.scbk as *mut [u8; 16]));
}
let len = (cap.offset_from(info.cap) + 1) as usize;
drop(Vec::from_raw_parts(
info.cap as *mut libosdp_sys::osdp_pd_cap,
len,
len,
));
}
if !info.scbk.is_null() {
drop(Box::from_raw(info.scbk as *mut [u8; 16]));
}
}
}

0 comments on commit 363eac5

Please sign in to comment.