soapysdr/
arginfo.rs

1use soapysdr_sys::*;
2use std::slice;
3
4use std::ffi::CStr;
5use std::os::raw::c_char;
6
7#[derive(Copy, Clone, Eq, PartialEq, Debug)]
8pub enum ArgType {
9    Bool,
10    Float,
11    Int,
12    String,
13    __Nonexhaustive,
14}
15
16impl From<SoapySDRArgInfoType> for ArgType {
17    #[allow(non_upper_case_globals)]
18    fn from(arg_info_type: SoapySDRArgInfoType) -> Self {
19        match arg_info_type {
20            SoapySDRArgInfoType_SOAPY_SDR_ARG_INFO_BOOL => ArgType::Bool,
21            SoapySDRArgInfoType_SOAPY_SDR_ARG_INFO_FLOAT => ArgType::Float,
22            SoapySDRArgInfoType_SOAPY_SDR_ARG_INFO_INT => ArgType::Int,
23            SoapySDRArgInfoType_SOAPY_SDR_ARG_INFO_STRING => ArgType::String,
24            _ => ArgType::__Nonexhaustive,
25        }
26    }
27}
28
29
30/// Metadata about supported arguments.
31#[derive(Debug)]
32pub struct ArgInfo {
33    /// The key used to identify the argument
34    pub key: String,
35
36    /// The default value of the argument when not specified
37    pub value: String,
38
39    /// The displayable name of the argument
40    pub name: Option<String>,
41
42    ///  A brief description about the argument
43    pub description: Option<String>,
44
45    /// The units of the argument: dB, Hz, etc
46    pub units: Option<String>,
47
48    /// The data type of the argument
49    pub data_type: ArgType,
50
51    /// A discrete list of possible values.
52    ///
53    /// When specified, the argument should be restricted to this options set.
54    pub options: Vec<(String, Option<String>)>,
55}
56
57unsafe fn required_string(s: *mut c_char) -> String {
58    assert!(!s.is_null(), "Null string from SoapySDR");
59    CStr::from_ptr(s).to_string_lossy().into()
60}
61
62unsafe fn optional_string(s: *mut c_char) -> Option<String> {
63    if !s.is_null() {
64        Some(CStr::from_ptr(s).to_string_lossy().into())
65    } else {
66        None
67    }
68}
69
70pub unsafe fn arg_info_from_c(c: &SoapySDRArgInfo) -> ArgInfo {
71    ArgInfo {
72        key:         required_string(c.key),
73        value:       required_string(c.value),
74        name:        optional_string(c.name),
75        description: optional_string(c.description),
76        units:       optional_string(c.units),
77        data_type:   c.type_.into(),
78        options: {
79            let option_vals = slice::from_raw_parts(c.options, c.numOptions);
80            let option_names = slice::from_raw_parts(c.optionNames, c.numOptions);
81            option_vals.iter().zip(option_names.iter()).map(|(&name, &val)| {
82                (required_string(name), optional_string(val))
83            }).collect()
84        }
85    }
86}