fidl_next_codec/wire/
ptr.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use core::marker::PhantomData;
6use core::mem::MaybeUninit;
7
8use munge::munge;
9
10use crate::{Chunk, DecodeError, Slot, WireU64};
11
12/// A raw FIDL pointer
13#[repr(C, align(8))]
14pub union WirePointer<'de, T> {
15    encoded: WireU64,
16    decoded: *mut T,
17    _phantom: PhantomData<&'de mut [Chunk]>,
18}
19
20unsafe impl<T: Send> Send for WirePointer<'_, T> {}
21unsafe impl<T: Sync> Sync for WirePointer<'_, T> {}
22
23impl<T> WirePointer<'_, T> {
24    /// Returns whether the wire pointer was encoded present.
25    pub fn is_encoded_present(slot: Slot<'_, Self>) -> Result<bool, DecodeError> {
26        munge!(let Self { encoded } = slot);
27        match **encoded {
28            0 => Ok(false),
29            u64::MAX => Ok(true),
30            x => Err(DecodeError::InvalidPointerPresence(x)),
31        }
32    }
33
34    /// Encodes that a pointer is present in an output.
35    pub fn encode_present(out: &mut MaybeUninit<Self>) {
36        munge!(let Self { encoded } = out);
37        encoded.write(WireU64(u64::MAX));
38    }
39
40    /// Encodes that a pointer is absent in a slot.
41    pub fn encode_absent(out: &mut MaybeUninit<Self>) {
42        munge!(let Self { encoded } = out);
43        encoded.write(WireU64(0));
44    }
45
46    /// Sets the decoded value of the pointer.
47    pub fn set_decoded(slot: Slot<'_, Self>, ptr: *mut T) {
48        munge!(let Self { mut decoded } = slot);
49        // SAFETY: Identical to `decoded.write(ptr.into_raw())`, but raw
50        // pointers don't currently implement `IntoBytes`.
51        unsafe {
52            *decoded.as_mut_ptr() = ptr;
53        }
54    }
55
56    /// Returns the underlying pointer.
57    pub fn as_ptr(&self) -> *mut T {
58        unsafe { self.decoded }
59    }
60}