1
0
mirror of https://github.com/danog/libdvb.git synced 2024-11-26 20:04:39 +01:00

Make it safer and add TryFrom support

This commit is contained in:
Daniil Gentili 2022-04-03 13:48:47 +02:00
parent 56e689656b
commit 14bbab5a49
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
3 changed files with 104 additions and 16 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "libdvb-rs" name = "libdvb-rs"
version = "0.4.5" version = "0.4.6"
description = "Safer and feature-complete pure-Rust interface for DVB-API v5 devices in Linux" description = "Safer and feature-complete pure-Rust interface for DVB-API v5 devices in Linux"
authors = ["Cesbo Developers Team <info@cesbo.com>", "Daniil Gentili <daniil@daniil.it>"] authors = ["Cesbo Developers Team <info@cesbo.com>", "Daniil Gentili <daniil@daniil.it>"]
license = "MIT" license = "MIT"

View File

@ -101,7 +101,7 @@ macro_rules! get_dtv_properties {
macro_rules! set_dtv_properties { macro_rules! set_dtv_properties {
( $device:expr, $( $property:ident($data:expr) ),+ ) => { ( $device:expr, $( $property:ident($data:expr) ),+ ) => {
$device.set_properties(&[ $device.set_properties(&[
$( $property($crate::fe::sys::DtvPropertyRequest::new($data)), )* $( $crate::dtv_property!($property($data)), )*
]) ])
}; };
} }

View File

@ -1,5 +1,7 @@
use anyhow::Context; use anyhow::Context;
use std::convert::TryFrom;
use std::fmt::Debug; use std::fmt::Debug;
use std::marker::PhantomData;
use std::str::FromStr; use std::str::FromStr;
use std::{fmt, mem}; use std::{fmt, mem};
@ -194,6 +196,12 @@ pub enum fe_sec_voltage {
SEC_VOLTAGE_OFF = 2, SEC_VOLTAGE_OFF = 2,
} }
impl Into<u32> for fe_sec_voltage {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, Copy, Clone, PartialEq, Eq, FromRepr)] #[derive(EnumString, Debug, Copy, Clone, PartialEq, Eq, FromRepr)]
@ -204,6 +212,12 @@ pub enum fe_sec_tone_mode {
SEC_TONE_OFF = 1, SEC_TONE_OFF = 1,
} }
impl Into<u32> for fe_sec_tone_mode {
fn into(self) -> u32 {
self as u32
}
}
/// Type of mini burst to be sent /// Type of mini burst to be sent
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -215,6 +229,12 @@ pub enum fe_sec_mini_cmd {
SEC_MINI_B = 1, SEC_MINI_B = 1,
} }
impl Into<u32> for fe_sec_mini_cmd {
fn into(self) -> u32 {
self as u32
}
}
bitflags! { bitflags! {
/// Enumerates the possible frontend status /// Enumerates the possible frontend status
#[repr(C)] #[repr(C)]
@ -252,6 +272,12 @@ pub enum fe_spectral_inversion {
INVERSION_AUTO = 2, INVERSION_AUTO = 2,
} }
impl Into<u32> for fe_spectral_inversion {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Clone, Copy)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Clone, Copy)]
@ -289,6 +315,11 @@ pub enum fe_code_rate {
FEC_1_3 = 14, FEC_1_3 = 14,
} }
impl Into<u32> for fe_code_rate {
fn into(self) -> u32 {
self as u32
}
}
/// Type of modulation/constellation /// Type of modulation/constellation
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -329,6 +360,11 @@ pub enum fe_modulation {
APSK_256 = 16, APSK_256 = 16,
} }
impl Into<u32> for fe_modulation {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -353,6 +389,11 @@ pub enum fe_transmit_mode {
TRANSMISSION_MODE_C3780 = 8, TRANSMISSION_MODE_C3780 = 8,
} }
impl Into<u32> for fe_transmit_mode {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -381,6 +422,12 @@ pub enum fe_guard_interval {
GUARD_INTERVAL_PN945 = 10, GUARD_INTERVAL_PN945 = 10,
} }
impl Into<u32> for fe_guard_interval {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -397,6 +444,12 @@ pub enum fe_hierarchy {
HIERARCHY_AUTO = 4, HIERARCHY_AUTO = 4,
} }
impl Into<u32> for fe_hierarchy {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -411,6 +464,12 @@ pub enum fe_interleaving {
INTERLEAVING_720 = 3, INTERLEAVING_720 = 3,
} }
impl Into<u32> for fe_interleaving {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -420,6 +479,11 @@ pub enum fe_pilot {
PILOT_AUTO = 2, PILOT_AUTO = 2,
} }
impl Into<u32> for fe_pilot {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -433,6 +497,12 @@ pub enum fe_rolloff {
ROLLOFF_5 = 6, ROLLOFF_5 = 6,
} }
impl Into<u32> for fe_rolloff {
fn into(self) -> u32 {
self as u32
}
}
#[derive(EnumString, Display, FromRepr, Debug, Copy, Clone)] #[derive(EnumString, Display, FromRepr, Debug, Copy, Clone)]
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -480,6 +550,12 @@ pub enum fe_delivery_system {
SYS_DVBC2 = 19, SYS_DVBC2 = 19,
} }
impl Into<u32> for fe_delivery_system {
fn into(self) -> u32 {
self as u32
}
}
#[repr(u32)] #[repr(u32)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -489,6 +565,12 @@ pub enum fe_lna {
LNA_AUTO = 0xFFFFFFFF, LNA_AUTO = 0xFFFFFFFF,
} }
impl Into<u32> for fe_lna {
fn into(self) -> u32 {
self as u32
}
}
// From here on, structures passed to Linux // From here on, structures passed to Linux
pub trait WrappedSlice<T> { pub trait WrappedSlice<T> {
fn slice(&self) -> &[T]; fn slice(&self) -> &[T];
@ -498,6 +580,7 @@ pub trait WrappedResult<T> {
fn get(&self) -> anyhow::Result<T>; fn get(&self) -> anyhow::Result<T>;
} }
pub trait DtvStatType { pub trait DtvStatType {
fn get_decibel(&self) -> Option<i64>; fn get_decibel(&self) -> Option<i64>;
fn get_relative(&self) -> Option<u16>; fn get_relative(&self) -> Option<u16>;
@ -647,14 +730,15 @@ impl Debug for DtvPropertyBuffer {
const DATA_SIZE: usize = 56; const DATA_SIZE: usize = 56;
#[repr(C, packed)] #[repr(C, packed)]
pub struct DtvPropertyRequest<T, const N: usize> { pub struct DtvPropertyRequest<T, TFake, const N: usize> {
__reserved: [u32; 3], __reserved: [u32; 3],
data: T, data: T,
padding: [u8; N], padding: [u8; N],
result: i32, // Unused result: i32, // Unused
fake: PhantomData<TFake>
} }
impl<T, const N: usize> DtvPropertyRequest<T, N> { impl<T, TFake, const N: usize> DtvPropertyRequest<T, TFake, N> {
#[inline] #[inline]
pub fn new(data: T) -> Self { pub fn new(data: T) -> Self {
Self { Self {
@ -662,18 +746,19 @@ impl<T, const N: usize> DtvPropertyRequest<T, N> {
data, data,
padding: [0; N], padding: [0; N],
result: 0, result: 0,
fake: PhantomData
} }
} }
} }
impl<T, const N: usize> Default for DtvPropertyRequest<T, N> { impl<T, TFake, const N: usize> Default for DtvPropertyRequest<T, TFake, N> {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
unsafe { mem::zeroed::<Self>() } unsafe { mem::zeroed::<Self>() }
} }
} }
pub type DtvPropertyRequestVoid = DtvPropertyRequest<(), DATA_SIZE>; pub type DtvPropertyRequestVoid = DtvPropertyRequest<(), (), DATA_SIZE>;
impl WrappedResult<()> for DtvPropertyRequestVoid { impl WrappedResult<()> for DtvPropertyRequestVoid {
#[inline] #[inline]
@ -688,22 +773,22 @@ impl Debug for DtvPropertyRequestVoid {
} }
} }
pub type DtvPropertyRequestInt<T> = DtvPropertyRequest<T, { DATA_SIZE - 4 }>; pub type DtvPropertyRequestInt<T> = DtvPropertyRequest<u32, T, { DATA_SIZE - 4 }>;
impl<T: Copy + Debug> WrappedResult<T> for DtvPropertyRequestInt<T> { impl<Err: 'static + std::error::Error + Send + Sync, T: Copy + Debug + TryFrom<u32, Error = Err>> WrappedResult<T> for DtvPropertyRequestInt<T> {
#[inline] #[inline]
fn get(&self) -> anyhow::Result<T> { fn get(&self) -> anyhow::Result<T> {
Ok(self.data) Context::with_context(T::try_from(self.data), ||format!("Got invalid value when extracting {}", stringify!(T)))
} }
} }
impl<T: Copy + Debug> Debug for DtvPropertyRequestInt<T> { impl<Err: 'static + std::error::Error + Send + Sync, T: Copy + Debug + TryFrom<u32, Error = Err>> Debug for DtvPropertyRequestInt<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.get().unwrap().fmt(f) self.get().unwrap().fmt(f)
} }
} }
pub type DtvPropertyRequestFrontendStats = DtvPropertyRequest<DtvFrontendStats, { DATA_SIZE - 37 }>; pub type DtvPropertyRequestFrontendStats = DtvPropertyRequest<DtvFrontendStats, DtvFrontendStats, { DATA_SIZE - 37 }>;
impl WrappedResult<DtvFrontendStats> for DtvPropertyRequestFrontendStats { impl WrappedResult<DtvFrontendStats> for DtvPropertyRequestFrontendStats {
#[inline] #[inline]
@ -719,7 +804,7 @@ impl Debug for DtvPropertyRequestFrontendStats {
} }
pub type DtvPropertyRequestDeliverySystems = pub type DtvPropertyRequestDeliverySystems =
DtvPropertyRequest<DtvPropertyBuffer, { DATA_SIZE - 4 - 32 }>; DtvPropertyRequest<DtvPropertyBuffer, Vec<fe_delivery_system>, { DATA_SIZE - 4 - 32 }>;
impl WrappedResult<Vec<fe_delivery_system>> for DtvPropertyRequestDeliverySystems { impl WrappedResult<Vec<fe_delivery_system>> for DtvPropertyRequestDeliverySystems {
#[inline] #[inline]
@ -861,13 +946,13 @@ pub enum DtvProperty {
#[macro_export] #[macro_export]
macro_rules! dtv_property { macro_rules! dtv_property {
( $property:ident ) => { ( $property:ident ) => {
$property($crate::fe::sys::DtvPropertyRequest::new(())) dtv_property!($property, ())
}; };
( $property:ident($data:expr) ) => { ( $property:ident($data:expr) ) => {
$property($crate::fe::sys::DtvPropertyRequest::new($data)) dtv_property!($property, $data)
}; };
( $property:ident, $data:expr ) => { ( $property:ident, $data:expr ) => {
$property($crate::fe::sys::DtvPropertyRequest::new($data)) $property($crate::fe::sys::DtvPropertyRequest::new($data.into()))
}; };
} }
@ -878,6 +963,9 @@ macro_rules! dtv_property_parse {
}; };
} }
pub(crate) use dtv_property;
pub(crate) use dtv_property_parse;
impl FromStr for DtvProperty { impl FromStr for DtvProperty {
type Err = anyhow::Error; type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {