From 14bbab5a493e250e8e16427e235e983f00004464 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sun, 3 Apr 2022 13:48:47 +0200 Subject: [PATCH] Make it safer and add TryFrom support --- Cargo.toml | 4 +- src/fe/mod.rs | 2 +- src/fe/sys.rs | 114 ++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 00b4f22..83448a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] 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" authors = ["Cesbo Developers Team ", "Daniil Gentili "] license = "MIT" @@ -16,4 +16,4 @@ nix = "^0.23" anyhow = "^1.0" strum = { git = "https://github.com/danog/strum", features = ["derive"] } bitflags = "^1.3.2" -itertools = "^0.10.2" +itertools = "^0.10.2" \ No newline at end of file diff --git a/src/fe/mod.rs b/src/fe/mod.rs index dc7c66e..3f2ecd7 100644 --- a/src/fe/mod.rs +++ b/src/fe/mod.rs @@ -101,7 +101,7 @@ macro_rules! get_dtv_properties { macro_rules! set_dtv_properties { ( $device:expr, $( $property:ident($data:expr) ),+ ) => { $device.set_properties(&[ - $( $property($crate::fe::sys::DtvPropertyRequest::new($data)), )* + $( $crate::dtv_property!($property($data)), )* ]) }; } diff --git a/src/fe/sys.rs b/src/fe/sys.rs index 9ce5f27..2cbcb36 100644 --- a/src/fe/sys.rs +++ b/src/fe/sys.rs @@ -1,5 +1,7 @@ use anyhow::Context; +use std::convert::TryFrom; use std::fmt::Debug; +use std::marker::PhantomData; use std::str::FromStr; use std::{fmt, mem}; @@ -194,6 +196,12 @@ pub enum fe_sec_voltage { SEC_VOLTAGE_OFF = 2, } +impl Into for fe_sec_voltage { + fn into(self) -> u32 { + self as u32 + } +} + #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, Copy, Clone, PartialEq, Eq, FromRepr)] @@ -204,6 +212,12 @@ pub enum fe_sec_tone_mode { SEC_TONE_OFF = 1, } +impl Into for fe_sec_tone_mode { + fn into(self) -> u32 { + self as u32 + } +} + /// Type of mini burst to be sent #[repr(u32)] #[allow(non_camel_case_types)] @@ -215,6 +229,12 @@ pub enum fe_sec_mini_cmd { SEC_MINI_B = 1, } +impl Into for fe_sec_mini_cmd { + fn into(self) -> u32 { + self as u32 + } +} + bitflags! { /// Enumerates the possible frontend status #[repr(C)] @@ -252,6 +272,12 @@ pub enum fe_spectral_inversion { INVERSION_AUTO = 2, } +impl Into for fe_spectral_inversion { + fn into(self) -> u32 { + self as u32 + } +} + #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Clone, Copy)] @@ -289,6 +315,11 @@ pub enum fe_code_rate { FEC_1_3 = 14, } +impl Into for fe_code_rate { + fn into(self) -> u32 { + self as u32 + } +} /// Type of modulation/constellation #[repr(u32)] #[allow(non_camel_case_types)] @@ -329,6 +360,11 @@ pub enum fe_modulation { APSK_256 = 16, } +impl Into for fe_modulation { + fn into(self) -> u32 { + self as u32 + } +} #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] @@ -353,6 +389,11 @@ pub enum fe_transmit_mode { TRANSMISSION_MODE_C3780 = 8, } +impl Into for fe_transmit_mode { + fn into(self) -> u32 { + self as u32 + } +} #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] @@ -381,6 +422,12 @@ pub enum fe_guard_interval { GUARD_INTERVAL_PN945 = 10, } +impl Into for fe_guard_interval { + fn into(self) -> u32 { + self as u32 + } +} + #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] @@ -397,6 +444,12 @@ pub enum fe_hierarchy { HIERARCHY_AUTO = 4, } +impl Into for fe_hierarchy { + fn into(self) -> u32 { + self as u32 + } +} + #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] @@ -411,6 +464,12 @@ pub enum fe_interleaving { INTERLEAVING_720 = 3, } +impl Into for fe_interleaving { + fn into(self) -> u32 { + self as u32 + } +} + #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] @@ -420,6 +479,11 @@ pub enum fe_pilot { PILOT_AUTO = 2, } +impl Into for fe_pilot { + fn into(self) -> u32 { + self as u32 + } +} #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] @@ -433,6 +497,12 @@ pub enum fe_rolloff { ROLLOFF_5 = 6, } +impl Into for fe_rolloff { + fn into(self) -> u32 { + self as u32 + } +} + #[derive(EnumString, Display, FromRepr, Debug, Copy, Clone)] #[repr(u32)] #[allow(non_camel_case_types)] @@ -480,6 +550,12 @@ pub enum fe_delivery_system { SYS_DVBC2 = 19, } +impl Into for fe_delivery_system { + fn into(self) -> u32 { + self as u32 + } +} + #[repr(u32)] #[allow(non_camel_case_types)] #[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] @@ -489,6 +565,12 @@ pub enum fe_lna { LNA_AUTO = 0xFFFFFFFF, } +impl Into for fe_lna { + fn into(self) -> u32 { + self as u32 + } +} + // From here on, structures passed to Linux pub trait WrappedSlice { fn slice(&self) -> &[T]; @@ -498,6 +580,7 @@ pub trait WrappedResult { fn get(&self) -> anyhow::Result; } + pub trait DtvStatType { fn get_decibel(&self) -> Option; fn get_relative(&self) -> Option; @@ -647,14 +730,15 @@ impl Debug for DtvPropertyBuffer { const DATA_SIZE: usize = 56; #[repr(C, packed)] -pub struct DtvPropertyRequest { +pub struct DtvPropertyRequest { __reserved: [u32; 3], data: T, padding: [u8; N], result: i32, // Unused + fake: PhantomData } -impl DtvPropertyRequest { +impl DtvPropertyRequest { #[inline] pub fn new(data: T) -> Self { Self { @@ -662,18 +746,19 @@ impl DtvPropertyRequest { data, padding: [0; N], result: 0, + fake: PhantomData } } } -impl Default for DtvPropertyRequest { +impl Default for DtvPropertyRequest { #[inline] fn default() -> Self { unsafe { mem::zeroed::() } } } -pub type DtvPropertyRequestVoid = DtvPropertyRequest<(), DATA_SIZE>; +pub type DtvPropertyRequestVoid = DtvPropertyRequest<(), (), DATA_SIZE>; impl WrappedResult<()> for DtvPropertyRequestVoid { #[inline] @@ -688,22 +773,22 @@ impl Debug for DtvPropertyRequestVoid { } } -pub type DtvPropertyRequestInt = DtvPropertyRequest; +pub type DtvPropertyRequestInt = DtvPropertyRequest; -impl WrappedResult for DtvPropertyRequestInt { +impl> WrappedResult for DtvPropertyRequestInt { #[inline] fn get(&self) -> anyhow::Result { - Ok(self.data) + Context::with_context(T::try_from(self.data), ||format!("Got invalid value when extracting {}", stringify!(T))) } } -impl Debug for DtvPropertyRequestInt { +impl> Debug for DtvPropertyRequestInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.get().unwrap().fmt(f) } } -pub type DtvPropertyRequestFrontendStats = DtvPropertyRequest; +pub type DtvPropertyRequestFrontendStats = DtvPropertyRequest; impl WrappedResult for DtvPropertyRequestFrontendStats { #[inline] @@ -719,7 +804,7 @@ impl Debug for DtvPropertyRequestFrontendStats { } pub type DtvPropertyRequestDeliverySystems = - DtvPropertyRequest; + DtvPropertyRequest, { DATA_SIZE - 4 - 32 }>; impl WrappedResult> for DtvPropertyRequestDeliverySystems { #[inline] @@ -861,13 +946,13 @@ pub enum DtvProperty { #[macro_export] macro_rules! dtv_property { ( $property:ident ) => { - $property($crate::fe::sys::DtvPropertyRequest::new(())) + dtv_property!($property, ()) }; ( $property:ident($data:expr) ) => { - $property($crate::fe::sys::DtvPropertyRequest::new($data)) + dtv_property!($property, $data) }; ( $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 { type Err = anyhow::Error; fn from_str(s: &str) -> Result {