chromium/mojo/public/rust/bindings/data.rs

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Mojo wire format bindings and helpers
//!
//! Contains types that are layout-equivalent to their serialized
//! representation. They are the building blocks for encoding and decoding mojo
//! messages.
//!
//! Some are helpers used in generated code.

use bytemuck::{Pod, Zeroable};

pub trait DataType {}

/// The mojo message header. Messages contain this before their payload.
///
/// This matches the representation of a version 2 header. Note that, depending
/// on the message header's specified version, the serialized representation may
/// be smaller than this Rust type.
///
/// See //mojo/public/cpp/bindings/lib/message_internal.h for the corresponding
/// C++ definitions.
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
#[repr(C)]
pub struct MessageHeader {
    pub header: StructHeader,
    pub interface_id: u32,
    pub name: u32,
    pub flags: MessageHeaderFlags,
    pub trace_nonce: u32,
    // Min version 1:
    pub request_id: u64,
    // Min version 2:
    pub payload: u64,
    pub payload_interface_ids: Pointer<Array<u32>>,
}

pub const MESSAGE_HEADER_V0_SIZE: usize = 24;
pub const MESSAGE_HEADER_V1_SIZE: usize = 32;
pub const MESSAGE_HEADER_V2_SIZE: usize = 48;

static_assertions::assert_eq_size!([u8; MESSAGE_HEADER_V2_SIZE], MessageHeader);

bitflags::bitflags! {
    /// See flags in //mojo/public/cpp/bindings/message.h.
    #[repr(transparent)]
    #[derive(Clone, Copy, Debug)]
    pub struct MessageHeaderFlags: u32 {
        const EXPECTS_RESPONSE = 0b001;
        const IS_RESPONSE = 0b010;
        const IS_SYNC = 0b100;
    }
}

// SAFETY: MessageHeaderFlags is repr(transparent) with `u32` which is POD, and
// has no invariants which would make any bit pattern invalid.
//
// Bitflags has a feature to allow bytemuck derives but we don't enable it.
unsafe impl Zeroable for MessageHeaderFlags {}
unsafe impl Pod for MessageHeaderFlags {}

/// A relative pointer in a mojom serialized message.
///
/// `offset` is a byte offset relative to the location of `self` in the buffer.
/// If it's 0, it is a null pointer.
///
/// Note that while this `impl Copy` for storage in a `union`, care should be
/// taken not to use it in a different context. It is only useful relative to
/// its location in a mojom struct or union.
#[derive(Debug)]
#[repr(transparent)]
pub struct Pointer<T: ?Sized> {
    pub offset: u64,
    pub _phantom: std::marker::PhantomData<*mut T>,
}

// SAFETY: `Pointer<_>` is repr(transparent) with `u64`, which is itself `Pod`.
//
// Impl'ed manually because the derive macro doesn't handle generic args.
unsafe impl<T: ?Sized + 'static> Pod for Pointer<T> {}
unsafe impl<T: ?Sized + 'static> Zeroable for Pointer<T> {}

impl<T: ?Sized> Copy for Pointer<T> {}

impl<T: ?Sized> Clone for Pointer<T> {
    fn clone(&self) -> Self {
        *self
    }
}

/// A reference to a handle transmitted in a message.
///
/// `index` is an index (*not* a byte offset) into the message's handle vector.
/// If it's `u32::MAX`, the handle is null.
///
/// Note that while this `impl Copy` for storage in a `union`, care should be
/// taken not to use it in a different context. It represents an owned handle.
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
#[repr(transparent)]
pub struct HandleRef {
    pub index: u32,
}

/// A serialized reference to a mojo interface.
///
/// Note that while this `impl Copy` for storage in a `union`, care should be
/// taken not to use it in a different context. It represents an owned handle.
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
#[repr(C)]
pub struct InterfaceData {
    pub handle: HandleRef,
    pub version: u32,
}

#[derive(Debug)]
#[repr(C)]
pub struct Array<T> {
    pub header: ArrayHeader,
    pub elems: [T],
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct Map<K, V> {
    pub header: StructHeader,
    pub keys: Pointer<Array<K>>,
    pub vals: Pointer<Array<V>>,
}

// SAFETY: `Map<_, _>` is repr(C) and consists of three fields which are `Pod`.
// They have size 8 and have alignment at most 8, so there are no padding bits.
// Hence all bits of `Map<_, _>` belong to one of the `Pod` fields.
//
// Impl'ed manually because the derive macro doesn't handle generic args.
unsafe impl<K: Copy + 'static, V: Copy + 'static> Pod for Map<K, V> {}
unsafe impl<K: Copy + 'static, V: Copy + 'static> Zeroable for Map<K, V> {}

#[derive(Copy, Clone, Debug, Pod, Zeroable)]
#[repr(C)]
pub struct StructHeader {
    pub size: u32,
    pub version: u32,
}

#[derive(Copy, Clone, Debug, Pod, Zeroable)]
#[repr(C)]
pub struct ArrayHeader {
    pub size: u32,
    pub num_elems: u32,
}

/// The required alignment of mojom objects (structs and arrays).
pub const OBJECT_ALIGNMENT: usize = 8;

pub const UNION_DATA_SIZE: usize = 16;
pub const UNION_INNER_SIZE: usize = 8;