use crate::{
helper::{as_ref, chars_to_string, libtool_lock},
try_gp_internal, Result,
};
use std::{fmt, marker::PhantomData};
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum PortType {
Serial,
Usb,
Disk,
PTPIp,
Ip,
UsbDiskDirect,
UsbScsi,
}
pub struct PortInfo<'a> {
pub(crate) inner: libgphoto2_sys::GPPortInfo,
_phantom: std::marker::PhantomData<&'a ()>,
}
impl PortInfo<'_> {
pub(crate) unsafe fn new(inner: libgphoto2_sys::GPPortInfo) -> Self {
Self { inner, _phantom: PhantomData }
}
}
pub(crate) struct PortInfoList {
pub(crate) inner: *mut libgphoto2_sys::GPPortInfoList,
}
impl Drop for PortInfoList {
fn drop(&mut self) {
try_gp_internal!(gp_port_info_list_free(self.inner).unwrap());
}
}
impl fmt::Debug for PortInfo<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PortInfo")
.field("name", &self.name())
.field("path", &self.path())
.field("port_type", &self.port_type())
.finish()
}
}
as_ref!(PortInfoList -> libgphoto2_sys::GPPortInfoList, *self.inner);
as_ref!(PortInfo<'_> -> libgphoto2_sys::GPPortInfo, self.inner);
impl PortType {
fn new(port_type: libgphoto2_sys::GPPortType) -> Option<Self> {
use libgphoto2_sys::GPPortType;
match port_type {
GPPortType::GP_PORT_NONE => None,
GPPortType::GP_PORT_SERIAL => Some(Self::Serial),
GPPortType::GP_PORT_USB => Some(Self::Usb),
GPPortType::GP_PORT_DISK => Some(Self::Disk),
GPPortType::GP_PORT_PTPIP => Some(Self::PTPIp),
GPPortType::GP_PORT_IP => Some(Self::Ip),
GPPortType::GP_PORT_USB_DISK_DIRECT => Some(Self::UsbDiskDirect),
GPPortType::GP_PORT_USB_SCSI => Some(Self::UsbScsi),
}
}
}
impl PortInfo<'_> {
pub fn name(&self) -> String {
try_gp_internal!(gp_port_info_get_name(self.inner, &out name).unwrap());
chars_to_string(name)
}
pub fn path(&self) -> String {
try_gp_internal!(gp_port_info_get_path(self.inner, &out path).unwrap());
chars_to_string(path)
}
pub fn port_type(&self) -> Option<PortType> {
try_gp_internal!(gp_port_info_get_type(self.inner, &out port_type).unwrap());
PortType::new(port_type)
}
}
impl PortInfoList {
pub(crate) fn new() -> Result<Self> {
let _lock = libtool_lock();
try_gp_internal!(gp_port_info_list_new(&out port_info_list)?);
try_gp_internal!(gp_port_info_list_load(port_info_list)?);
Ok(Self { inner: port_info_list })
}
pub(crate) fn get_port_info(&self, p: i32) -> Result<PortInfo<'_>> {
try_gp_internal!(gp_port_info_list_get_info(self.inner, p, &out port_info)?);
Ok(unsafe { PortInfo::new(port_info) })
}
}