blob: a3a9dc62580de87f5192250421e046f345cc619b [file] [log] [blame]
Andrew Walbran9487efd2024-08-20 18:37:59 +01001// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{mem::forget, ptr::NonNull};
16
17/// Rust wrapper around `native_handle_t`.
18///
19/// This owns the `native_handle_t` and its file descriptors, and will close them and free it when
20/// it is dropped.
21#[derive(Debug)]
22pub struct NativeHandle(NonNull<ffi::native_handle_t>);
23
24impl NativeHandle {
25 /// Wraps a raw `native_handle_t` pointer, taking ownership of it.
26 ///
27 /// # Safety
28 ///
29 /// `native_handle` must be a valid pointer to a `native_handle_t`, and must not be used
30 /// anywhere else after calling this method.
31 pub unsafe fn from_raw(native_handle: NonNull<ffi::native_handle_t>) -> Self {
32 Self(native_handle)
33 }
34
35 /// Creates a new `NativeHandle` wrapping a clone of the given `native_handle_t` pointer.
36 ///
37 /// Unlike [`from_raw`](Self::from_raw) this doesn't take ownership of the pointer passed in, so
38 /// the caller remains responsible for closing and freeing it.
39 ///
40 /// # Safety
41 ///
42 /// `native_handle` must be a valid pointer to a `native_handle_t`.
43 pub unsafe fn clone_from_raw(native_handle: NonNull<ffi::native_handle_t>) -> Option<Self> {
44 // SAFETY: The caller promised that `native_handle` was valid.
45 let cloned = unsafe { ffi::native_handle_clone(native_handle.as_ptr()) };
46 NonNull::new(cloned).map(Self)
47 }
48
49 /// Returns a raw pointer to the wrapped `native_handle_t`.
50 ///
51 /// This is only valid as long as this `NativeHandle` exists, so shouldn't be stored. It mustn't
52 /// be closed or deleted.
53 pub fn as_raw(&self) -> NonNull<ffi::native_handle_t> {
54 self.0
55 }
56
57 /// Turns the `NativeHandle` into a raw `native_handle_t`.
58 ///
59 /// The caller takes ownership of the `native_handle_t` and its file descriptors, so is
60 /// responsible for closing and freeing it.
61 pub fn into_raw(self) -> NonNull<ffi::native_handle_t> {
62 let raw = self.0;
63 forget(self);
64 raw
65 }
66}
67
68impl Clone for NativeHandle {
69 fn clone(&self) -> Self {
70 // SAFETY: Our wrapped `native_handle_t` pointer is always valid.
71 unsafe { Self::clone_from_raw(self.0) }.expect("native_handle_clone returned null")
72 }
73}
74
75impl Drop for NativeHandle {
76 fn drop(&mut self) {
77 // SAFETY: Our wrapped `native_handle_t` pointer is always valid, and it won't be accessed
78 // after this because we own it and are being dropped.
79 unsafe {
80 assert_eq!(ffi::native_handle_close(self.0.as_ptr()), 0);
81 assert_eq!(ffi::native_handle_delete(self.0.as_ptr()), 0);
82 }
83 }
84}
85
86// SAFETY: `NativeHandle` owns the `native_handle_t`, which just contains some integers and file
87// descriptors, which aren't tied to any particular thread.
88unsafe impl Send for NativeHandle {}
89
90// SAFETY: A `NativeHandle` can be used from different threads simultaneously, as is is just
91// integers and file descriptors.
92unsafe impl Sync for NativeHandle {}