summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cubeb-core/src/device_collection.rs
blob: 733c068f146b3a7c0f20a7868b16e101615a303b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

use ffi;
use ffi_types;
use std::{ops, slice};
use {ContextRef, DeviceInfo};

/// A collection of `DeviceInfo` used by libcubeb
type CType = ffi::cubeb_device_collection;

#[derive(Debug)]
pub struct DeviceCollection<'ctx>(CType, &'ctx ContextRef);

impl<'ctx> DeviceCollection<'ctx> {
    pub(crate) fn init_with_ctx(ctx: &ContextRef, coll: CType) -> DeviceCollection {
        DeviceCollection(coll, ctx)
    }

    pub fn as_ptr(&self) -> *mut CType {
        &self.0 as *const CType as *mut CType
    }
}

impl<'ctx> Drop for DeviceCollection<'ctx> {
    fn drop(&mut self) {
        unsafe {
            let _ = call!(ffi::cubeb_device_collection_destroy(
                self.1.as_ptr(),
                &mut self.0
            ));
        }
    }
}

impl<'ctx> ::std::ops::Deref for DeviceCollection<'ctx> {
    type Target = DeviceCollectionRef;

    #[inline]
    fn deref(&self) -> &DeviceCollectionRef {
        let ptr = &self.0 as *const CType as *mut CType;
        unsafe { DeviceCollectionRef::from_ptr(ptr) }
    }
}

impl<'ctx> ::std::convert::AsRef<DeviceCollectionRef> for DeviceCollection<'ctx> {
    #[inline]
    fn as_ref(&self) -> &DeviceCollectionRef {
        self
    }
}

pub struct DeviceCollectionRef(ffi_types::Opaque);

impl DeviceCollectionRef {
    /// # Safety
    ///
    /// This function is unsafe because it dereferences the given `ptr` pointer.
    /// The caller should ensure that pointer is valid.
    #[inline]
    pub unsafe fn from_ptr<'a>(ptr: *mut CType) -> &'a Self {
        &*(ptr as *mut _)
    }

    /// # Safety
    ///
    /// This function is unsafe because it dereferences the given `ptr` pointer.
    /// The caller should ensure that pointer is valid.
    #[inline]
    pub unsafe fn from_ptr_mut<'a>(ptr: *mut CType) -> &'a mut Self {
        &mut *(ptr as *mut _)
    }

    #[inline]
    pub fn as_ptr(&self) -> *mut CType {
        self as *const _ as *mut _
    }
}

impl ::std::fmt::Debug for DeviceCollectionRef {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let ptr = self as *const DeviceCollectionRef as usize;
        f.debug_tuple(stringify!(DeviceCollectionRef))
            .field(&ptr)
            .finish()
    }
}

impl ops::Deref for DeviceCollectionRef {
    type Target = [DeviceInfo];
    fn deref(&self) -> &[DeviceInfo] {
        unsafe {
            let coll: &ffi::cubeb_device_collection = &*self.as_ptr();
            slice::from_raw_parts(coll.device as *const DeviceInfo, coll.count)
        }
    }
}