1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use thiserror::Error;
6 
7 use crate::bindings;
8 
9 /// A wrapper over `VAGenericValue` giving us safe access to the underlying union members.
10 #[derive(Debug)]
11 pub enum GenericValue {
12     /// A wrapper over VAGenericValueTypeInteger
13     Integer(i32),
14     /// A wrapper over VAGenericValueTypeFloat
15     Float(f32),
16     /// A wrapper over VAGenericValueTypePointer
17     Pointer(*mut std::os::raw::c_void),
18     /// A wrapper over VAGenericValueTypeFunc
19     Func(bindings::VAGenericFunc),
20 }
21 
22 #[derive(Debug, Error)]
23 pub enum GenericValueError {
24     #[error("unexpected VAGenericValueType {0}")]
25     UnexpectedType(u32),
26 }
27 
28 impl TryFrom<bindings::VAGenericValue> for GenericValue {
29     type Error = GenericValueError;
30 
try_from(value: bindings::VAGenericValue) -> Result<Self, Self::Error>31     fn try_from(value: bindings::VAGenericValue) -> Result<Self, Self::Error> {
32         // Safe because we check the type before accessing the union.
33         match value.type_ {
34             // Safe because we check the type before accessing the union.
35             bindings::VAGenericValueType::VAGenericValueTypeInteger => {
36                 Ok(Self::Integer(unsafe { value.value.i }))
37             }
38             bindings::VAGenericValueType::VAGenericValueTypeFloat => {
39                 Ok(Self::Float(unsafe { value.value.f }))
40             }
41             bindings::VAGenericValueType::VAGenericValueTypePointer => {
42                 Ok(Self::Pointer(unsafe { value.value.p }))
43             }
44             bindings::VAGenericValueType::VAGenericValueTypeFunc => {
45                 Ok(Self::Func(unsafe { value.value.fn_ }))
46             }
47             _ => Err(GenericValueError::UnexpectedType(value.type_)),
48         }
49     }
50 }
51