use std::{ops::Deref, os::raw::c_void, ptr::null, str::from_utf8};
use crate::PdParameters;
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C)]
pub enum ParameterFormat {
Text = 0,
Binary = 1,
}
#[derive(Debug, PartialEq, Eq)]
pub enum ParameterValue<'a> {
Text(&'a str),
Binary(&'a [u8]),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Parameter {
pub len: i32,
pub data: Vec<u8>,
}
impl Parameter {
pub fn decode(&self, format: ParameterFormat) -> Option<ParameterValue<'_>> {
if self.len == -1 {
return None;
}
match format {
ParameterFormat::Binary => Some(ParameterValue::Binary(&self.data[..])),
ParameterFormat::Text => from_utf8(&self.data).ok().map(ParameterValue::Text),
}
}
pub fn null(&self) -> bool {
self.len == -1
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Parameters {
params: Option<Vec<Parameter>>,
format_codes: Option<Vec<ParameterFormat>>,
borrowed: bool,
}
impl Default for Parameters {
fn default() -> Self {
Self {
params: Some(vec![]),
format_codes: Some(vec![]),
borrowed: false,
}
}
}
impl Clone for Parameters {
fn clone(&self) -> Self {
Self {
params: self.params.clone(),
format_codes: self.format_codes.clone(),
borrowed: false,
}
}
}
impl Parameters {
pub fn format_codes(&self) -> &[ParameterFormat] {
self.format_codes.as_ref().unwrap()
}
pub fn parameter_format(&self, param: usize) -> ParameterFormat {
match self.format_codes().len() {
0 => ParameterFormat::Text,
1 => self.format_codes()[0].clone(),
_ => self
.format_codes()
.get(param)
.unwrap_or(&ParameterFormat::Text)
.clone(),
}
}
}
impl Deref for Parameters {
type Target = Vec<Parameter>;
fn deref(&self) -> &Self::Target {
self.params.as_ref().unwrap()
}
}
impl From<PdParameters> for Parameters {
fn from(value: PdParameters) -> Self {
if value.format_codes.is_null() || value.params.is_null() {
return Self {
params: Some(vec![]),
format_codes: Some(vec![]),
borrowed: false,
};
}
let params = unsafe {
Vec::from_raw_parts(
value.params as *mut Parameter,
value.num_params as usize,
value.num_params as usize,
)
};
let format_codes = unsafe {
Vec::from_raw_parts(
value.format_codes as *mut ParameterFormat,
value.num_format_codes as usize,
value.num_format_codes as usize,
)
};
Self {
params: Some(params),
format_codes: Some(format_codes),
borrowed: true,
}
}
}
impl Drop for Parameters {
fn drop(&mut self) {
if self.borrowed {
std::mem::forget(self.params.take());
std::mem::forget(self.format_codes.take());
}
}
}
impl Default for PdParameters {
fn default() -> Self {
Self {
num_params: 0,
params: null::<c_void>() as *mut c_void,
num_format_codes: 0,
format_codes: null::<c_void>() as *mut c_void,
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_empty_params() {
let params = PdParameters::default();
let params: Parameters = params.into();
println!("{:?}", params);
}
}