babeltrace2-sys 0.2.8

Rust sys crate for babeltrace2
use crate::{ffi, util, BtResult, Env, EnvValue, Error};
use std::collections::BTreeMap;
use std::convert::TryInto;
use std::{ptr, slice};
use uuid::Uuid;

pub struct Trace {
    pub(crate) inner: *const ffi::bt_trace,
}

impl Trace {
    pub fn properties(&self) -> BtResult<TraceProperties> {
        use ffi::bt_value_type::*;

        let name_cstr = unsafe { ffi::bt_trace_get_name(self.inner) };
        let name = util::opt_owned_cstr(name_cstr)?;

        let uuid_raw = unsafe { ffi::bt_trace_get_uuid(self.inner) };
        let uuid = if uuid_raw.is_null() {
            None
        } else {
            let bytes: uuid::Bytes = unsafe { slice::from_raw_parts(uuid_raw, 16) }
                .try_into()
                .map_err(|_| Error::Uuid)?;
            Uuid::from_bytes(bytes).into()
        };

        let env_count = unsafe { ffi::bt_trace_get_environment_entry_count(self.inner) };
        let env = if env_count == 0 {
            None
        } else {
            let mut entries: BTreeMap<String, EnvValue> = Default::default();
            for idx in 0..env_count {
                let mut env_name = ptr::null();
                let mut env_val = ptr::null();
                unsafe {
                    ffi::bt_trace_borrow_environment_entry_by_index_const(
                        self.inner,
                        idx,
                        &mut env_name,
                        &mut env_val,
                    )
                };
                if let Some(key) = util::opt_owned_cstr(env_name)? {
                    match unsafe { ffi::bt_value_get_type(env_val) } {
                        BT_VALUE_TYPE_SIGNED_INTEGER => {
                            let v = unsafe { ffi::bt_value_integer_signed_get(env_val) };
                            entries.insert(key, EnvValue::Integer(v));
                        }
                        BT_VALUE_TYPE_STRING => {
                            let v = unsafe { ffi::bt_value_string_get(env_val) };
                            if let Some(val) = util::opt_owned_cstr(v)? {
                                entries.insert(key, EnvValue::String(val));
                            }
                        }
                        typ => {
                            log::error!(
                                "Environment value for key '{}' must be either string or integer (got {})",
                                key, typ
                            );
                            unsafe { ffi::bt_value_put_ref(env_val) };
                            return Err(Error::EnvValue);
                        }
                    }
                }
            }
            Env { entries }.into()
        };

        Ok(TraceProperties { name, uuid, env })
    }
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct TraceProperties {
    pub name: Option<String>,
    pub uuid: Option<Uuid>,
    pub env: Option<Env>,
}