start work on nihed-cros-libva
[nihav-player.git] / nihed-cros-libva / src / generic_value.rs
diff --git a/nihed-cros-libva/src/generic_value.rs b/nihed-cros-libva/src/generic_value.rs
new file mode 100644 (file)
index 0000000..3900edc
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2022 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use anyhow::anyhow;
+use anyhow::Result;
+
+use crate::bindings;
+
+/// A wrapper over `VAGenericValue` giving us safe access to the underlying union members.
+#[derive(Debug)]
+pub enum GenericValue {
+    /// A wrapper over VAGenericValueTypeInteger
+    Integer(i32),
+    /// A wrapper over VAGenericValueTypeFloat
+    Float(f32),
+    /// A wrapper over VAGenericValueTypePointer
+    Pointer(*mut std::os::raw::c_void),
+    /// A wrapper over VAGenericValueTypeFunc
+    Func(bindings::VAGenericFunc),
+}
+
+impl TryFrom<bindings::VAGenericValue> for GenericValue {
+    type Error = anyhow::Error;
+
+    fn try_from(value: bindings::VAGenericValue) -> Result<Self, Self::Error> {
+        // Safe because we check the type before accessing the union.
+        match value.type_ {
+            // Safe because we check the type before accessing the union.
+            bindings::VAGenericValueType::VAGenericValueTypeInteger => {
+                Ok(Self::Integer(unsafe { value.value.i }))
+            }
+            bindings::VAGenericValueType::VAGenericValueTypeFloat => {
+                Ok(Self::Float(unsafe { value.value.f }))
+            }
+            bindings::VAGenericValueType::VAGenericValueTypePointer => {
+                Ok(Self::Pointer(unsafe { value.value.p }))
+            }
+            bindings::VAGenericValueType::VAGenericValueTypeFunc => {
+                Ok(Self::Func(unsafe { value.value.fn_ }))
+            }
+            other => Err(anyhow!(
+                "Conversion failed for unexpected VAGenericValueType: {}",
+                other
+            )),
+        }
+    }
+}