From patchwork Thu May 16 19:03:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666484 Received: from aer-iport-2.cisco.com (aer-iport-2.cisco.com [173.38.203.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 163DD157E6E; Thu, 16 May 2024 19:05:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886311; cv=none; b=QZG5c6dhWjPNctWXqSBN7gdsvxie+sqWkmZkyd753CfilIppVja05/bWG7dZsome+mXsey3dDXOUKWqdcgEEmJQRybIddoCyFiewB81FREd6sXNY1fJ8+dgEdrsUiVxgVuY62FmH4n+5SPGz8MOjX7EOcEr29m2+z3pE1hYqGQA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886311; c=relaxed/simple; bh=tzGNyzSA2XSVOcfb4MHGV3ymf1WGaeCoGpXHWR8I0Sg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jeVA/FrRJ2HynQgjjhob5vYwzb72H906Tt+ioe6YfioIUUN/p7O3J78MCTM/RIXDml48+Pmgo+kD+mw9DN3JVC5tmkKFo1Oe/NMnetJGXcvC/mlOmZbTi3bblIkijtDbxM+QYm2IT9xYXGswcoQSVTtmhvisjaQCg+hC9VaT+cE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=gTgUpP9/; arc=none smtp.client-ip=173.38.203.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="gTgUpP9/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=2747; q=dns/txt; s=iport; t=1715886309; x=1717095909; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DJnJbYQMInpEqhEWqVj7qdnmi6VUKPrWQdQ0UzbxgDI=; b=gTgUpP9/Ofz0EjBhQ8VLOyq0gSPCk1PBfnKiZpzNR2eA0c+/BqSXg2wi A2S/glX/Jl5/drZkQhTMHI1Tz6QWhFQ/0lzaa2ia7pnZ5JLVZTEfhiZmL N/jaSDp1Ar7uF5EnngcELT+7x+GJvZr6OagM3/5whpA7W0Mllf/3PnqCn 0=; X-CSE-ConnectionGUID: 7AklUx1fQ5CuiRsQQJSmJA== X-CSE-MsgGUID: R0i+RELvT6iiXRa0XzjoHQ== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12416983" Received: from aer-iport-nat.cisco.com (HELO aer-core-1.cisco.com) ([173.38.203.22]) by aer-iport-2.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:03:58 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-1.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ3vLn030156 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:03:58 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 01/22] kernel: configs: add qemu-busybox-min.config Date: Thu, 16 May 2024 22:03:24 +0300 Message-Id: <20240516190345.957477-2-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-1.cisco.com This is a minimal configuration for running a busybox initramfs image with networking support. Added for convenience. Signed-off-by: Ariel Miculas --- arch/x86/configs/qemu-busybox-min.config | 11 +++++ kernel/configs/qemu-busybox-min.config | 56 ++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 arch/x86/configs/qemu-busybox-min.config create mode 100644 kernel/configs/qemu-busybox-min.config diff --git a/arch/x86/configs/qemu-busybox-min.config b/arch/x86/configs/qemu-busybox-min.config new file mode 100644 index 000000000000..9a2bf2549053 --- /dev/null +++ b/arch/x86/configs/qemu-busybox-min.config @@ -0,0 +1,11 @@ +CONFIG_64BIT=y +CONFIG_ACPI=y + +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y + +CONFIG_HYPERVISOR_GUEST=y +CONFIG_PVH=y + +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0 nokaslr rdinit=/sbin/init" diff --git a/kernel/configs/qemu-busybox-min.config b/kernel/configs/qemu-busybox-min.config new file mode 100644 index 000000000000..51435e178199 --- /dev/null +++ b/kernel/configs/qemu-busybox-min.config @@ -0,0 +1,56 @@ +# This is a minimal configuration for running a busybox initramfs image with +# networking support. +# +# The following command can be used create the configuration for a minimal +# kernel image: +# +# make allnoconfig qemu-busybox-min.config +# +# The following command can be used to build the configuration for a default +# kernel image: +# +# make defconfig qemu-busybox-min.config +# +# On x86, the following command can be used to run qemu: +# +# qemu-system-x86_64 -nographic -kernel vmlinux -initrd initrd.img -nic user,model=rtl8139,hostfwd=tcp::5555-:23 +# +# On arm64, the following command can be used to run qemu: +# +# qemu-system-aarch64 -M virt -cpu cortex-a72 -nographic -kernel arch/arm64/boot/Image -initrd initrd.img -nic user,model=rtl8139,hostfwd=tcp::5555-:23 + +CONFIG_SMP=y +CONFIG_PRINTK=y +CONFIG_PRINTK_TIME=y + +CONFIG_PCI=y + +# We use an initramfs for busybox with elf binaries in it. +CONFIG_BLK_DEV_INITRD=y +CONFIG_RD_GZIP=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_SCRIPT=y + +# This is for /dev file system. +CONFIG_DEVTMPFS=y + +# Core networking (packet is for dhcp). +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_INET=y + +# RTL8139 NIC support. +CONFIG_NETDEVICES=y +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_8139CP=y + +# To get GDB symbols and script. +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y +CONFIG_GDB_SCRIPTS=y + +# For the power-down button (triggered by qemu's `system_powerdown` command). +CONFIG_INPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_KEYBOARD=y From patchwork Thu May 16 19:03:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666485 Received: from aer-iport-3.cisco.com (aer-iport-3.cisco.com [173.38.203.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E1FA157E79; Thu, 16 May 2024 19:05:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886314; cv=none; b=Yfq39oPOdswgFZ/6L7ogBNVO0IAMhWuvXJizt6/7yIhduzx/QmDFJ+RM9J6ypA/mocmYb+vo23LGL1ioGjTS/9B0loiTOz4ykxtM0lrlSmFzAb8q2gLd2fXaEHsx/NpO6oqlUn41tCD1JCZa46qy/x6TWs15TdEvmBQpX+3bNN4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886314; c=relaxed/simple; bh=5/7SEzUqNOQzOz5OKVG5e+BFOae3lGhNr2rqkMCeXVk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sUwaD6GNt1PDsHEMN2Kavg6tiqvCUuPBeqm/WahtOxF37Ko2g8qasJKinAyp5fmLDr1Me/rAz8Kw4e+Y2oL4qg6/zNBs6DjgNZ2LGXrnexydjPDpgTUwN8cjpt+sPigYlVyBUrS22OZ5nTeo9PRovxlTNwVGAKTixrbuvpKpzKk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=cJ/hODSv; arc=none smtp.client-ip=173.38.203.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="cJ/hODSv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=20796; q=dns/txt; s=iport; t=1715886311; x=1717095911; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WwoWGQOt8e4ocz745ywVztH+TLbfTG8qj9hApEJcyfc=; b=cJ/hODSvYtgBP6zNFUnFLaW+z+nKccSuiGjzQM5AuVBYW/GIKfAkVC8J D3j7qSoCAndFjQhAh7z5OMLenD9DV8ZI5afeahyk65+I9MrxZTTa/xH6N b57hQT3gZRqeuobdxW76UG/egmARph03CkkomzcWKGDNzyfcBC9MM2XvM o=; X-CSE-ConnectionGUID: XknJQn56Rz64WFzhBsEnoQ== X-CSE-MsgGUID: kOUUzzI2TFiDIMkedgGElw== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12237922" Received: from aer-iport-nat.cisco.com (HELO aer-core-1.cisco.com) ([173.38.203.22]) by aer-iport-3.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:00 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-1.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ3wvl030160 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:03:59 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 02/22] rust: hex: import crate Date: Thu, 16 May 2024 22:03:25 +0300 Message-Id: <20240516190345.957477-3-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-1.cisco.com This is a subset of the Rust `hex` crate, version v0.4.3, licensed under "Apache-2.0 OR MIT", from: https://github.com/KokaKiwi/rust-hex/tree/v0.4.3/src The files are copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers). For copyright details, please see: https://github.com/KokaKiwi/rust-hex/blob/v0.4.3/README.md#license https://github.com/KokaKiwi/rust-hex/blob/v0.4.3/LICENSE-APACHE https://github.com/KokaKiwi/rust-hex/blob/v0.4.3/LICENSE-MIT The next three patches modify these files as needed for use within the kernel. This patch split allows reviewers to double-check the import and to clearly see the differences introduced. The following script may be used to verify the contents: for path in $(cd rust/hex/ && find . -type f -name '*.rs'); do curl --silent --show-error --location \ https://github.com/KokaKiwi/rust-hex/raw/v0.4.3/src/$path \ | diff --unified rust/hex/$path - && echo $path: OK done Signed-off-by: Ariel Miculas --- rust/hex/error.rs | 59 ++++++ rust/hex/lib.rs | 525 ++++++++++++++++++++++++++++++++++++++++++++++ rust/hex/serde.rs | 102 +++++++++ 3 files changed, 686 insertions(+) create mode 100644 rust/hex/error.rs create mode 100644 rust/hex/lib.rs create mode 100644 rust/hex/serde.rs diff --git a/rust/hex/error.rs b/rust/hex/error.rs new file mode 100644 index 000000000000..ff7a3b5c16bd --- /dev/null +++ b/rust/hex/error.rs @@ -0,0 +1,59 @@ +use core::fmt; + +/// The error type for decoding a hex string into `Vec` or `[u8; N]`. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum FromHexError { + /// An invalid character was found. Valid ones are: `0...9`, `a...f` + /// or `A...F`. + InvalidHexCharacter { c: char, index: usize }, + + /// A hex string's length needs to be even, as two digits correspond to + /// one byte. + OddLength, + + /// If the hex string is decoded into a fixed sized container, such as an + /// array, the hex string's length * 2 has to match the container's + /// length. + InvalidStringLength, +} + +#[cfg(feature = "std")] +impl std::error::Error for FromHexError {} + +impl fmt::Display for FromHexError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + FromHexError::InvalidHexCharacter { c, index } => { + write!(f, "Invalid character {:?} at position {}", c, index) + } + FromHexError::OddLength => write!(f, "Odd number of digits"), + FromHexError::InvalidStringLength => write!(f, "Invalid string length"), + } + } +} + +#[cfg(test)] +// this feature flag is here to suppress unused +// warnings of `super::*` and `pretty_assertions::assert_eq` +#[cfg(feature = "alloc")] +mod tests { + use super::*; + #[cfg(feature = "alloc")] + use alloc::string::ToString; + use pretty_assertions::assert_eq; + + #[test] + #[cfg(feature = "alloc")] + fn test_display() { + assert_eq!( + FromHexError::InvalidHexCharacter { c: '\n', index: 5 }.to_string(), + "Invalid character '\\n' at position 5" + ); + + assert_eq!(FromHexError::OddLength.to_string(), "Odd number of digits"); + assert_eq!( + FromHexError::InvalidStringLength.to_string(), + "Invalid string length" + ); + } +} diff --git a/rust/hex/lib.rs b/rust/hex/lib.rs new file mode 100644 index 000000000000..ec48961b9ffe --- /dev/null +++ b/rust/hex/lib.rs @@ -0,0 +1,525 @@ +// Copyright (c) 2013-2014 The Rust Project Developers. +// Copyright (c) 2015-2020 The rust-hex Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +//! Encoding and decoding hex strings. +//! +//! For most cases, you can simply use the [`decode`], [`encode`] and +//! [`encode_upper`] functions. If you need a bit more control, use the traits +//! [`ToHex`] and [`FromHex`] instead. +//! +//! # Example +//! +//! ``` +//! # #[cfg(not(feature = "alloc"))] +//! # let mut output = [0; 0x18]; +//! # +//! # #[cfg(not(feature = "alloc"))] +//! # hex::encode_to_slice(b"Hello world!", &mut output).unwrap(); +//! # +//! # #[cfg(not(feature = "alloc"))] +//! # let hex_string = ::core::str::from_utf8(&output).unwrap(); +//! # +//! # #[cfg(feature = "alloc")] +//! let hex_string = hex::encode("Hello world!"); +//! +//! println!("{}", hex_string); // Prints "48656c6c6f20776f726c6421" +//! +//! # assert_eq!(hex_string, "48656c6c6f20776f726c6421"); +//! ``` + +#![doc(html_root_url = "https://docs.rs/hex/0.4.3")] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![allow(clippy::unreadable_literal)] + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "alloc")] +use alloc::{string::String, vec::Vec}; + +use core::iter; + +mod error; +pub use crate::error::FromHexError; + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +pub mod serde; +#[cfg(feature = "serde")] +pub use crate::serde::deserialize; +#[cfg(all(feature = "alloc", feature = "serde"))] +pub use crate::serde::{serialize, serialize_upper}; + +/// Encoding values as hex string. +/// +/// This trait is implemented for all `T` which implement `AsRef<[u8]>`. This +/// includes `String`, `str`, `Vec` and `[u8]`. +/// +/// # Example +/// +/// ``` +/// use hex::ToHex; +/// +/// println!("{}", "Hello world!".encode_hex::()); +/// # assert_eq!("Hello world!".encode_hex::(), "48656c6c6f20776f726c6421".to_string()); +/// ``` +/// +/// *Note*: instead of using this trait, you might want to use [`encode()`]. +pub trait ToHex { + /// Encode the hex strict representing `self` into the result. Lower case + /// letters are used (e.g. `f9b4ca`) + fn encode_hex>(&self) -> T; + + /// Encode the hex strict representing `self` into the result. Upper case + /// letters are used (e.g. `F9B4CA`) + fn encode_hex_upper>(&self) -> T; +} + +const HEX_CHARS_LOWER: &[u8; 16] = b"0123456789abcdef"; +const HEX_CHARS_UPPER: &[u8; 16] = b"0123456789ABCDEF"; + +struct BytesToHexChars<'a> { + inner: ::core::slice::Iter<'a, u8>, + table: &'static [u8; 16], + next: Option, +} + +impl<'a> BytesToHexChars<'a> { + fn new(inner: &'a [u8], table: &'static [u8; 16]) -> BytesToHexChars<'a> { + BytesToHexChars { + inner: inner.iter(), + table, + next: None, + } + } +} + +impl<'a> Iterator for BytesToHexChars<'a> { + type Item = char; + + fn next(&mut self) -> Option { + match self.next.take() { + Some(current) => Some(current), + None => self.inner.next().map(|byte| { + let current = self.table[(byte >> 4) as usize] as char; + self.next = Some(self.table[(byte & 0x0F) as usize] as char); + current + }), + } + } + + fn size_hint(&self) -> (usize, Option) { + let length = self.len(); + (length, Some(length)) + } +} + +impl<'a> iter::ExactSizeIterator for BytesToHexChars<'a> { + fn len(&self) -> usize { + let mut length = self.inner.len() * 2; + if self.next.is_some() { + length += 1; + } + length + } +} + +#[inline] +fn encode_to_iter>(table: &'static [u8; 16], source: &[u8]) -> T { + BytesToHexChars::new(source, table).collect() +} + +impl> ToHex for T { + fn encode_hex>(&self) -> U { + encode_to_iter(HEX_CHARS_LOWER, self.as_ref()) + } + + fn encode_hex_upper>(&self) -> U { + encode_to_iter(HEX_CHARS_UPPER, self.as_ref()) + } +} + +/// Types that can be decoded from a hex string. +/// +/// This trait is implemented for `Vec` and small `u8`-arrays. +/// +/// # Example +/// +/// ``` +/// use core::str; +/// use hex::FromHex; +/// +/// let buffer = <[u8; 12]>::from_hex("48656c6c6f20776f726c6421")?; +/// let string = str::from_utf8(&buffer).expect("invalid buffer length"); +/// +/// println!("{}", string); // prints "Hello world!" +/// # assert_eq!("Hello world!", string); +/// # Ok::<(), hex::FromHexError>(()) +/// ``` +pub trait FromHex: Sized { + type Error; + + /// Creates an instance of type `Self` from the given hex string, or fails + /// with a custom error type. + /// + /// Both, upper and lower case characters are valid and can even be + /// mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings). + fn from_hex>(hex: T) -> Result; +} + +fn val(c: u8, idx: usize) -> Result { + match c { + b'A'..=b'F' => Ok(c - b'A' + 10), + b'a'..=b'f' => Ok(c - b'a' + 10), + b'0'..=b'9' => Ok(c - b'0'), + _ => Err(FromHexError::InvalidHexCharacter { + c: c as char, + index: idx, + }), + } +} + +#[cfg(feature = "alloc")] +impl FromHex for Vec { + type Error = FromHexError; + + fn from_hex>(hex: T) -> Result { + let hex = hex.as_ref(); + if hex.len() % 2 != 0 { + return Err(FromHexError::OddLength); + } + + hex.chunks(2) + .enumerate() + .map(|(i, pair)| Ok(val(pair[0], 2 * i)? << 4 | val(pair[1], 2 * i + 1)?)) + .collect() + } +} + +// Helper macro to implement the trait for a few fixed sized arrays. Once Rust +// has type level integers, this should be removed. +macro_rules! from_hex_array_impl { + ($($len:expr)+) => {$( + impl FromHex for [u8; $len] { + type Error = FromHexError; + + fn from_hex>(hex: T) -> Result { + let mut out = [0_u8; $len]; + decode_to_slice(hex, &mut out as &mut [u8])?; + Ok(out) + } + } + )+} +} + +from_hex_array_impl! { + 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 100 101 102 103 104 105 106 107 108 109 110 111 112 + 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 + 160 192 200 224 256 384 512 768 1024 2048 4096 8192 16384 32768 +} + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +from_hex_array_impl! { + 65536 131072 262144 524288 1048576 2097152 4194304 8388608 + 16777216 33554432 67108864 134217728 268435456 536870912 + 1073741824 2147483648 +} + +#[cfg(target_pointer_width = "64")] +from_hex_array_impl! { + 4294967296 +} + +/// Encodes `data` as hex string using lowercase characters. +/// +/// Lowercase characters are used (e.g. `f9b4ca`). The resulting string's +/// length is always even, each byte in `data` is always encoded using two hex +/// digits. Thus, the resulting string contains exactly twice as many bytes as +/// the input data. +/// +/// # Example +/// +/// ``` +/// assert_eq!(hex::encode("Hello world!"), "48656c6c6f20776f726c6421"); +/// assert_eq!(hex::encode(vec![1, 2, 3, 15, 16]), "0102030f10"); +/// ``` +#[must_use] +#[cfg(feature = "alloc")] +pub fn encode>(data: T) -> String { + data.encode_hex() +} + +/// Encodes `data` as hex string using uppercase characters. +/// +/// Apart from the characters' casing, this works exactly like `encode()`. +/// +/// # Example +/// +/// ``` +/// assert_eq!(hex::encode_upper("Hello world!"), "48656C6C6F20776F726C6421"); +/// assert_eq!(hex::encode_upper(vec![1, 2, 3, 15, 16]), "0102030F10"); +/// ``` +#[must_use] +#[cfg(feature = "alloc")] +pub fn encode_upper>(data: T) -> String { + data.encode_hex_upper() +} + +/// Decodes a hex string into raw bytes. +/// +/// Both, upper and lower case characters are valid in the input string and can +/// even be mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings). +/// +/// # Example +/// +/// ``` +/// assert_eq!( +/// hex::decode("48656c6c6f20776f726c6421"), +/// Ok("Hello world!".to_owned().into_bytes()) +/// ); +/// +/// assert_eq!(hex::decode("123"), Err(hex::FromHexError::OddLength)); +/// assert!(hex::decode("foo").is_err()); +/// ``` +#[cfg(feature = "alloc")] +pub fn decode>(data: T) -> Result, FromHexError> { + FromHex::from_hex(data) +} + +/// Decode a hex string into a mutable bytes slice. +/// +/// Both, upper and lower case characters are valid in the input string and can +/// even be mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings). +/// +/// # Example +/// +/// ``` +/// let mut bytes = [0u8; 4]; +/// assert_eq!(hex::decode_to_slice("6b697769", &mut bytes as &mut [u8]), Ok(())); +/// assert_eq!(&bytes, b"kiwi"); +/// ``` +pub fn decode_to_slice>(data: T, out: &mut [u8]) -> Result<(), FromHexError> { + let data = data.as_ref(); + + if data.len() % 2 != 0 { + return Err(FromHexError::OddLength); + } + if data.len() / 2 != out.len() { + return Err(FromHexError::InvalidStringLength); + } + + for (i, byte) in out.iter_mut().enumerate() { + *byte = val(data[2 * i], 2 * i)? << 4 | val(data[2 * i + 1], 2 * i + 1)?; + } + + Ok(()) +} + +// generates an iterator like this +// (0, 1) +// (2, 3) +// (4, 5) +// (6, 7) +// ... +#[inline] +fn generate_iter(len: usize) -> impl Iterator { + (0..len).step_by(2).zip((0..len).skip(1).step_by(2)) +} + +// the inverse of `val`. +#[inline] +#[must_use] +fn byte2hex(byte: u8, table: &[u8; 16]) -> (u8, u8) { + let high = table[((byte & 0xf0) >> 4) as usize]; + let low = table[(byte & 0x0f) as usize]; + + (high, low) +} + +/// Encodes some bytes into a mutable slice of bytes. +/// +/// The output buffer, has to be able to hold at least `input.len() * 2` bytes, +/// otherwise this function will return an error. +/// +/// # Example +/// +/// ``` +/// # use hex::FromHexError; +/// # fn main() -> Result<(), FromHexError> { +/// let mut bytes = [0u8; 4 * 2]; +/// +/// hex::encode_to_slice(b"kiwi", &mut bytes)?; +/// assert_eq!(&bytes, b"6b697769"); +/// # Ok(()) +/// # } +/// ``` +pub fn encode_to_slice>(input: T, output: &mut [u8]) -> Result<(), FromHexError> { + if input.as_ref().len() * 2 != output.len() { + return Err(FromHexError::InvalidStringLength); + } + + for (byte, (i, j)) in input + .as_ref() + .iter() + .zip(generate_iter(input.as_ref().len() * 2)) + { + let (high, low) = byte2hex(*byte, HEX_CHARS_LOWER); + output[i] = high; + output[j] = low; + } + + Ok(()) +} + +#[cfg(test)] +mod test { + use super::*; + #[cfg(feature = "alloc")] + use alloc::string::ToString; + use pretty_assertions::assert_eq; + + #[test] + #[cfg(feature = "alloc")] + fn test_gen_iter() { + let result = vec![(0, 1), (2, 3)]; + + assert_eq!(generate_iter(5).collect::>(), result); + } + + #[test] + fn test_encode_to_slice() { + let mut output_1 = [0; 4 * 2]; + encode_to_slice(b"kiwi", &mut output_1).unwrap(); + assert_eq!(&output_1, b"6b697769"); + + let mut output_2 = [0; 5 * 2]; + encode_to_slice(b"kiwis", &mut output_2).unwrap(); + assert_eq!(&output_2, b"6b69776973"); + + let mut output_3 = [0; 100]; + + assert_eq!( + encode_to_slice(b"kiwis", &mut output_3), + Err(FromHexError::InvalidStringLength) + ); + } + + #[test] + fn test_decode_to_slice() { + let mut output_1 = [0; 4]; + decode_to_slice(b"6b697769", &mut output_1).unwrap(); + assert_eq!(&output_1, b"kiwi"); + + let mut output_2 = [0; 5]; + decode_to_slice(b"6b69776973", &mut output_2).unwrap(); + assert_eq!(&output_2, b"kiwis"); + + let mut output_3 = [0; 4]; + + assert_eq!( + decode_to_slice(b"6", &mut output_3), + Err(FromHexError::OddLength) + ); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_encode() { + assert_eq!(encode("foobar"), "666f6f626172"); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_decode() { + assert_eq!( + decode("666f6f626172"), + Ok(String::from("foobar").into_bytes()) + ); + } + + #[test] + #[cfg(feature = "alloc")] + pub fn test_from_hex_okay_str() { + assert_eq!(Vec::from_hex("666f6f626172").unwrap(), b"foobar"); + assert_eq!(Vec::from_hex("666F6F626172").unwrap(), b"foobar"); + } + + #[test] + #[cfg(feature = "alloc")] + pub fn test_from_hex_okay_bytes() { + assert_eq!(Vec::from_hex(b"666f6f626172").unwrap(), b"foobar"); + assert_eq!(Vec::from_hex(b"666F6F626172").unwrap(), b"foobar"); + } + + #[test] + #[cfg(feature = "alloc")] + pub fn test_invalid_length() { + assert_eq!(Vec::from_hex("1").unwrap_err(), FromHexError::OddLength); + assert_eq!( + Vec::from_hex("666f6f6261721").unwrap_err(), + FromHexError::OddLength + ); + } + + #[test] + #[cfg(feature = "alloc")] + pub fn test_invalid_char() { + assert_eq!( + Vec::from_hex("66ag").unwrap_err(), + FromHexError::InvalidHexCharacter { c: 'g', index: 3 } + ); + } + + #[test] + #[cfg(feature = "alloc")] + pub fn test_empty() { + assert_eq!(Vec::from_hex("").unwrap(), b""); + } + + #[test] + #[cfg(feature = "alloc")] + pub fn test_from_hex_whitespace() { + assert_eq!( + Vec::from_hex("666f 6f62617").unwrap_err(), + FromHexError::InvalidHexCharacter { c: ' ', index: 4 } + ); + } + + #[test] + pub fn test_from_hex_array() { + assert_eq!( + <[u8; 6] as FromHex>::from_hex("666f6f626172"), + Ok([0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]) + ); + + assert_eq!( + <[u8; 5] as FromHex>::from_hex("666f6f626172"), + Err(FromHexError::InvalidStringLength) + ); + } + + #[test] + #[cfg(feature = "alloc")] + fn test_to_hex() { + assert_eq!( + [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex::(), + "666f6f626172".to_string(), + ); + + assert_eq!( + [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex_upper::(), + "666F6F626172".to_string(), + ); + } +} diff --git a/rust/hex/serde.rs b/rust/hex/serde.rs new file mode 100644 index 000000000000..335a15132a27 --- /dev/null +++ b/rust/hex/serde.rs @@ -0,0 +1,102 @@ +//! Hex encoding with `serde`. +#[cfg_attr( + all(feature = "alloc", feature = "serde"), + doc = r##" +# Example + +``` +use serde::{Serialize, Deserialize}; + +#[derive(Serialize, Deserialize)] +struct Foo { + #[serde(with = "hex")] + bar: Vec, +} +``` +"## +)] +use serde::de::{Error, Visitor}; +use serde::Deserializer; +#[cfg(feature = "alloc")] +use serde::Serializer; + +#[cfg(feature = "alloc")] +use alloc::string::String; + +use core::fmt; +use core::marker::PhantomData; + +use crate::FromHex; + +#[cfg(feature = "alloc")] +use crate::ToHex; + +/// Serializes `data` as hex string using uppercase characters. +/// +/// Apart from the characters' casing, this works exactly like `serialize()`. +#[cfg(feature = "alloc")] +pub fn serialize_upper(data: T, serializer: S) -> Result +where + S: Serializer, + T: ToHex, +{ + let s = data.encode_hex_upper::(); + serializer.serialize_str(&s) +} + +/// Serializes `data` as hex string using lowercase characters. +/// +/// Lowercase characters are used (e.g. `f9b4ca`). The resulting string's length +/// is always even, each byte in data is always encoded using two hex digits. +/// Thus, the resulting string contains exactly twice as many bytes as the input +/// data. +#[cfg(feature = "alloc")] +pub fn serialize(data: T, serializer: S) -> Result +where + S: Serializer, + T: ToHex, +{ + let s = data.encode_hex::(); + serializer.serialize_str(&s) +} + +/// Deserializes a hex string into raw bytes. +/// +/// Both, upper and lower case characters are valid in the input string and can +/// even be mixed (e.g. `f9b4ca`, `F9B4CA` and `f9B4Ca` are all valid strings). +pub fn deserialize<'de, D, T>(deserializer: D) -> Result +where + D: Deserializer<'de>, + T: FromHex, + ::Error: fmt::Display, +{ + struct HexStrVisitor(PhantomData); + + impl<'de, T> Visitor<'de> for HexStrVisitor + where + T: FromHex, + ::Error: fmt::Display, + { + type Value = T; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "a hex encoded string") + } + + fn visit_str(self, data: &str) -> Result + where + E: Error, + { + FromHex::from_hex(data).map_err(Error::custom) + } + + fn visit_borrowed_str(self, data: &'de str) -> Result + where + E: Error, + { + FromHex::from_hex(data).map_err(Error::custom) + } + } + + deserializer.deserialize_str(HexStrVisitor(PhantomData)) +} From patchwork Thu May 16 19:03:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666486 Received: from aer-iport-5.cisco.com (aer-iport-5.cisco.com [173.38.203.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FC8C1581FF; Thu, 16 May 2024 19:05:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.67 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886314; cv=none; b=JOMLicT4oHvbJ0MO+xI55N7XZlTTO2XOcQAMwvkhPwO8zbRZPzT1MSqqZcn5dkVo3wAHYHDdMBupNB4iOyEVR3utnqECyALgu4D38AjjTTBgxobx2cu46YAH1AtaAA6UzCzmiBfeNatmDiSmb8sHvxUQCpwK+t1LgdvjZShYmJM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886314; c=relaxed/simple; bh=JLavhVFc09FEg9EY6gMPlypJaSPpAewW2C1Acr5xDKw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EflXRPzJ5xn2hfl9U92jk3OhYDe8ejbQ/3pGhXLjOWqLlMGASRMyLXR6RnqBwkMlzBT7HdDWX0QIij+Beso7bfTetIIeTsNWVsmuJntE2n3NUOZUwZS1QFGjPM3w+s1TDew9xtxYYjmVGCY+4r+7cZonMTvLIOzwFS+F7h5jelk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=Q98/3hMV; arc=none smtp.client-ip=173.38.203.67 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="Q98/3hMV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=1236; q=dns/txt; s=iport; t=1715886312; x=1717095912; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=B+y082Y8KjvrVBkn/4Dxr8IGelz4ZU6IVUPo0Qa5ojw=; b=Q98/3hMV/0EKTxd++4RCdqVjH+x2Bfg3w+bjhox28KFaCGMzhr+v2omK yg569fPgcI1veznH48oP+Ane/ydXqnJyLDZENnc07m6uYM9h89TgnEoK5 XTXL8qmvERXD+HAdOjkpvv7VXwg7V3+c7mimQeqPlBDPD3qE+HyYwWMIZ E=; X-CSE-ConnectionGUID: O0HGUG50T4C2oJrIvng/bQ== X-CSE-MsgGUID: xtzBqNHyRSisowtvoRep0w== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="9839846" Received: from aer-iport-nat.cisco.com (HELO aer-core-3.cisco.com) ([173.38.203.22]) by aer-iport-5.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:01 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-3.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ40nr017864 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:01 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 03/22] rust: hex: add SPDX license identifiers Date: Thu, 16 May 2024 22:03:26 +0300 Message-Id: <20240516190345.957477-4-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-3.cisco.com Add the SPDX license identifiers, since the initial patch added the upstream sources with no modifications whatsoever. Signed-off-by: Ariel Miculas --- rust/hex/error.rs | 2 ++ rust/hex/lib.rs | 2 ++ rust/hex/serde.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/rust/hex/error.rs b/rust/hex/error.rs index ff7a3b5c16bd..e553a046c9ed 100644 --- a/rust/hex/error.rs +++ b/rust/hex/error.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + use core::fmt; /// The error type for decoding a hex string into `Vec` or `[u8; N]`. diff --git a/rust/hex/lib.rs b/rust/hex/lib.rs index ec48961b9ffe..a23def3f80db 100644 --- a/rust/hex/lib.rs +++ b/rust/hex/lib.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + // Copyright (c) 2013-2014 The Rust Project Developers. // Copyright (c) 2015-2020 The rust-hex Developers. // diff --git a/rust/hex/serde.rs b/rust/hex/serde.rs index 335a15132a27..40ab1edb2bc8 100644 --- a/rust/hex/serde.rs +++ b/rust/hex/serde.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + //! Hex encoding with `serde`. #[cfg_attr( all(feature = "alloc", feature = "serde"), From patchwork Thu May 16 19:03:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666487 Received: from aer-iport-3.cisco.com (aer-iport-3.cisco.com [173.38.203.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B969D15B0E0; Thu, 16 May 2024 19:05:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886317; cv=none; b=Loz+Z0Wjjca0YpnRMgDaITDKVVVv+3f8UgJ/EZtAsDhajjcIzexReQRhrHBNdSr7PqKAH9R4qZSlN0Ani4OWshcowiLnNQ5lMOIKm/fMqSo+TMfYk2mnzlGH2avBAuArtUHJnpJKgmboLcyaZRA2f4/dF49h4NZRyp/uB8F9RAA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886317; c=relaxed/simple; bh=xtn+hR+P6AtQasd2NPiultmzHD+2r4okOEboO6xOKX4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EiZecIh9/50TnMapbmazHaxznYKhC5p9mW6+JImULbAIxcS1h4wzqmMOuPbUutfqerUJi3S0WoeA8am20HMa3lr5WKGzXHSyBpddtjvp10el68C3E71xcYWNVCgaH4jDCUrcJpQk30LxNRiyZz2j8y0M79s75EYXzncE8Bhc+Bw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=QJwMHFy0; arc=none smtp.client-ip=173.38.203.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="QJwMHFy0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=2646; q=dns/txt; s=iport; t=1715886315; x=1717095915; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eUbj65dbFM2s2DOl9iZSyGQu1oPu0UEugwjSxAQmAg8=; b=QJwMHFy03a+TIFgaJ96fKH3lZTvieLnf4VI5QB6T+Qi22J1LkZPHjAAm H0uXKZD4ZuQF/Ub5b5iwYDJ8WES1pOVGHZ3Cy2epvLFdFYtafOfBISu6d 05O/HieSCXGicf8x2AVeerDH5+T7198ONCZnZume3M8SHMk7wrq8nq87+ Q=; X-CSE-ConnectionGUID: Pc4fKmp5QsiZIb2FD6WG/g== X-CSE-MsgGUID: XN6AYbzsQ8GBJglZ3GZLDQ== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12237923" Received: from aer-iport-nat.cisco.com (HELO aer-core-8.cisco.com) ([173.38.203.22]) by aer-iport-3.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:02 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-8.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ41l7042434 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:02 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 04/22] rust: Kbuild: enable `hex` Date: Thu, 16 May 2024 22:03:27 +0300 Message-Id: <20240516190345.957477-5-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-8.cisco.com With all the new files in place from the hex crate, this patch adds support for them in the build system. Signed-off-by: Ariel Miculas --- rust/Makefile | 24 ++++++++++++++++++++---- scripts/Makefile.build | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/rust/Makefile b/rust/Makefile index ca86abac4ed0..fef8e38fbebd 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -15,7 +15,7 @@ always-$(CONFIG_RUST) += libmacros.so no-clean-files += libmacros.so always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs -obj-$(CONFIG_RUST) += alloc.o bindings.o kernel.o +obj-$(CONFIG_RUST) += alloc.o bindings.o hex.o kernel.o always-$(CONFIG_RUST) += exports_alloc_generated.h exports_bindings_generated.h \ exports_kernel_generated.h @@ -65,6 +65,15 @@ alloc-cfgs = \ --cfg no_rc \ --cfg no_sync +hex-skip_flags := \ + --edition=2021 \ + -Drust_2018_idioms \ + -Dunreachable_pub + +hex-flags := \ + --edition=2018 \ + -Amissing_docs + quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< cmd_rustdoc = \ OBJTREE=$(abspath $(objtree)) \ @@ -455,10 +464,17 @@ $(obj)/uapi.o: $(src)/uapi/lib.rs \ $(obj)/uapi/uapi_generated.rs FORCE +$(call if_changed_dep,rustc_library) +$(obj)/hex.o: private skip_clippy = 1 +$(obj)/hex.o: private skip_flags = $(hex-skip_flags) +$(obj)/hex.o: private rustc_target_flags = $(hex-flags) +$(obj)/hex.o: $(src)/hex/lib.rs $(obj)/compiler_builtins.o FORCE + $(call if_changed_dep,rustc_library) + $(obj)/kernel.o: private rustc_target_flags = --extern alloc \ - --extern build_error --extern macros --extern bindings --extern uapi + --extern build_error --extern macros --extern bindings --extern uapi \ + --extern hex $(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \ - $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE - +$(call if_changed_dep,rustc_library) + $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o $(obj)/hex.o FORCE + $(call if_changed_dep,rustc_library) endif # CONFIG_RUST diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 367cfeea74c5..2e9a64224c51 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -273,7 +273,7 @@ rust_common_cmd = \ -Zallow-features=$(rust_allowed_features) \ -Zcrate-attr=no_std \ -Zcrate-attr='feature($(rust_allowed_features))' \ - --extern alloc --extern kernel \ + --extern alloc --extern kernel --extern hex \ --crate-type rlib -L $(objtree)/rust/ \ --crate-name $(basename $(notdir $@)) \ --sysroot=/dev/null \ From patchwork Thu May 16 19:03:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666488 Received: from aer-iport-4.cisco.com (aer-iport-4.cisco.com [173.38.203.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F27E15ADA6; Thu, 16 May 2024 19:05:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886317; cv=none; b=p7Q0pJ6emCfOIdE7NQhtqEHlAfax+GyqYmdfTg0mUm/01NhBoTzcbtoMAP1zmPv5jiEg/HjLdaABeb0PlfWPoXIyCFJBgurBPYYmIPjXx0tRlVQpJ3oUoRe7ZJd6AGgW9ReRNWtdkxXc45UyAWozZLotEmPnjrscS2XymKhNkNg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886317; c=relaxed/simple; bh=C0ihuL2jj8QfBcPXgxKcqRDlDBwSCbXEYWR2OmjZkwU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ULd+DVRtz3GHpfi4WHKpvOJnC2ypfRxQykPxzrusejolyBD9CRc+LzxrL+fPPhzJp+3mGA04OMMQshJYXs1TTb3OelpcL+7qneaktXXJnug0W+oOmmvKUjYrKxh9zR00LXjnkyiaZRZxf9PLo4dvF5pShrtb/cE9Ytp53nBHqao= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=Gl9srvSx; arc=none smtp.client-ip=173.38.203.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="Gl9srvSx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=4299; q=dns/txt; s=iport; t=1715886315; x=1717095915; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XmrkWfcmaLB4LqRKL0XJRG+hfTU9BH5HMiJRTIlB8AY=; b=Gl9srvSxVW0jkbRvkgSKPc4mXARCAYT5/MuxUjZGXwfPUH1uArzQdsgh Voyzqs3MgqjVAH2aWIAXWRqxLeboT4Bk/+ltKb359DbINvpc3+wvHZPHq GQ0yVjbtpw9/FoqZnOtu1v6ym/ub6PGOaaBetxU6Wfv0MAGzguSrp4o+l I=; X-CSE-ConnectionGUID: 4EVdI9oZSiGwXuoPzTiTfQ== X-CSE-MsgGUID: fSSpwu+cRWaQ6JdKcx1PCg== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12379869" Received: from aer-iport-nat.cisco.com (HELO aer-core-8.cisco.com) ([173.38.203.22]) by aer-iport-4.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:04 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-8.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ43g0042440 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:03 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 05/22] rust: hex: add encode_hex_iter and encode_hex_upper_iter methods Date: Thu, 16 May 2024 22:03:28 +0300 Message-Id: <20240516190345.957477-6-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-8.cisco.com Add encode_hex_iter and encode_hex_upper_iter which return an iterator, so it can be used in conjunction with the Vec::from_iter_fallible function to (try to) create a hex string. Replace BytesToHexChars with BytesToHexByteSequence because String is not available. We need to collect the values in a Vec, append a NUL character and the create a CStr on top of it. Also remove the ToHex trait because it uses the FromIterator trait which cannot be implemented in the kernel due to the prohibition of infallible allocations. Signed-off-by: Ariel Miculas --- rust/hex/lib.rs | 60 ++++++++++++------------------------------------- 1 file changed, 14 insertions(+), 46 deletions(-) diff --git a/rust/hex/lib.rs b/rust/hex/lib.rs index a23def3f80db..3abf61ccbfc3 100644 --- a/rust/hex/lib.rs +++ b/rust/hex/lib.rs @@ -57,43 +57,18 @@ #[cfg(all(feature = "alloc", feature = "serde"))] pub use crate::serde::{serialize, serialize_upper}; -/// Encoding values as hex string. -/// -/// This trait is implemented for all `T` which implement `AsRef<[u8]>`. This -/// includes `String`, `str`, `Vec` and `[u8]`. -/// -/// # Example -/// -/// ``` -/// use hex::ToHex; -/// -/// println!("{}", "Hello world!".encode_hex::()); -/// # assert_eq!("Hello world!".encode_hex::(), "48656c6c6f20776f726c6421".to_string()); -/// ``` -/// -/// *Note*: instead of using this trait, you might want to use [`encode()`]. -pub trait ToHex { - /// Encode the hex strict representing `self` into the result. Lower case - /// letters are used (e.g. `f9b4ca`) - fn encode_hex>(&self) -> T; - - /// Encode the hex strict representing `self` into the result. Upper case - /// letters are used (e.g. `F9B4CA`) - fn encode_hex_upper>(&self) -> T; -} - const HEX_CHARS_LOWER: &[u8; 16] = b"0123456789abcdef"; const HEX_CHARS_UPPER: &[u8; 16] = b"0123456789ABCDEF"; -struct BytesToHexChars<'a> { +struct BytesToHexByteSequence<'a> { inner: ::core::slice::Iter<'a, u8>, table: &'static [u8; 16], - next: Option, + next: Option, } -impl<'a> BytesToHexChars<'a> { - fn new(inner: &'a [u8], table: &'static [u8; 16]) -> BytesToHexChars<'a> { - BytesToHexChars { +impl<'a> BytesToHexByteSequence<'a> { + fn new(inner: &'a [u8], table: &'static [u8; 16]) -> BytesToHexByteSequence<'a> { + BytesToHexByteSequence { inner: inner.iter(), table, next: None, @@ -101,15 +76,15 @@ impl<'a> BytesToHexChars<'a> { } } -impl<'a> Iterator for BytesToHexChars<'a> { - type Item = char; +impl<'a> Iterator for BytesToHexByteSequence<'a> { + type Item = u8; fn next(&mut self) -> Option { match self.next.take() { Some(current) => Some(current), None => self.inner.next().map(|byte| { - let current = self.table[(byte >> 4) as usize] as char; - self.next = Some(self.table[(byte & 0x0F) as usize] as char); + let current = self.table[(byte >> 4) as usize]; + self.next = Some(self.table[(byte & 0x0F) as usize]); current }), } @@ -121,7 +96,7 @@ fn size_hint(&self) -> (usize, Option) { } } -impl<'a> iter::ExactSizeIterator for BytesToHexChars<'a> { +impl<'a> iter::ExactSizeIterator for BytesToHexByteSequence<'a> { fn len(&self) -> usize { let mut length = self.inner.len() * 2; if self.next.is_some() { @@ -131,19 +106,12 @@ fn len(&self) -> usize { } } -#[inline] -fn encode_to_iter>(table: &'static [u8; 16], source: &[u8]) -> T { - BytesToHexChars::new(source, table).collect() +pub fn encode_hex_iter<'a>(source: &'a [u8]) -> impl iter::Iterator + 'a { + BytesToHexByteSequence::new(source, HEX_CHARS_LOWER).into_iter() } -impl> ToHex for T { - fn encode_hex>(&self) -> U { - encode_to_iter(HEX_CHARS_LOWER, self.as_ref()) - } - - fn encode_hex_upper>(&self) -> U { - encode_to_iter(HEX_CHARS_UPPER, self.as_ref()) - } +pub fn encode_hex_upper_iter<'a>(source: &'a [u8]) -> impl iter::Iterator + 'a { + BytesToHexByteSequence::new(source, HEX_CHARS_UPPER).into_iter() } /// Types that can be decoded from a hex string. From patchwork Thu May 16 19:03:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666495 Received: from aer-iport-1.cisco.com (aer-iport-1.cisco.com [173.38.203.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB5181581EE; Thu, 16 May 2024 19:05:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886346; cv=none; b=rImxqpr/bwl/L3PhL0MPHqFXKxPuJQPtgReWfUybqh89FlYrX4QzZswmf0PEYOMkMWavTIUEwGagzi+oQT3c06JHIyEZGPR/fN4bkA8BLMCqZjOZGdwPPW5GPIKWNelqfD0rHR3IOG1R1wFoSAausA6yAkVvxnrRoZHxPAPArds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886346; c=relaxed/simple; bh=l1Ck2k+Ek+FoDiX7MdCY/O7IhZYyvBSXJ8HUMoyE/nE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=F5SnjEwicr1KVEJ2l/vLflt4ndMzHX8pLwTk8dBkTdOi3wa/BXylciFmPY8CQyCjQj/s1J7SZ076MjPZDSw50mYidzZgXiK413XNGFNcZBsGhD2X0UUi8RFewg0hgNAD+P6cae8Y/i24vZIeYAMH8ZcToPAdJKJizqaC388ApUo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=NofPZdgK; arc=none smtp.client-ip=173.38.203.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="NofPZdgK" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=932915; q=dns/txt; s=iport; t=1715886312; x=1717095912; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=M1n6BYrSPprOVkR5cxW6LU9CD1Y5iOXyBM2uYJT5uYE=; b=NofPZdgKPQl7FkuVwkgATfOCct7GE9evK/AXyLnov3QXdMl2PiXHiVkr YZ4I+bWwd24bT5rk2sml/zkDnb+i/uVSPclO/n5P7Y6/gAyQeM5FhcE5f kXKcXRbxIkXb37OA3cdjGfrXYpkMBrRp6txzPXR94rwnUqeaQFoSFd9dR E=; X-CSE-ConnectionGUID: ytwXVbTeQUyD5ujJag2ufA== X-CSE-MsgGUID: O6J2vq9FR1eTdyekl/GzGA== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12419633" Received: from aer-iport-nat.cisco.com (HELO aer-core-3.cisco.com) ([173.38.203.22]) by aer-iport-1.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:09 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-3.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ44as017876 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:04 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 06/22] rust: capnp: import crate Date: Thu, 16 May 2024 22:03:29 +0300 Message-Id: <20240516190345.957477-7-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-3.cisco.com This is a subset of the Rust `capnp` crate, version capnpc-v0.18.0, licensed under "MIT", from: https://github.com/capnproto/capnproto-rust/tree/capnpc-v0.18.0/capnp/src The files are copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers). For copyright details, please see: https://github.com/capnproto/capnproto-rust/blob/capnpc-v0.18.0/LICENSE The next patches modify these files as needed for use within the kernel. This patch split allows reviewers to double-check the import and to clearly see the differences introduced. The following script may be used to verify the contents: for path in $(cd rust/capnp/ && find . -type f -name '*.rs'); do curl --silent --show-error --location \ https://github.com/capnproto/capnproto-rust/raw/capnpc-v0.18.0/capnp/src/$path \ | diff --unified rust/capnp/$path - && echo $path: OK done Signed-off-by: Ariel Miculas --- rust/capnp/any_pointer.rs | 313 + rust/capnp/any_pointer_list.rs | 208 + rust/capnp/capability.rs | 363 + rust/capnp/capability_list.rs | 297 + rust/capnp/constant.rs | 54 + rust/capnp/data.rs | 95 + rust/capnp/data_list.rs | 218 + rust/capnp/dynamic_list.rs | 408 + rust/capnp/dynamic_struct.rs | 782 + rust/capnp/dynamic_value.rs | 317 + rust/capnp/enum_list.rs | 237 + rust/capnp/introspect.rs | 282 + rust/capnp/io.rs | 202 + rust/capnp/lib.rs | 651 + rust/capnp/list_list.rs | 296 + rust/capnp/message.rs | 878 + rust/capnp/primitive_list.rs | 279 + rust/capnp/private/arena.rs | 417 + rust/capnp/private/capability.rs | 155 + rust/capnp/private/layout.rs | 4210 +++++ rust/capnp/private/layout_test.rs | 192 + rust/capnp/private/mask.rs | 62 + rust/capnp/private/mod.rs | 36 + rust/capnp/private/primitive.rs | 119 + rust/capnp/private/read_limiter.rs | 113 + rust/capnp/private/units.rs | 68 + rust/capnp/private/zero.rs | 46 + rust/capnp/raw.rs | 69 + rust/capnp/schema.rs | 430 + rust/capnp/schema_capnp.rs | 14448 ++++++++++++++++ rust/capnp/serialize.rs | 961 + .../serialize/no_alloc_buffer_segments.rs | 627 + rust/capnp/serialize_packed.rs | 618 + rust/capnp/stringify.rs | 181 + rust/capnp/struct_list.rs | 300 + rust/capnp/text.rs | 294 + rust/capnp/text_list.rs | 216 + rust/capnp/traits.rs | 233 + 38 files changed, 29675 insertions(+) create mode 100644 rust/capnp/any_pointer.rs create mode 100644 rust/capnp/any_pointer_list.rs create mode 100644 rust/capnp/capability.rs create mode 100644 rust/capnp/capability_list.rs create mode 100644 rust/capnp/constant.rs create mode 100644 rust/capnp/data.rs create mode 100644 rust/capnp/data_list.rs create mode 100644 rust/capnp/dynamic_list.rs create mode 100644 rust/capnp/dynamic_struct.rs create mode 100644 rust/capnp/dynamic_value.rs create mode 100644 rust/capnp/enum_list.rs create mode 100644 rust/capnp/introspect.rs create mode 100644 rust/capnp/io.rs create mode 100644 rust/capnp/lib.rs create mode 100644 rust/capnp/list_list.rs create mode 100644 rust/capnp/message.rs create mode 100644 rust/capnp/primitive_list.rs create mode 100644 rust/capnp/private/arena.rs create mode 100644 rust/capnp/private/capability.rs create mode 100644 rust/capnp/private/layout.rs create mode 100644 rust/capnp/private/layout_test.rs create mode 100644 rust/capnp/private/mask.rs create mode 100644 rust/capnp/private/mod.rs create mode 100644 rust/capnp/private/primitive.rs create mode 100644 rust/capnp/private/read_limiter.rs create mode 100644 rust/capnp/private/units.rs create mode 100644 rust/capnp/private/zero.rs create mode 100644 rust/capnp/raw.rs create mode 100644 rust/capnp/schema.rs create mode 100644 rust/capnp/schema_capnp.rs create mode 100644 rust/capnp/serialize.rs create mode 100644 rust/capnp/serialize/no_alloc_buffer_segments.rs create mode 100644 rust/capnp/serialize_packed.rs create mode 100644 rust/capnp/stringify.rs create mode 100644 rust/capnp/struct_list.rs create mode 100644 rust/capnp/text.rs create mode 100644 rust/capnp/text_list.rs create mode 100644 rust/capnp/traits.rs diff --git a/rust/capnp/any_pointer.rs b/rust/capnp/any_pointer.rs new file mode 100644 index 000000000000..c49216cd031e --- /dev/null +++ b/rust/capnp/any_pointer.rs @@ -0,0 +1,313 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Untyped pointer that can be cast to any struct, list, or capability type. + +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, vec::Vec}; + +#[cfg(feature = "alloc")] +use crate::capability::FromClientHook; +#[cfg(feature = "alloc")] +use crate::private::capability::{ClientHook, PipelineHook, PipelineOp}; +use crate::private::layout::{PointerBuilder, PointerReader}; +use crate::traits::{FromPointerBuilder, FromPointerReader, SetPointerBuilder}; +use crate::Result; + +#[derive(Copy, Clone)] +pub struct Owned(()); + +impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; +} + +impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::AnyPointer.into() + } +} + +impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; +} + +#[derive(Copy, Clone)] +pub struct Reader<'a> { + pub(crate) reader: PointerReader<'a>, +} + +impl<'a> Reader<'a> { + pub fn new(reader: PointerReader<'_>) -> Reader<'_> { + Reader { reader } + } + + #[inline] + pub fn is_null(&self) -> bool { + self.reader.is_null() + } + + /// Gets the total size of the target and all of its children. Does not count far pointer overhead. + pub fn target_size(&self) -> Result { + self.reader.total_size() + } + + #[inline] + pub fn get_as>(&self) -> Result { + FromPointerReader::get_from_pointer(&self.reader, None) + } + + #[cfg(feature = "alloc")] + pub fn get_as_capability(&self) -> Result { + Ok(FromClientHook::new(self.reader.get_capability()?)) + } + + //# Used by RPC system to implement pipelining. Applications + //# generally shouldn't use this directly. + #[cfg(feature = "alloc")] + pub fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Result> { + let mut pointer = self.reader; + + for op in ops { + match *op { + PipelineOp::Noop => {} + PipelineOp::GetPointerField(idx) => { + pointer = pointer.get_struct(None)?.get_pointer_field(idx as usize); + } + } + } + + pointer.get_capability() + } +} + +impl<'a> FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + if default.is_some() { + panic!("Unsupported: any_pointer with a default value."); + } + Ok(Reader { reader: *reader }) + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> Result<()> { + pointer.copy_from(value.reader, canonicalize) + } +} + +#[cfg(feature = "alloc")] +impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)); + } +} + +pub struct Builder<'a> { + builder: PointerBuilder<'a>, +} + +impl<'a> Builder<'a> { + pub fn new(builder: PointerBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + + pub fn is_null(&self) -> bool { + self.builder.is_null() + } + + /// Gets the total size of the target and all of its children. Does not count far pointer overhead. + pub fn target_size(&self) -> Result { + self.builder.as_reader().total_size() + } + + pub fn get_as>(self) -> Result { + FromPointerBuilder::get_from_pointer(self.builder, None) + } + + pub fn init_as>(self) -> T { + FromPointerBuilder::init_pointer(self.builder, 0) + } + + pub fn initn_as>(self, size: u32) -> T { + FromPointerBuilder::init_pointer(self.builder, size) + } + + pub fn set_as(&mut self, value: From) -> Result<()> { + SetPointerBuilder::set_pointer_builder(self.builder.reborrow(), value, false) + } + + // XXX value should be a user client. + #[cfg(feature = "alloc")] + pub fn set_as_capability(&mut self, value: Box) { + self.builder.set_capability(value); + } + + #[inline] + pub fn clear(&mut self) { + self.builder.clear() + } + + pub fn into_reader(self) -> Reader<'a> { + Reader { + reader: self.builder.into_reader(), + } + } +} + +impl<'a> FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(mut builder: PointerBuilder<'a>, _len: u32) -> Builder<'a> { + if !builder.is_null() { + builder.clear(); + } + Builder { builder } + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + if default.is_some() { + panic!("AnyPointer defaults are unsupported") + } + Ok(Builder { builder }) + } +} + +#[cfg(feature = "alloc")] +impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)); + } +} + +pub struct Pipeline { + // XXX this should not be public + #[cfg(feature = "alloc")] + pub hook: Box, + + #[cfg(feature = "alloc")] + ops: Vec, +} + +impl Pipeline { + #[cfg(feature = "alloc")] + pub fn new(hook: Box) -> Self { + Self { + hook, + ops: Vec::new(), + } + } + + #[cfg(feature = "alloc")] + pub fn noop(&self) -> Self { + Self { + hook: self.hook.add_ref(), + ops: self.ops.clone(), + } + } + + #[cfg(not(feature = "alloc"))] + pub fn noop(&self) -> Self { + Self {} + } + + #[cfg(feature = "alloc")] + pub fn get_pointer_field(&self, pointer_index: u16) -> Self { + let mut new_ops = Vec::with_capacity(self.ops.len() + 1); + for op in &self.ops { + new_ops.push(*op) + } + new_ops.push(PipelineOp::GetPointerField(pointer_index)); + Self { + hook: self.hook.add_ref(), + ops: new_ops, + } + } + + #[cfg(not(feature = "alloc"))] + pub fn get_pointer_field(&self, _pointer_index: u16) -> Self { + Self {} + } + + #[cfg(feature = "alloc")] + pub fn as_cap(&self) -> Box { + self.hook.get_pipelined_cap(&self.ops) + } +} + +impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: Pipeline) -> Self { + typeless + } +} + +impl<'a> From> for crate::dynamic_value::Reader<'a> { + fn from(a: Reader<'a>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::AnyPointer(a) + } +} + +impl<'a> From> for crate::dynamic_value::Builder<'a> { + fn from(a: Builder<'a>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::AnyPointer(a) + } +} + +#[cfg(feature = "alloc")] +#[test] +fn init_clears_value() { + let mut message = crate::message::Builder::new_default(); + { + let root: crate::any_pointer::Builder = message.init_root(); + let mut list: crate::primitive_list::Builder = root.initn_as(10); + for idx in 0..10 { + list.set(idx, idx as u16); + } + } + + { + let root: crate::any_pointer::Builder = message.init_root(); + assert!(root.is_null()); + } + + let mut output: Vec = Vec::new(); + crate::serialize::write_message(&mut output, &message).unwrap(); + assert_eq!(output.len(), 40); + for byte in &output[8..] { + // Everything not in the message header is zero. + assert_eq!(*byte, 0u8); + } +} diff --git a/rust/capnp/any_pointer_list.rs b/rust/capnp/any_pointer_list.rs new file mode 100644 index 000000000000..1c4e9e40c879 --- /dev/null +++ b/rust/capnp/any_pointer_list.rs @@ -0,0 +1,208 @@ +// Copyright (c) 2018 the capnproto-rust contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of AnyPointers. +//! +//! Note: this cannot be used for a list of structs, since such lists are not encoded +//! as pointer lists. + +use crate::private::layout::{ListBuilder, ListReader, Pointer, PointerBuilder, PointerReader}; +use crate::traits::{FromPointerBuilder, FromPointerReader, IndexMove, ListIter}; +use crate::Result; + +#[derive(Clone, Copy)] +pub struct Owned; + +impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; +} + +impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::Type::list_of(crate::introspect::TypeVariant::AnyPointer.into()) + } +} + +#[derive(Clone, Copy)] +pub struct Reader<'a> { + pub reader: ListReader<'a>, +} + +impl<'a> Reader<'a> { + pub(crate) fn new(reader: ListReader<'_>) -> Reader<'_> { + Reader { reader } + } + + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, Result>> { + let l = self.len(); + ListIter::new(self, l) + } + + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> crate::any_pointer::Reader<'a> { + assert!(index < self.len()); + crate::any_pointer::Reader::new(self.reader.get_pointer_element(index)) + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option> { + if index < self.len() { + Some(crate::any_pointer::Reader::new( + self.reader.get_pointer_element(index), + )) + } else { + None + } + } +} + +impl<'a> IndexMove>> for Reader<'a> { + fn index_move(&self, index: u32) -> Result> { + Ok(self.get(index)) + } +} + +impl<'a> FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(Pointer, default)?, + }) + } +} + +impl<'a> crate::traits::IntoInternalListReader<'a> for Reader<'a> { + fn into_internal_list_reader(self) -> ListReader<'a> { + self.reader + } +} + +pub struct Builder<'a> { + builder: ListBuilder<'a>, +} + +impl<'a> Builder<'a> { + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn into_reader(self) -> Reader<'a> { + Reader { + reader: self.builder.into_reader(), + } + } + + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> crate::any_pointer::Builder<'a> { + assert!(index < self.len()); + crate::any_pointer::Builder::new(self.builder.get_pointer_element(index)) + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option> { + if index < self.len() { + Some(crate::any_pointer::Builder::new( + self.builder.get_pointer_element(index), + )) + } else { + None + } + } + + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } +} + +impl<'a> FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a> { + Builder { + builder: builder.init_list(Pointer, size), + } + } + + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + builder: builder.get_list(Pointer, default)?, + }) + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize)?; + Ok(()) + } +} + +impl<'a> core::iter::IntoIterator for Reader<'a> { + type Item = Result>; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a> From> for crate::dynamic_value::Reader<'a> { + fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( + t.reader, + ::introspect(), + )) + } +} + +impl<'a> From> for crate::dynamic_value::Builder<'a> { + fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( + t.builder, + ::introspect(), + )) + } +} diff --git a/rust/capnp/capability.rs b/rust/capnp/capability.rs new file mode 100644 index 000000000000..7cff20bbbcb9 --- /dev/null +++ b/rust/capnp/capability.rs @@ -0,0 +1,363 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Hooks for for the RPC system. +//! +//! Roughly corresponds to capability.h in the C++ implementation. + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +#[cfg(feature = "alloc")] +use core::future::Future; +#[cfg(feature = "alloc")] +use core::marker::{PhantomData, Unpin}; +#[cfg(feature = "rpc_try")] +use core::ops::Try; +#[cfg(feature = "alloc")] +use core::pin::Pin; +#[cfg(feature = "alloc")] +use core::task::Poll; + +use crate::any_pointer; +#[cfg(feature = "alloc")] +use crate::private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook}; +#[cfg(feature = "alloc")] +use crate::traits::{Owned, Pipelined}; +#[cfg(feature = "alloc")] +use crate::{Error, MessageSize}; + +/// A computation that might eventually resolve to a value of type `T` or to an error +/// of type `E`. Dropping the promise cancels the computation. +#[cfg(feature = "alloc")] +#[must_use = "futures do nothing unless polled"] +pub struct Promise { + inner: PromiseInner, +} + +#[cfg(feature = "alloc")] +enum PromiseInner { + Immediate(Result), + Deferred(Pin> + 'static>>), + Empty, +} + +// Allow Promise to be Unpin, regardless of whether T and E are. +#[cfg(feature = "alloc")] +impl Unpin for PromiseInner {} + +#[cfg(feature = "alloc")] +impl Promise { + pub fn ok(value: T) -> Self { + Self { + inner: PromiseInner::Immediate(Ok(value)), + } + } + + pub fn err(error: E) -> Self { + Self { + inner: PromiseInner::Immediate(Err(error)), + } + } + + pub fn from_future(f: F) -> Self + where + F: Future> + 'static, + { + Self { + inner: PromiseInner::Deferred(Box::pin(f)), + } + } +} + +#[cfg(feature = "alloc")] +impl Future for Promise { + type Output = core::result::Result; + + fn poll(self: Pin<&mut Self>, cx: &mut ::core::task::Context) -> Poll { + match self.get_mut().inner { + PromiseInner::Empty => panic!("Promise polled after done."), + ref mut imm @ PromiseInner::Immediate(_) => { + match core::mem::replace(imm, PromiseInner::Empty) { + PromiseInner::Immediate(r) => Poll::Ready(r), + _ => unreachable!(), + } + } + PromiseInner::Deferred(ref mut f) => f.as_mut().poll(cx), + } + } +} + +#[cfg(feature = "alloc")] +#[cfg(feature = "rpc_try")] +impl core::ops::Try for Promise { + type Output = Self; + type Residual = Result; + + fn from_output(output: Self::Output) -> Self { + output + } + + fn branch(self) -> core::ops::ControlFlow { + unimplemented!(); + } +} + +#[cfg(feature = "alloc")] +#[cfg(feature = "rpc_try")] +impl core::ops::FromResidual for Promise { + fn from_residual(residual: ::Residual) -> Self { + match residual { + Ok(_) => unimplemented!(), + Err(e) => Self::err(e), + } + } +} + +/// A promise for a result from a method call. +#[cfg(feature = "alloc")] +#[must_use] +pub struct RemotePromise +where + Results: Pipelined + Owned + 'static, +{ + pub promise: Promise, crate::Error>, + pub pipeline: Results::Pipeline, +} + +/// A response from a method call, as seen by the client. +#[cfg(feature = "alloc")] +pub struct Response { + pub marker: PhantomData, + pub hook: Box, +} + +#[cfg(feature = "alloc")] +impl Response +where + Results: Pipelined + Owned, +{ + pub fn new(hook: Box) -> Self { + Self { + marker: PhantomData, + hook, + } + } + pub fn get(&self) -> crate::Result> { + self.hook.get()?.get_as() + } +} + +/// A method call that has not been sent yet. +#[cfg(feature = "alloc")] +pub struct Request { + pub marker: PhantomData<(Params, Results)>, + pub hook: Box, +} + +#[cfg(feature = "alloc")] +impl Request +where + Params: Owned, +{ + pub fn new(hook: Box) -> Self { + Self { + hook, + marker: PhantomData, + } + } + + pub fn get(&mut self) -> Params::Builder<'_> { + self.hook.get().get_as().unwrap() + } + + pub fn set(&mut self, from: Params::Reader<'_>) -> crate::Result<()> { + self.hook.get().set_as(from) + } +} + +#[cfg(feature = "alloc")] +impl Request +where + Results: Pipelined + Owned + 'static + Unpin, + ::Pipeline: FromTypelessPipeline, +{ + pub fn send(self) -> RemotePromise { + let RemotePromise { + promise, pipeline, .. + } = self.hook.send(); + let typed_promise = Promise::from_future(async move { + Ok(Response { + hook: promise.await?.hook, + marker: PhantomData, + }) + }); + RemotePromise { + promise: typed_promise, + pipeline: FromTypelessPipeline::new(pipeline), + } + } +} + +/// The values of the parameters passed to a method call, as seen by the server. +#[cfg(feature = "alloc")] +pub struct Params { + pub marker: PhantomData, + pub hook: Box, +} + +#[cfg(feature = "alloc")] +impl Params { + pub fn new(hook: Box) -> Self { + Self { + marker: PhantomData, + hook, + } + } + pub fn get(&self) -> crate::Result> + where + T: Owned, + { + self.hook.get()?.get_as() + } +} + +/// The return values of a method, written in-place by the method body. +#[cfg(feature = "alloc")] +pub struct Results { + pub marker: PhantomData, + pub hook: Box, +} + +#[cfg(feature = "alloc")] +impl Results +where + T: Owned, +{ + pub fn new(hook: Box) -> Self { + Self { + marker: PhantomData, + hook, + } + } + + pub fn get(&mut self) -> T::Builder<'_> { + self.hook.get().unwrap().get_as().unwrap() + } + + pub fn set(&mut self, other: T::Reader<'_>) -> crate::Result<()> { + self.hook.get().unwrap().set_as(other) + } +} + +pub trait FromTypelessPipeline { + fn new(typeless: any_pointer::Pipeline) -> Self; +} + +/// Trait implemented (via codegen) by all user-defined capability client types. +#[cfg(feature = "alloc")] +pub trait FromClientHook { + /// Wraps a client hook to create a new client. + fn new(hook: Box) -> Self; + + /// Unwraps client to get the underlying client hook. + fn into_client_hook(self) -> Box; + + /// Gets a reference to the underlying client hook. + fn as_client_hook(&self) -> &dyn ClientHook; + + /// Casts `self` to another instance of `FromClientHook`. This always succeeds, + /// but if the underlying capability does not actually implement `T`'s interface, + /// then method calls will fail with "unimplemented" errors. + fn cast_to(self) -> T + where + Self: Sized, + { + FromClientHook::new(self.into_client_hook()) + } +} + +/// An untyped client. +#[cfg(feature = "alloc")] +pub struct Client { + pub hook: Box, +} + +#[cfg(feature = "alloc")] +impl Client { + pub fn new(hook: Box) -> Self { + Self { hook } + } + + pub fn new_call( + &self, + interface_id: u64, + method_id: u16, + size_hint: Option, + ) -> Request { + let typeless = self.hook.new_call(interface_id, method_id, size_hint); + Request { + hook: typeless.hook, + marker: PhantomData, + } + } + + /// If the capability is actually only a promise, the returned promise resolves once the + /// capability itself has resolved to its final destination (or propagates the exception if + /// the capability promise is rejected). This is mainly useful for error-checking in the case + /// where no calls are being made. There is no reason to wait for this before making calls; if + /// the capability does not resolve, the call results will propagate the error. + pub fn when_resolved(&self) -> Promise<(), Error> { + self.hook.when_resolved() + } +} + +/// An untyped server. +#[cfg(feature = "alloc")] +pub trait Server { + fn dispatch_call( + &mut self, + interface_id: u64, + method_id: u16, + params: Params, + results: Results, + ) -> Promise<(), Error>; +} + +/// Trait to track the relationship between generated Server traits and Client structs. +#[cfg(feature = "alloc")] +pub trait FromServer: FromClientHook { + // Implemented by the generated ServerDispatch struct. + type Dispatch: Server + 'static + core::ops::DerefMut; + + fn from_server(s: S) -> Self::Dispatch; +} + +/// Gets the "resolved" version of a capability. One place this is useful is for pre-resolving +/// the argument to `capnp_rpc::CapabilityServerSet::get_local_server_of_resolved()`. +#[cfg(feature = "alloc")] +pub async fn get_resolved_cap(cap: C) -> C { + let mut hook = cap.into_client_hook(); + let _ = hook.when_resolved().await; + while let Some(resolved) = hook.get_resolved() { + hook = resolved; + } + FromClientHook::new(hook) +} diff --git a/rust/capnp/capability_list.rs b/rust/capnp/capability_list.rs new file mode 100644 index 000000000000..083794e073d1 --- /dev/null +++ b/rust/capnp/capability_list.rs @@ -0,0 +1,297 @@ +// Copyright (c) 2017 David Renshaw and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of capabilities. +#![cfg(feature = "alloc")] + +use alloc::boxed::Box; +use core::marker::PhantomData; + +use crate::capability::FromClientHook; +use crate::private::capability::ClientHook; +use crate::private::layout::{ListBuilder, ListReader, Pointer, PointerBuilder, PointerReader}; +use crate::traits::{FromPointerBuilder, FromPointerReader, IndexMove, ListIter}; +use crate::Result; + +#[derive(Copy, Clone)] +pub struct Owned +where + T: FromClientHook, +{ + marker: PhantomData, +} + +impl crate::introspect::Introspect for Owned +where + T: FromClientHook, +{ + fn introspect() -> crate::introspect::Type { + crate::introspect::Type::list_of(crate::introspect::TypeVariant::Capability.into()) + } +} + +impl crate::traits::Owned for Owned +where + T: FromClientHook, +{ + type Reader<'a> = Reader<'a, T>; + type Builder<'a> = Builder<'a, T>; +} + +pub struct Reader<'a, T> +where + T: FromClientHook, +{ + marker: PhantomData, + reader: ListReader<'a>, +} + +impl<'a, T> Clone for Reader<'a, T> +where + T: FromClientHook, +{ + fn clone(&self) -> Reader<'a, T> { + *self + } +} +impl<'a, T> Copy for Reader<'a, T> where T: FromClientHook {} + +impl<'a, T> Reader<'a, T> +where + T: FromClientHook, +{ + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, Result> { + ListIter::new(self, self.len()) + } +} + +impl<'a, T> Reader<'a, T> +where + T: FromClientHook, +{ + pub fn reborrow(&self) -> Reader<'_, T> { + Reader { + reader: self.reader, + marker: PhantomData, + } + } +} + +impl<'a, T> FromPointerReader<'a> for Reader<'a, T> +where + T: FromClientHook, +{ + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(Pointer, default)?, + marker: PhantomData, + }) + } +} + +impl<'a, T> Reader<'a, T> +where + T: FromClientHook, +{ + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> Result { + assert!(index < self.len()); + Ok(FromClientHook::new( + self.reader.get_pointer_element(index).get_capability()?, + )) + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option> { + if index < self.len() { + Some( + self.reader + .get_pointer_element(index) + .get_capability() + .map(FromClientHook::new), + ) + } else { + None + } + } +} + +impl<'a, T> IndexMove> for Reader<'a, T> +where + T: FromClientHook, +{ + fn index_move(&self, index: u32) -> Result { + self.get(index) + } +} + +pub struct Builder<'a, T> +where + T: FromClientHook, +{ + marker: PhantomData, + builder: ListBuilder<'a>, +} + +impl<'a, T> Builder<'a, T> +where + T: FromClientHook, +{ + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn into_reader(self) -> Reader<'a, T> { + Reader { + marker: PhantomData, + reader: self.builder.into_reader(), + } + } + + pub fn set(&mut self, index: u32, value: Box) { + assert!(index < self.len()); + self.builder + .reborrow() + .get_pointer_element(index) + .set_capability(value); + } +} + +impl<'a, T> Builder<'a, T> +where + T: FromClientHook, +{ + pub fn reborrow(&mut self) -> Builder<'_, T> { + Builder { + builder: self.builder.reborrow(), + marker: PhantomData, + } + } +} + +impl<'a, T> FromPointerBuilder<'a> for Builder<'a, T> +where + T: FromClientHook, +{ + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a, T> { + Builder { + marker: PhantomData, + builder: builder.init_list(Pointer, size), + } + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + marker: PhantomData, + builder: builder.get_list(Pointer, default)?, + }) + } +} + +impl<'a, T> Builder<'a, T> +where + T: FromClientHook, +{ + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> Result { + assert!(index < self.len()); + Ok(FromClientHook::new( + self.builder.get_pointer_element(index).get_capability()?, + )) + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option> { + if index < self.len() { + Some( + self.builder + .get_pointer_element(index) + .get_capability() + .map(FromClientHook::new), + ) + } else { + None + } + } +} + +impl<'a, T> crate::traits::SetPointerBuilder for Reader<'a, T> +where + T: FromClientHook, +{ + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a, T>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize) + } +} + +impl<'a, T> ::core::iter::IntoIterator for Reader<'a, T> +where + T: FromClientHook, +{ + type Item = Result; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T: FromClientHook> From> for crate::dynamic_value::Reader<'a> { + fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( + t.reader, + crate::introspect::TypeVariant::Capability.into(), + )) + } +} + +impl<'a, T: FromClientHook> From> for crate::dynamic_value::Builder<'a> { + fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( + t.builder, + crate::introspect::TypeVariant::Capability.into(), + )) + } +} diff --git a/rust/capnp/constant.rs b/rust/capnp/constant.rs new file mode 100644 index 000000000000..fdd1edf487ff --- /dev/null +++ b/rust/capnp/constant.rs @@ -0,0 +1,54 @@ +// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Helper type for generated Struct and List constants. +//! +//! `constant::Reader` does not do bounds-checking, so it is unsafe to +//! manually construct one of these. + +use core::marker::PhantomData; + +use crate::any_pointer; +use crate::private::layout::PointerReader; +use crate::traits::Owned; +use crate::Result; + +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct Reader { + #[doc(hidden)] + pub phantom: PhantomData, + + #[doc(hidden)] + pub words: &'static [crate::Word], +} + +impl Reader +where + T: Owned, +{ + /// Retrieve the value. + pub fn get(&self) -> Result<::Reader<'static>> { + any_pointer::Reader::new(unsafe { + PointerReader::get_root_unchecked(self.words.as_ptr() as *const u8) + }) + .get_as() + } +} diff --git a/rust/capnp/data.rs b/rust/capnp/data.rs new file mode 100644 index 000000000000..89e0c6c19ea4 --- /dev/null +++ b/rust/capnp/data.rs @@ -0,0 +1,95 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Sequence of bytes. + +use crate::private::layout::{PointerBuilder, PointerReader}; +use crate::Result; + +#[derive(Copy, Clone)] +pub struct Owned(()); + +impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; +} + +impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Data.into() + } +} + +pub type Reader<'a> = &'a [u8]; + +pub(crate) unsafe fn reader_from_raw_parts<'a>(p: *const u8, len: u32) -> Reader<'a> { + ::core::slice::from_raw_parts(p, len as usize) +} + +impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + reader.get_data(default) + } +} + +pub type Builder<'a> = &'a mut [u8]; + +pub(crate) unsafe fn builder_from_raw_parts<'a>(p: *mut u8, len: u32) -> Builder<'a> { + ::core::slice::from_raw_parts_mut(p, len as usize) +} + +impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a> { + builder.init_data(size) + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + builder.get_data(default) + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: PointerBuilder<'b>, + value: Reader<'a>, + _canonicalize: bool, + ) -> Result<()> { + pointer.set_data(value); + Ok(()) + } +} + +impl<'a> From> for crate::dynamic_value::Reader<'a> { + fn from(d: Reader<'a>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::Data(d) + } +} + +impl<'a> From> for crate::dynamic_value::Builder<'a> { + fn from(d: Builder<'a>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::Data(d) + } +} diff --git a/rust/capnp/data_list.rs b/rust/capnp/data_list.rs new file mode 100644 index 000000000000..f5fee2575fd2 --- /dev/null +++ b/rust/capnp/data_list.rs @@ -0,0 +1,218 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of sequences of bytes. + +use crate::private::layout::*; +use crate::traits::{FromPointerBuilder, FromPointerReader, IndexMove, ListIter}; +use crate::Result; + +#[derive(Copy, Clone)] +pub struct Owned; + +impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; +} + +impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::Type::list_of(crate::introspect::TypeVariant::Data.into()) + } +} + +#[derive(Clone, Copy)] +pub struct Reader<'a> { + pub reader: ListReader<'a>, +} + +impl<'a> Reader<'a> { + pub fn new(reader: ListReader<'_>) -> Reader<'_> { + Reader { reader } + } + + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, Result>> { + let l = self.len(); + ListIter::new(self, l) + } +} + +impl<'a> FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(Pointer, default)?, + }) + } +} + +impl<'a> IndexMove>> for Reader<'a> { + fn index_move(&self, index: u32) -> Result> { + self.get(index) + } +} + +impl<'a> Reader<'a> { + /// Gets the `data::Reader` at position `index`. Panics if `index` is + /// greater than or equal to `len()`. + pub fn get(self, index: u32) -> Result> { + assert!(index < self.len()); + self.reader.get_pointer_element(index).get_data(None) + } + + /// Gets the `data::Reader` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option>> { + if index < self.len() { + Some(self.reader.get_pointer_element(index).get_data(None)) + } else { + None + } + } +} + +impl<'a> crate::traits::IntoInternalListReader<'a> for Reader<'a> { + fn into_internal_list_reader(self) -> ListReader<'a> { + self.reader + } +} + +pub struct Builder<'a> { + builder: ListBuilder<'a>, +} + +impl<'a> Builder<'a> { + pub fn new(builder: ListBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn into_reader(self) -> Reader<'a> { + Reader { + reader: self.builder.into_reader(), + } + } + + pub fn set(&mut self, index: u32, value: crate::data::Reader) { + assert!(index < self.len()); + self.builder + .reborrow() + .get_pointer_element(index) + .set_data(value); + } + + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } +} + +impl<'a> FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a> { + Builder { + builder: builder.init_list(Pointer, size), + } + } + + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + builder: builder.get_list(Pointer, default)?, + }) + } +} + +impl<'a> Builder<'a> { + /// Gets the `data::Builder` at position `index`. Panics if `index` is + /// greater than or equal to `len()`. + pub fn get(self, index: u32) -> Result> { + assert!(index < self.len()); + self.builder.get_pointer_element(index).get_data(None) + } + + /// Gets the `data::Builder` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option>> { + if index < self.len() { + Some(self.builder.get_pointer_element(index).get_data(None)) + } else { + None + } + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize)?; + Ok(()) + } +} + +impl<'a> ::core::iter::IntoIterator for Reader<'a> { + type Item = Result>; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a> From> for crate::dynamic_value::Reader<'a> { + fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader { + reader: t.reader, + element_type: crate::introspect::TypeVariant::Data.into(), + }) + } +} + +impl<'a> From> for crate::dynamic_value::Builder<'a> { + fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder { + builder: t.builder, + element_type: crate::introspect::TypeVariant::Data.into(), + }) + } +} diff --git a/rust/capnp/dynamic_list.rs b/rust/capnp/dynamic_list.rs new file mode 100644 index 000000000000..f2c93e1cbe16 --- /dev/null +++ b/rust/capnp/dynamic_list.rs @@ -0,0 +1,408 @@ +//! Dynamically-typed lists. + +use crate::dynamic_value; +use crate::introspect::{Type, TypeVariant}; +use crate::private::layout::{self, PrimitiveElement}; +use crate::traits::{IndexMove, ListIter}; +use crate::{Error, ErrorKind, Result}; + +/// A read-only dynamically-typed list. +#[derive(Copy, Clone)] +pub struct Reader<'a> { + pub(crate) reader: layout::ListReader<'a>, + pub(crate) element_type: Type, +} + +impl<'a> From> for dynamic_value::Reader<'a> { + fn from(x: Reader<'a>) -> dynamic_value::Reader<'a> { + dynamic_value::Reader::List(x) + } +} + +impl<'a> Reader<'a> { + pub(crate) fn new(reader: layout::ListReader<'a>, element_type: Type) -> Self { + Self { + reader, + element_type, + } + } + + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn element_type(&self) -> Type { + self.element_type + } + + pub fn get(self, index: u32) -> Result> { + assert!(index < self.reader.len()); + match self.element_type.which() { + TypeVariant::Void => Ok(dynamic_value::Reader::Void), + TypeVariant::Bool => Ok(dynamic_value::Reader::Bool(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::Int8 => Ok(dynamic_value::Reader::Int8(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::Int16 => Ok(dynamic_value::Reader::Int16(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::Int32 => Ok(dynamic_value::Reader::Int32(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::Int64 => Ok(dynamic_value::Reader::Int64(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::UInt8 => Ok(dynamic_value::Reader::UInt8(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::UInt16 => Ok(dynamic_value::Reader::UInt16(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::UInt32 => Ok(dynamic_value::Reader::UInt32(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::UInt64 => Ok(dynamic_value::Reader::UInt64(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::Float32 => Ok(dynamic_value::Reader::Float32(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::Float64 => Ok(dynamic_value::Reader::Float64(PrimitiveElement::get( + &self.reader, + index, + ))), + TypeVariant::Enum(e) => Ok(dynamic_value::Enum::new( + PrimitiveElement::get(&self.reader, index), + e.into(), + ) + .into()), + TypeVariant::Text => Ok(dynamic_value::Reader::Text( + self.reader.get_pointer_element(index).get_text(None)?, + )), + TypeVariant::Data => Ok(dynamic_value::Reader::Data( + self.reader.get_pointer_element(index).get_data(None)?, + )), + TypeVariant::List(element_type) => Ok(Reader { + reader: self + .reader + .get_pointer_element(index) + .get_list(element_type.expected_element_size(), None)?, + element_type, + } + .into()), + TypeVariant::Struct(ss) => { + let r = self.reader.get_struct_element(index); + Ok(dynamic_value::Reader::Struct( + crate::dynamic_struct::Reader::new(r, ss.into()), + )) + } + TypeVariant::AnyPointer => { + Ok(crate::any_pointer::Reader::new(self.reader.get_pointer_element(index)).into()) + } + TypeVariant::Capability => { + Ok(dynamic_value::Reader::Capability(dynamic_value::Capability)) + } + } + } + + pub fn iter(self) -> ListIter, Result>> { + ListIter::new(self, self.len()) + } +} + +impl<'a> IndexMove>> for Reader<'a> { + fn index_move(&self, index: u32) -> Result> { + self.get(index) + } +} + +impl<'a> ::core::iter::IntoIterator for Reader<'a> { + type Item = Result>; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// A mutable dynamically-typed list. +pub struct Builder<'a> { + pub(crate) builder: layout::ListBuilder<'a>, + pub(crate) element_type: Type, +} + +impl<'a> From> for dynamic_value::Builder<'a> { + fn from(x: Builder<'a>) -> dynamic_value::Builder<'a> { + dynamic_value::Builder::List(x) + } +} + +impl<'a> Builder<'a> { + pub(crate) fn new(builder: layout::ListBuilder<'a>, element_type: Type) -> Self { + Self { + builder, + element_type, + } + } + + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + element_type: self.element_type, + } + } + + pub fn into_reader(self) -> Reader<'a> { + Reader { + reader: self.builder.into_reader(), + element_type: self.element_type, + } + } + + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn element_type(&self) -> Type { + self.element_type + } + + pub fn get(self, index: u32) -> Result> { + assert!(index < self.builder.len()); + match self.element_type.which() { + TypeVariant::Void => Ok(dynamic_value::Builder::Void), + TypeVariant::Bool => Ok(dynamic_value::Builder::Bool( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::Int8 => Ok(dynamic_value::Builder::Int8( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::Int16 => Ok(dynamic_value::Builder::Int16( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::Int32 => Ok(dynamic_value::Builder::Int32( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::Int64 => Ok(dynamic_value::Builder::Int64( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::UInt8 => Ok(dynamic_value::Builder::UInt8( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::UInt16 => Ok(dynamic_value::Builder::UInt16( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::UInt32 => Ok(dynamic_value::Builder::UInt32( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::UInt64 => Ok(dynamic_value::Builder::UInt64( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::Float32 => Ok(dynamic_value::Builder::Float32( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::Float64 => Ok(dynamic_value::Builder::Float64( + PrimitiveElement::get_from_builder(&self.builder, index), + )), + TypeVariant::Enum(e) => Ok(dynamic_value::Enum::new( + PrimitiveElement::get_from_builder(&self.builder, index), + e.into(), + ) + .into()), + TypeVariant::Text => Ok(dynamic_value::Builder::Text( + self.builder.get_pointer_element(index).get_text(None)?, + )), + TypeVariant::Data => Ok(dynamic_value::Builder::Data( + self.builder.get_pointer_element(index).get_data(None)?, + )), + TypeVariant::List(element_type) => Ok(Builder { + builder: self + .builder + .get_pointer_element(index) + .get_list(element_type.expected_element_size(), None)?, + element_type, + } + .into()), + TypeVariant::Struct(ss) => { + let r = self.builder.get_struct_element(index); + Ok(dynamic_value::Builder::Struct( + crate::dynamic_struct::Builder::new(r, ss.into()), + )) + } + TypeVariant::AnyPointer => Ok(crate::any_pointer::Builder::new( + self.builder.get_pointer_element(index), + ) + .into()), + TypeVariant::Capability => Ok(dynamic_value::Builder::Capability( + dynamic_value::Capability, + )), + } + } + + pub fn set(&mut self, index: u32, value: dynamic_value::Reader<'_>) -> Result<()> { + assert!(index < self.builder.len()); + match (self.element_type.which(), value) { + (TypeVariant::Void, _) => Ok(()), + (TypeVariant::Bool, dynamic_value::Reader::Bool(b)) => { + PrimitiveElement::set(&self.builder, index, b); + Ok(()) + } + (TypeVariant::Int8, dynamic_value::Reader::Int8(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::Int16, dynamic_value::Reader::Int16(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::Int32, dynamic_value::Reader::Int32(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::Int64, dynamic_value::Reader::Int64(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::UInt8, dynamic_value::Reader::UInt8(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::UInt16, dynamic_value::Reader::UInt16(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::UInt32, dynamic_value::Reader::UInt32(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::UInt64, dynamic_value::Reader::UInt64(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::Float32, dynamic_value::Reader::Float32(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::Float64, dynamic_value::Reader::Float64(x)) => { + PrimitiveElement::set(&self.builder, index, x); + Ok(()) + } + (TypeVariant::Enum(_es), dynamic_value::Reader::Enum(e)) => { + PrimitiveElement::set(&self.builder, index, e.get_value()); + Ok(()) + } + (TypeVariant::Text, dynamic_value::Reader::Text(t)) => { + self.builder + .reborrow() + .get_pointer_element(index) + .set_text(t); + Ok(()) + } + (TypeVariant::Data, dynamic_value::Reader::Data(d)) => { + self.builder + .reborrow() + .get_pointer_element(index) + .set_data(d); + Ok(()) + } + (TypeVariant::Struct(ss), dynamic_value::Reader::Struct(s)) => { + assert_eq!(ss, s.get_schema().raw); + self.builder + .reborrow() + .get_struct_element(index) + .copy_content_from(&s.reader) + } + (TypeVariant::List(_element_type), dynamic_value::Reader::List(list)) => self + .builder + .reborrow() + .get_pointer_element(index) + .set_list(&list.reader, false), + (TypeVariant::AnyPointer, _) => { + Err(Error::from_kind(ErrorKind::ListAnyPointerNotSupported)) + } + (TypeVariant::Capability, dynamic_value::Reader::Capability(_)) => { + Err(Error::from_kind(ErrorKind::ListCapabilityNotSupported)) + } + (_, _) => Err(Error::from_kind(ErrorKind::TypeMismatch)), + } + } + + pub fn init(self, index: u32, size: u32) -> Result> { + assert!(index < self.builder.len()); + match self.element_type.which() { + TypeVariant::Void + | TypeVariant::Bool + | TypeVariant::Int8 + | TypeVariant::Int16 + | TypeVariant::Int32 + | TypeVariant::Int64 + | TypeVariant::UInt8 + | TypeVariant::UInt16 + | TypeVariant::UInt32 + | TypeVariant::UInt64 + | TypeVariant::Float32 + | TypeVariant::Float64 + | TypeVariant::Enum(_) + | TypeVariant::Struct(_) + | TypeVariant::Capability => Err(Error::from_kind(ErrorKind::ExpectedAListOrBlob)), + TypeVariant::Text => Ok(self + .builder + .get_pointer_element(index) + .init_text(size) + .into()), + TypeVariant::Data => Ok(self + .builder + .get_pointer_element(index) + .init_data(size) + .into()), + TypeVariant::List(inner_element_type) => match inner_element_type.which() { + TypeVariant::Struct(rbs) => Ok(Builder::new( + self.builder.get_pointer_element(index).init_struct_list( + size, + crate::dynamic_struct::struct_size_from_schema(rbs.into())?, + ), + inner_element_type, + ) + .into()), + _ => Ok(Builder::new( + self.builder + .get_pointer_element(index) + .init_list(inner_element_type.expected_element_size(), size), + inner_element_type, + ) + .into()), + }, + TypeVariant::AnyPointer => Err(Error::from_kind(ErrorKind::ListAnyPointerNotSupported)), + } + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize) + } +} diff --git a/rust/capnp/dynamic_struct.rs b/rust/capnp/dynamic_struct.rs new file mode 100644 index 000000000000..d0244fc29f40 --- /dev/null +++ b/rust/capnp/dynamic_struct.rs @@ -0,0 +1,782 @@ +//! Dynamically-typed structs. + +use crate::introspect::TypeVariant; +use crate::private::layout; +use crate::schema::{Field, StructSchema}; +use crate::schema_capnp::{field, node, value}; +use crate::{dynamic_list, dynamic_value}; +use crate::{Error, ErrorKind, Result}; + +fn has_discriminant_value(reader: field::Reader) -> bool { + reader.get_discriminant_value() != field::NO_DISCRIMINANT +} + +pub(crate) fn struct_size_from_schema(schema: StructSchema) -> Result { + if let node::Struct(s) = schema.proto.which()? { + Ok(layout::StructSize { + data: s.get_data_word_count(), + pointers: s.get_pointer_count(), + }) + } else { + Err(Error::from_kind(ErrorKind::NotAStruct)) + } +} + +/// A read-only dynamically-typed struct. +#[derive(Clone, Copy)] +pub struct Reader<'a> { + pub(crate) reader: layout::StructReader<'a>, + schema: StructSchema, +} + +impl<'a> From> for dynamic_value::Reader<'a> { + fn from(x: Reader<'a>) -> dynamic_value::Reader<'a> { + dynamic_value::Reader::Struct(x) + } +} + +impl<'a> Reader<'a> { + pub fn new(reader: layout::StructReader<'a>, schema: StructSchema) -> Self { + Self { reader, schema } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + + pub fn get_schema(&self) -> StructSchema { + self.schema + } + + pub fn get(self, field: Field) -> Result> { + assert_eq!(self.schema.raw, field.parent.raw); + let ty = field.get_type(); + match field.get_proto().which()? { + field::Slot(slot) => { + let offset = slot.get_offset(); + let default_value = slot.get_default_value()?; + + match (ty.which(), default_value.which()?) { + (TypeVariant::Void, _) => Ok(dynamic_value::Reader::Void), + (TypeVariant::Bool, value::Bool(b)) => Ok(dynamic_value::Reader::Bool( + self.reader.get_bool_field_mask(offset as usize, b), + )), + (TypeVariant::Int8, value::Int8(x)) => Ok(dynamic_value::Reader::Int8( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Int16, value::Int16(x)) => Ok(dynamic_value::Reader::Int16( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Int32, value::Int32(x)) => Ok(dynamic_value::Reader::Int32( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Int64, value::Int64(x)) => Ok(dynamic_value::Reader::Int64( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt8, value::Uint8(x)) => Ok(dynamic_value::Reader::UInt8( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt16, value::Uint16(x)) => Ok(dynamic_value::Reader::UInt16( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt32, value::Uint32(x)) => Ok(dynamic_value::Reader::UInt32( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt64, value::Uint64(x)) => Ok(dynamic_value::Reader::UInt64( + self.reader.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Float32, value::Float32(x)) => { + Ok(dynamic_value::Reader::Float32( + self.reader + .get_data_field_mask::(offset as usize, x.to_bits()), + )) + } + (TypeVariant::Float64, value::Float64(x)) => { + Ok(dynamic_value::Reader::Float64( + self.reader + .get_data_field_mask::(offset as usize, x.to_bits()), + )) + } + (TypeVariant::Enum(schema), value::Enum(d)) => Ok(dynamic_value::Enum::new( + self.reader.get_data_field_mask::(offset as usize, d), + schema.into(), + ) + .into()), + (TypeVariant::Text, dval) => { + let p = self.reader.get_pointer_field(offset as usize); + // If the type is a generic, then the default value + // is always an empty AnyPointer. Ignore that case. + let t1 = if let (true, value::Text(t)) = (p.is_null(), dval) { + t? + } else { + p.get_text(None)? + }; + Ok(dynamic_value::Reader::Text(t1)) + } + (TypeVariant::Data, dval) => { + let p = self.reader.get_pointer_field(offset as usize); + // If the type is a generic, then the default value + // is always an empty AnyPointer. Ignore that case. + let d1 = if let (true, value::Data(d)) = (p.is_null(), dval) { + d? + } else { + p.get_data(None)? + }; + Ok(dynamic_value::Reader::Data(d1)) + } + (TypeVariant::Struct(schema), dval) => { + let p = self.reader.get_pointer_field(offset as usize); + // If the type is a generic, then the default value + // is always an empty AnyPointer. Ignore that case. + let p1 = if let (true, value::Struct(s)) = (p.is_null(), dval) { + s.reader + } else { + p + }; + let r = p1.get_struct(None)?; + Ok(Reader::new(r, schema.into()).into()) + } + (TypeVariant::List(element_type), dval) => { + let p = self.reader.get_pointer_field(offset as usize); + // If the type is a generic, then the default value + // is always an empty AnyPointer. Ignore that case. + let p1 = if let (true, value::List(l)) = (p.is_null(), dval) { + l.reader + } else { + p + }; + let l = p1.get_list(element_type.expected_element_size(), None)?; + Ok(dynamic_list::Reader::new(l, element_type).into()) + } + (TypeVariant::AnyPointer, value::AnyPointer(a)) => { + let p = self.reader.get_pointer_field(offset as usize); + let a1 = if p.is_null() { + a + } else { + crate::any_pointer::Reader::new(p) + }; + Ok(dynamic_value::Reader::AnyPointer(a1)) + } + (TypeVariant::Capability, value::Interface(())) => { + Ok(dynamic_value::Reader::Capability(dynamic_value::Capability)) + } + _ => Err(Error::from_kind(ErrorKind::FieldAndDefaultMismatch)), + } + } + field::Group(_) => { + if let TypeVariant::Struct(schema) = ty.which() { + Ok(Reader::new(self.reader, schema.into()).into()) + } else { + Err(Error::from_kind(ErrorKind::GroupFieldButTypeIsNotStruct)) + } + } + } + } + + /// Gets the field with the given name. + pub fn get_named(self, field_name: &str) -> Result> { + self.get(self.schema.get_field_by_name(field_name)?) + } + + /// If this struct has union fields, returns the one that is currently active. + /// Otherwise, returns None. + pub fn which(&self) -> Result> { + let node::Struct(st) = self.schema.get_proto().which()? else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + if st.get_discriminant_count() == 0 { + Ok(None) + } else { + let discrim = self + .reader + .get_data_field::(st.get_discriminant_offset() as usize); + self.schema.get_field_by_discriminant(discrim) + } + } + + /// Returns `false` if the field is a pointer and the pointer is null. + pub fn has(&self, field: Field) -> Result { + assert_eq!(self.schema.raw, field.parent.raw); + let proto = field.get_proto(); + if has_discriminant_value(proto) { + let node::Struct(st) = self.schema.get_proto().which()? else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + + let discrim = self + .reader + .get_data_field::(st.get_discriminant_offset() as usize); + if discrim != proto.get_discriminant_value() { + // Field is not active in the union. + return Ok(false); + } + } + let slot = match proto.which()? { + field::Group(_) => return Ok(true), + field::Slot(s) => s, + }; + let ty = field.get_type(); + if ty.is_pointer_type() { + Ok(!self + .reader + .get_pointer_field(slot.get_offset() as usize) + .is_null()) + } else { + Ok(true) + } + } + + pub fn has_named(&self, field_name: &str) -> Result { + let field = self.schema.get_field_by_name(field_name)?; + self.has(field) + } +} + +/// A mutable dynamically-typed struct. +pub struct Builder<'a> { + builder: layout::StructBuilder<'a>, + schema: StructSchema, +} + +impl<'a> From> for dynamic_value::Builder<'a> { + fn from(x: Builder<'a>) -> dynamic_value::Builder<'a> { + dynamic_value::Builder::Struct(x) + } +} + +impl<'a> Builder<'a> { + pub fn new(builder: layout::StructBuilder<'a>, schema: StructSchema) -> Self { + Self { builder, schema } + } + + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + schema: self.schema, + } + } + + pub fn reborrow_as_reader(&self) -> Reader<'_> { + Reader { + reader: self.builder.as_reader(), + schema: self.schema, + } + } + + pub fn into_reader(self) -> Reader<'a> { + Reader { + schema: self.schema, + reader: self.builder.into_reader(), + } + } + + pub fn get_schema(&self) -> StructSchema { + self.schema + } + + pub fn get(self, field: Field) -> Result> { + assert_eq!(self.schema.raw, field.parent.raw); + let ty = field.get_type(); + match field.get_proto().which()? { + field::Slot(slot) => { + let offset = slot.get_offset(); + let default_value = slot.get_default_value()?; + + match (ty.which(), default_value.which()?) { + (TypeVariant::Void, _) => Ok(dynamic_value::Builder::Void), + (TypeVariant::Bool, value::Bool(b)) => Ok(dynamic_value::Builder::Bool( + self.builder.get_bool_field_mask(offset as usize, b), + )), + (TypeVariant::Int8, value::Int8(x)) => Ok(dynamic_value::Builder::Int8( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Int16, value::Int16(x)) => Ok(dynamic_value::Builder::Int16( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Int32, value::Int32(x)) => Ok(dynamic_value::Builder::Int32( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Int64, value::Int64(x)) => Ok(dynamic_value::Builder::Int64( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt8, value::Uint8(x)) => Ok(dynamic_value::Builder::UInt8( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt16, value::Uint16(x)) => Ok(dynamic_value::Builder::UInt16( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt32, value::Uint32(x)) => Ok(dynamic_value::Builder::UInt32( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::UInt64, value::Uint64(x)) => Ok(dynamic_value::Builder::UInt64( + self.builder.get_data_field_mask::(offset as usize, x), + )), + (TypeVariant::Float32, value::Float32(x)) => { + Ok(dynamic_value::Builder::Float32( + self.builder + .get_data_field_mask::(offset as usize, x.to_bits()), + )) + } + (TypeVariant::Float64, value::Float64(x)) => { + Ok(dynamic_value::Builder::Float64( + self.builder + .get_data_field_mask::(offset as usize, x.to_bits()), + )) + } + (TypeVariant::Enum(schema), value::Enum(d)) => Ok(dynamic_value::Enum::new( + self.builder.get_data_field_mask::(offset as usize, d), + schema.into(), + ) + .into()), + (TypeVariant::Text, dval) => { + let mut p = self.builder.get_pointer_field(offset as usize); + if p.is_null() { + // If the type is a generic, then the default value + // is always an empty AnyPointer. Ignore that case. + if let value::Text(t) = dval { + p.set_text(t?); + } + } + Ok(dynamic_value::Builder::Text(p.get_text(None)?)) + } + (TypeVariant::Data, dval) => { + let mut p = self.builder.get_pointer_field(offset as usize); + if p.is_null() { + // If the type is a generic, then the default value + // is always an empty AnyPointer. Ignore that case. + if let value::Data(d) = dval { + p.set_data(d?); + } + } + Ok(dynamic_value::Builder::Data(p.get_data(None)?)) + } + (TypeVariant::Struct(schema), dval) => { + let mut p = self.builder.get_pointer_field(offset as usize); + if p.is_null() { + // If the type is a generic, then the default value + // is always an empty AnyPointer. Ignore that case. + if let value::Struct(s) = dval { + p.copy_from(s.reader, false)?; + } + } + Ok(Builder::new( + p.get_struct(struct_size_from_schema(schema.into())?, None)?, + schema.into(), + ) + .into()) + } + (TypeVariant::List(element_type), dval) => { + let mut p = self.builder.get_pointer_field(offset as usize); + if p.is_null() { + if let value::List(l) = dval { + p.copy_from(l.reader, false)?; + } + } + let l = if let TypeVariant::Struct(ss) = element_type.which() { + p.get_struct_list(struct_size_from_schema(ss.into())?, None)? + } else { + p.get_list(element_type.expected_element_size(), None)? + }; + + Ok(dynamic_list::Builder::new(l, element_type).into()) + } + (TypeVariant::AnyPointer, value::AnyPointer(_a)) => { + // AnyPointer fields can't have a nontrivial default. + Ok(crate::any_pointer::Builder::new( + self.builder.get_pointer_field(offset as usize), + ) + .into()) + } + (TypeVariant::Capability, value::Interface(())) => Ok( + dynamic_value::Builder::Capability(dynamic_value::Capability), + ), + _ => Err(Error::from_kind(ErrorKind::FieldAndDefaultMismatch)), + } + } + field::Group(_) => { + if let TypeVariant::Struct(schema) = ty.which() { + Ok(Builder::new(self.builder, schema.into()).into()) + } else { + Err(Error::from_kind(ErrorKind::GroupFieldButTypeIsNotStruct)) + } + } + } + } + + pub fn get_named(self, field_name: &str) -> Result> { + let field = self.schema.get_field_by_name(field_name)?; + self.get(field) + } + + pub fn which(&self) -> Result> { + let node::Struct(st) = self.schema.get_proto().which()? else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + if st.get_discriminant_count() == 0 { + Ok(None) + } else { + let discrim = self + .builder + .get_data_field::(st.get_discriminant_offset() as usize); + self.schema.get_field_by_discriminant(discrim) + } + } + + pub fn has(&self, field: Field) -> Result { + self.reborrow_as_reader().has(field) + } + + pub fn has_named(&self, field_name: &str) -> Result { + let field = self.schema.get_field_by_name(field_name)?; + self.has(field) + } + + pub fn set(&mut self, field: Field, value: dynamic_value::Reader<'_>) -> Result<()> { + assert_eq!(self.schema.raw, field.parent.raw); + self.set_in_union(field)?; + let ty = field.get_type(); + match field.get_proto().which()? { + field::Slot(slot) => { + let dval = slot.get_default_value()?; + let offset = slot.get_offset() as usize; + match (ty.which(), value, dval.which()?) { + (TypeVariant::Void, _, _) => Ok(()), + (TypeVariant::Bool, dynamic_value::Reader::Bool(v), value::Bool(b)) => { + self.builder.set_bool_field_mask(offset, v, b); + Ok(()) + } + (TypeVariant::Int8, dynamic_value::Reader::Int8(v), value::Int8(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + (TypeVariant::Int16, dynamic_value::Reader::Int16(v), value::Int16(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + (TypeVariant::Int32, dynamic_value::Reader::Int32(v), value::Int32(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + (TypeVariant::Int64, dynamic_value::Reader::Int64(v), value::Int64(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + (TypeVariant::UInt8, dynamic_value::Reader::UInt8(v), value::Uint8(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + (TypeVariant::UInt16, dynamic_value::Reader::UInt16(v), value::Uint16(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + (TypeVariant::UInt32, dynamic_value::Reader::UInt32(v), value::Uint32(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + (TypeVariant::UInt64, dynamic_value::Reader::UInt64(v), value::Uint64(d)) => { + self.builder.set_data_field_mask::(offset, v, d); + Ok(()) + } + ( + TypeVariant::Float32, + dynamic_value::Reader::Float32(v), + value::Float32(d), + ) => { + self.builder + .set_data_field_mask::(offset, v, d.to_bits()); + Ok(()) + } + ( + TypeVariant::Float64, + dynamic_value::Reader::Float64(v), + value::Float64(d), + ) => { + self.builder + .set_data_field_mask::(offset, v, d.to_bits()); + Ok(()) + } + (TypeVariant::Enum(_), dynamic_value::Reader::Enum(ev), value::Enum(d)) => { + self.builder + .set_data_field_mask::(offset, ev.get_value(), d); + Ok(()) + } + (TypeVariant::Text, dynamic_value::Reader::Text(tv), _) => { + let mut p = self.builder.reborrow().get_pointer_field(offset); + p.set_text(tv); + Ok(()) + } + (TypeVariant::Data, dynamic_value::Reader::Data(v), _) => { + let mut p = self.builder.reborrow().get_pointer_field(offset); + p.set_data(v); + Ok(()) + } + (TypeVariant::List(_), dynamic_value::Reader::List(l), _) => { + let mut p = self.builder.reborrow().get_pointer_field(offset); + p.set_list(&l.reader, false) + } + (TypeVariant::Struct(_), dynamic_value::Reader::Struct(v), _) => { + let mut p = self.builder.reborrow().get_pointer_field(offset); + p.set_struct(&v.reader, false) + } + (TypeVariant::AnyPointer, _, _) => { + let mut target = crate::any_pointer::Builder::new( + self.builder.reborrow().get_pointer_field(offset), + ); + match value { + dynamic_value::Reader::Text(t) => target.set_as(t), + dynamic_value::Reader::Data(t) => target.set_as(t), + dynamic_value::Reader::Struct(s) => target.set_as(s), + dynamic_value::Reader::List(l) => target.set_as(l), + dynamic_value::Reader::Capability(_) => Err(Error::from_kind( + ErrorKind::SettingDynamicCapabilitiesIsUnsupported, + )), + _ => Err(Error::from_kind( + ErrorKind::CannotSetAnyPointerFieldToAPrimitiveValue, + )), + } + } + (TypeVariant::Capability, _, _) => Err(Error::from_kind( + ErrorKind::SettingDynamicCapabilitiesIsUnsupported, + )), + _ => Err(Error::from_kind(ErrorKind::TypeMismatch)), + } + } + field::Group(_group) => { + let dynamic_value::Reader::Struct(src) = value else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + let dynamic_value::Builder::Struct(mut dst) = self.reborrow().init(field)? else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + if let Some(union_field) = src.which()? { + dst.set(union_field, src.get(union_field)?)?; + } + + let non_union_fields = src.schema.get_non_union_fields()?; + for idx in 0..non_union_fields.len() { + let field = non_union_fields.get(idx); + if src.has(field)? { + dst.set(field, src.get(field)?)?; + } + } + Ok(()) + } + } + } + + pub fn set_named(&mut self, field_name: &str, value: dynamic_value::Reader<'_>) -> Result<()> { + let field = self.schema.get_field_by_name(field_name)?; + self.set(field, value) + } + + pub fn init(mut self, field: Field) -> Result> { + assert_eq!(self.schema.raw, field.parent.raw); + self.set_in_union(field)?; + let ty = field.get_type(); + match field.get_proto().which()? { + field::Slot(slot) => { + let offset = slot.get_offset() as usize; + match ty.which() { + TypeVariant::Struct(ss) => Ok(Builder { + schema: ss.into(), + builder: self + .builder + .get_pointer_field(offset) + .init_struct(struct_size_from_schema(ss.into())?), + } + .into()), + TypeVariant::AnyPointer => { + let mut p = self.builder.get_pointer_field(offset); + p.clear(); + Ok(crate::any_pointer::Builder::new(p).into()) + } + _ => Err(Error::from_kind( + ErrorKind::InitIsOnlyValidForStructAndAnyPointerFields, + )), + } + } + field::Group(_) => { + self.clear(field)?; + let TypeVariant::Struct(schema) = ty.which() else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + Ok((Builder::new(self.builder, schema.into())).into()) + } + } + } + + pub fn init_named(self, field_name: &str) -> Result> { + let field = self.schema.get_field_by_name(field_name)?; + self.init(field) + } + + pub fn initn(mut self, field: Field, size: u32) -> Result> { + assert_eq!(self.schema.raw, field.parent.raw); + self.set_in_union(field)?; + let ty = field.get_type(); + match field.get_proto().which()? { + field::Slot(slot) => { + let offset = slot.get_offset() as usize; + match ty.which() { + TypeVariant::List(element_type) => match element_type.which() { + TypeVariant::Struct(ss) => Ok(dynamic_list::Builder::new( + self.builder + .get_pointer_field(offset) + .init_struct_list(size, struct_size_from_schema(ss.into())?), + element_type, + ) + .into()), + _ => Ok(dynamic_list::Builder::new( + self.builder + .get_pointer_field(offset) + .init_list(element_type.expected_element_size(), size), + element_type, + ) + .into()), + }, + TypeVariant::Text => Ok(self + .builder + .get_pointer_field(offset) + .init_text(size) + .into()), + TypeVariant::Data => Ok(self + .builder + .get_pointer_field(offset) + .init_data(size) + .into()), + + _ => Err(Error::from_kind( + ErrorKind::InitnIsOnlyValidForListTextOrDataFields, + )), + } + } + field::Group(_) => Err(Error::from_kind( + ErrorKind::InitnIsOnlyValidForListTextOrDataFields, + )), + } + } + + pub fn initn_named(self, field_name: &str, size: u32) -> Result> { + let field = self.schema.get_field_by_name(field_name)?; + self.initn(field, size) + } + + /// Clears a field, setting it to its default value. For pointer fields, + /// this makes the field null. + pub fn clear(&mut self, field: Field) -> Result<()> { + assert_eq!(self.schema.raw, field.parent.raw); + self.set_in_union(field)?; + let ty = field.get_type(); + match field.get_proto().which()? { + field::Slot(slot) => { + let offset = slot.get_offset() as usize; + match ty.which() { + TypeVariant::Void => Ok(()), + TypeVariant::Bool => { + self.builder.set_bool_field(offset, false); + Ok(()) + } + TypeVariant::Int8 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::Int16 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::Int32 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::Int64 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::UInt8 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::UInt16 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::UInt32 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::UInt64 => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::Float32 => { + self.builder.set_data_field::(offset, 0f32); + Ok(()) + } + TypeVariant::Float64 => { + self.builder.set_data_field::(offset, 0f64); + Ok(()) + } + TypeVariant::Enum(_) => { + self.builder.set_data_field::(offset, 0); + Ok(()) + } + TypeVariant::Text + | TypeVariant::Data + | TypeVariant::Struct(_) + | TypeVariant::List(_) + | TypeVariant::AnyPointer + | TypeVariant::Capability => { + self.builder.reborrow().get_pointer_field(offset).clear(); + Ok(()) + } + } + } + field::Group(_) => { + let TypeVariant::Struct(schema) = ty.which() else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + let mut group = Builder::new(self.builder.reborrow(), schema.into()); + + // We clear the union field with discriminant 0 rather than the one that + // is set because we want the union to end up with its default field active. + if let Some(union_field) = group.schema.get_field_by_discriminant(0)? { + group.clear(union_field)?; + } + + let non_union_fields = group.schema.get_non_union_fields()?; + for idx in 0..non_union_fields.len() { + group.clear(non_union_fields.get(idx))?; + } + Ok(()) + } + } + } + + pub fn clear_named(&mut self, field_name: &str) -> Result<()> { + let field = self.schema.get_field_by_name(field_name)?; + self.clear(field) + } + + fn set_in_union(&mut self, field: Field) -> Result<()> { + if has_discriminant_value(field.get_proto()) { + let node::Struct(st) = self.schema.get_proto().which()? else { + return Err(Error::from_kind(ErrorKind::NotAStruct)); + }; + self.builder.set_data_field::( + st.get_discriminant_offset() as usize, + field.get_proto().get_discriminant_value(), + ); + } + Ok(()) + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } +} diff --git a/rust/capnp/dynamic_value.rs b/rust/capnp/dynamic_value.rs new file mode 100644 index 000000000000..83646e26de31 --- /dev/null +++ b/rust/capnp/dynamic_value.rs @@ -0,0 +1,317 @@ +//! Dynamically typed values. + +use crate::introspect::{self, TypeVariant}; +use crate::schema_capnp::value; +use crate::Result; +use crate::{dynamic_list, dynamic_struct}; + +/// A dynamically-typed read-only value. +#[derive(Clone, Copy)] +pub enum Reader<'a> { + Void, + Bool(bool), + Int8(i8), + Int16(i16), + Int32(i32), + Int64(i64), + UInt8(u8), + UInt16(u16), + UInt32(u32), + UInt64(u64), + Float32(f32), + Float64(f64), + Enum(Enum), + Text(crate::text::Reader<'a>), + Data(crate::data::Reader<'a>), + Struct(dynamic_struct::Reader<'a>), + List(dynamic_list::Reader<'a>), + AnyPointer(crate::any_pointer::Reader<'a>), + Capability(Capability), +} + +impl<'a> Reader<'a> { + pub fn new(value: value::Reader<'a>, ty: introspect::Type) -> Result { + match (value.which()?, ty.which()) { + (value::Void(()), _) => Ok(Reader::Void), + (value::Bool(b), _) => Ok(Reader::Bool(b)), + (value::Int8(x), _) => Ok(Reader::Int8(x)), + (value::Int16(x), _) => Ok(Reader::Int16(x)), + (value::Int32(x), _) => Ok(Reader::Int32(x)), + (value::Int64(x), _) => Ok(Reader::Int64(x)), + (value::Uint8(x), _) => Ok(Reader::UInt8(x)), + (value::Uint16(x), _) => Ok(Reader::UInt16(x)), + (value::Uint32(x), _) => Ok(Reader::UInt32(x)), + (value::Uint64(x), _) => Ok(Reader::UInt64(x)), + (value::Float32(x), _) => Ok(Reader::Float32(x)), + (value::Float64(x), _) => Ok(Reader::Float64(x)), + (value::Enum(d), TypeVariant::Enum(e)) => Ok(Reader::Enum(Enum::new(d, e.into()))), + (value::Text(t), _) => Ok(Reader::Text(t?)), + (value::Data(d), _) => Ok(Reader::Data(d?)), + (value::Struct(d), TypeVariant::Struct(schema)) => Ok(Reader::Struct( + dynamic_struct::Reader::new(d.reader.get_struct(None)?, schema.into()), + )), + (value::List(l), TypeVariant::List(element_type)) => { + Ok(Reader::List(dynamic_list::Reader::new( + l.reader + .get_list(element_type.expected_element_size(), None)?, + element_type, + ))) + } + (value::Interface(()), TypeVariant::Capability) => Ok(Capability.into()), + (value::AnyPointer(a), TypeVariant::AnyPointer) => Ok(a.into()), + _ => Err(crate::Error::from_kind(crate::ErrorKind::TypeMismatch)), + } + } + + /// Downcasts the `Reader` into a more specific type. Panics if the + /// expected type does not match the value. + pub fn downcast>(self) -> T { + T::downcast_reader(self) + } +} + +impl<'a> From<()> for Reader<'a> { + fn from((): ()) -> Reader<'a> { + Reader::Void + } +} + +macro_rules! primitive_dynamic_value( + ($t:ty, $v:ident) => ( + impl <'a> From<$t> for Reader<'a> { + fn from(x: $t) -> Reader<'a> { Reader::$v(x) } + } + ) +); + +primitive_dynamic_value!(bool, Bool); +primitive_dynamic_value!(i8, Int8); +primitive_dynamic_value!(i16, Int16); +primitive_dynamic_value!(i32, Int32); +primitive_dynamic_value!(i64, Int64); +primitive_dynamic_value!(u8, UInt8); +primitive_dynamic_value!(u16, UInt16); +primitive_dynamic_value!(u32, UInt32); +primitive_dynamic_value!(u64, UInt64); +primitive_dynamic_value!(f32, Float32); +primitive_dynamic_value!(f64, Float64); + +/// Helper trait for the `dynamic_value::Reader::downcast()` method. +pub trait DowncastReader<'a> { + fn downcast_reader(v: Reader<'a>) -> Self; +} + +impl<'a> DowncastReader<'a> for () { + fn downcast_reader(value: Reader<'a>) { + let Reader::Void = value else { + panic!("error downcasting to void") + }; + } +} + +macro_rules! downcast_reader_impl( + ($t:ty, $v:ident, $s:expr) => ( + impl <'a> DowncastReader<'a> for $t { + fn downcast_reader(value: Reader<'a>) -> Self { + let Reader::$v(x) = value else { panic!("error downcasting to {}", $s) }; + x + } + } + ) +); + +downcast_reader_impl!(bool, Bool, "bool"); +downcast_reader_impl!(i8, Int8, "i8"); +downcast_reader_impl!(i16, Int16, "i16"); +downcast_reader_impl!(i32, Int32, "i32"); +downcast_reader_impl!(i64, Int64, "i64"); +downcast_reader_impl!(u8, UInt8, "u8"); +downcast_reader_impl!(u16, UInt16, "u16"); +downcast_reader_impl!(u32, UInt32, "u32"); +downcast_reader_impl!(u64, UInt64, "u64"); +downcast_reader_impl!(f32, Float32, "f32"); +downcast_reader_impl!(f64, Float64, "f64"); +downcast_reader_impl!(Enum, Enum, "enum"); +downcast_reader_impl!(crate::text::Reader<'a>, Text, "text"); +downcast_reader_impl!(crate::data::Reader<'a>, Data, "data"); +downcast_reader_impl!(dynamic_list::Reader<'a>, List, "list"); +downcast_reader_impl!(dynamic_struct::Reader<'a>, Struct, "struct"); +downcast_reader_impl!(crate::any_pointer::Reader<'a>, AnyPointer, "anypointer"); + +/// A dynamically-typed value with mutable interior. +pub enum Builder<'a> { + Void, + Bool(bool), + Int8(i8), + Int16(i16), + Int32(i32), + Int64(i64), + UInt8(u8), + UInt16(u16), + UInt32(u32), + UInt64(u64), + Float32(f32), + Float64(f64), + Enum(Enum), + Text(crate::text::Builder<'a>), + Data(crate::data::Builder<'a>), + Struct(dynamic_struct::Builder<'a>), + List(dynamic_list::Builder<'a>), + AnyPointer(crate::any_pointer::Builder<'a>), + Capability(Capability), +} + +impl<'a> Builder<'a> { + pub fn reborrow(&mut self) -> Builder<'_> { + match self { + Builder::Void => Builder::Void, + Builder::Bool(b) => Builder::Bool(*b), + Builder::Int8(x) => Builder::Int8(*x), + Builder::Int16(x) => Builder::Int16(*x), + Builder::Int32(x) => Builder::Int32(*x), + Builder::Int64(x) => Builder::Int64(*x), + Builder::UInt8(x) => Builder::UInt8(*x), + Builder::UInt16(x) => Builder::UInt16(*x), + Builder::UInt32(x) => Builder::UInt32(*x), + Builder::UInt64(x) => Builder::UInt64(*x), + Builder::Float32(x) => Builder::Float32(*x), + Builder::Float64(x) => Builder::Float64(*x), + Builder::Enum(e) => Builder::Enum(*e), + Builder::Text(t) => Builder::Text(t.reborrow()), + Builder::Data(d) => Builder::Data(d), + Builder::Struct(ref mut s) => Builder::Struct(s.reborrow()), + Builder::List(ref mut l) => Builder::List(l.reborrow()), + Builder::AnyPointer(ref mut a) => Builder::AnyPointer(a.reborrow()), + Builder::Capability(c) => Builder::Capability(*c), + } + } + + pub fn into_reader(self) -> Reader<'a> { + match self { + Builder::Void => Reader::Void, + Builder::Bool(b) => Reader::Bool(b), + Builder::Int8(x) => Reader::Int8(x), + Builder::Int16(x) => Reader::Int16(x), + Builder::Int32(x) => Reader::Int32(x), + Builder::Int64(x) => Reader::Int64(x), + Builder::UInt8(x) => Reader::UInt8(x), + Builder::UInt16(x) => Reader::UInt16(x), + Builder::UInt32(x) => Reader::UInt32(x), + Builder::UInt64(x) => Reader::UInt64(x), + Builder::Float32(x) => Reader::Float32(x), + Builder::Float64(x) => Reader::Float64(x), + Builder::Enum(e) => Reader::Enum(e), + Builder::Text(t) => Reader::Text(t.into_reader()), + Builder::Data(d) => Reader::Data(d), + Builder::Struct(s) => Reader::Struct(s.into_reader()), + Builder::List(l) => Reader::List(l.into_reader()), + Builder::AnyPointer(a) => Reader::AnyPointer(a.into_reader()), + Builder::Capability(c) => Reader::Capability(c), + } + } + + /// Downcasts the `Reader` into a more specific type. Panics if the + /// expected type does not match the value. + pub fn downcast>(self) -> T { + T::downcast_builder(self) + } +} + +/// Helper trait for the `dynamic_value::Builder::downcast()` method. +pub trait DowncastBuilder<'a> { + fn downcast_builder(v: Builder<'a>) -> Self; +} + +impl<'a> DowncastBuilder<'a> for () { + fn downcast_builder(value: Builder<'a>) { + let Builder::Void = value else { + panic!("error downcasting to void") + }; + } +} + +macro_rules! downcast_builder_impl( + ($t:ty, $v:ident, $s:expr) => ( + impl <'a> DowncastBuilder<'a> for $t { + fn downcast_builder(value: Builder<'a>) -> Self { + let Builder::$v(x) = value else { panic!("error downcasting to {}", $s) }; + x + } + } + ) +); + +downcast_builder_impl!(bool, Bool, "bool"); +downcast_builder_impl!(i8, Int8, "i8"); +downcast_builder_impl!(i16, Int16, "i16"); +downcast_builder_impl!(i32, Int32, "i32"); +downcast_builder_impl!(i64, Int64, "i64"); +downcast_builder_impl!(u8, UInt8, "u8"); +downcast_builder_impl!(u16, UInt16, "u16"); +downcast_builder_impl!(u32, UInt32, "u32"); +downcast_builder_impl!(u64, UInt64, "u64"); +downcast_builder_impl!(f32, Float32, "f32"); +downcast_builder_impl!(f64, Float64, "f64"); +downcast_builder_impl!(Enum, Enum, "enum"); +downcast_builder_impl!(crate::text::Builder<'a>, Text, "text"); +downcast_builder_impl!(crate::data::Builder<'a>, Data, "data"); +downcast_builder_impl!(dynamic_list::Builder<'a>, List, "list"); +downcast_builder_impl!(dynamic_struct::Builder<'a>, Struct, "struct"); +downcast_builder_impl!(crate::any_pointer::Builder<'a>, AnyPointer, "anypointer"); + +/// A dynamically-typed enum value. +#[derive(Clone, Copy)] +pub struct Enum { + value: u16, + schema: crate::schema::EnumSchema, +} + +impl Enum { + pub fn new(value: u16, schema: crate::schema::EnumSchema) -> Self { + Self { value, schema } + } + + /// Gets the u16 representation of this value. + pub fn get_value(&self) -> u16 { + self.value + } + + /// Gets the schema of this enumerant. + pub fn get_enumerant(self) -> crate::Result> { + let enumerants = self.schema.get_enumerants()?; + if (self.value) < enumerants.len() { + Ok(Some(enumerants.get(self.value))) + } else { + Ok(None) + } + } +} + +impl<'a> From for Reader<'a> { + fn from(e: Enum) -> Reader<'a> { + Reader::Enum(e) + } +} + +impl<'a> From for Builder<'a> { + fn from(e: Enum) -> Builder<'a> { + Builder::Enum(e) + } +} + +/// A dynamic capability. Currently, this is just a stub and does not support calling +/// of methods. +#[derive(Clone, Copy)] +pub struct Capability; + +impl<'a> From for Reader<'a> { + fn from(c: Capability) -> Reader<'a> { + Reader::Capability(c) + } +} + +impl<'a> From for Builder<'a> { + fn from(c: Capability) -> Builder<'a> { + Builder::Capability(c) + } +} diff --git a/rust/capnp/enum_list.rs b/rust/capnp/enum_list.rs new file mode 100644 index 000000000000..8fa713029250 --- /dev/null +++ b/rust/capnp/enum_list.rs @@ -0,0 +1,237 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of enums. + +use crate::private::layout::{ + ListBuilder, ListReader, PointerBuilder, PointerReader, PrimitiveElement, TwoBytes, +}; +use crate::traits::{FromPointerBuilder, FromPointerReader, IndexMove, ListIter}; +use crate::{NotInSchema, Result}; + +use core::marker::PhantomData; + +#[derive(Clone, Copy)] +pub struct Owned { + marker: PhantomData, +} + +impl crate::introspect::Introspect for Owned +where + T: crate::introspect::Introspect, +{ + fn introspect() -> crate::introspect::Type { + crate::introspect::Type::list_of(T::introspect()) + } +} + +impl crate::traits::Owned for Owned +where + T: TryFrom + crate::introspect::Introspect, +{ + type Reader<'a> = Reader<'a, T>; + type Builder<'a> = Builder<'a, T>; +} + +#[derive(Clone, Copy)] +pub struct Reader<'a, T> { + marker: PhantomData, + reader: ListReader<'a>, +} + +impl<'a, T: TryFrom> Reader<'a, T> { + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, ::core::result::Result> { + let l = self.len(); + ListIter::new(self, l) + } +} + +impl<'a, T: TryFrom> FromPointerReader<'a> for Reader<'a, T> { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(TwoBytes, default)?, + marker: PhantomData, + }) + } +} + +impl<'a, T: TryFrom> + IndexMove> for Reader<'a, T> +{ + fn index_move(&self, index: u32) -> ::core::result::Result { + self.get(index) + } +} + +impl<'a, T: TryFrom> Reader<'a, T> { + /// Gets the `T` at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(&self, index: u32) -> ::core::result::Result { + assert!(index < self.len()); + let result: u16 = PrimitiveElement::get(&self.reader, index); + result.try_into() + } + + /// Gets the `T` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(&self, index: u32) -> Option<::core::result::Result> { + if index < self.len() { + let result: u16 = PrimitiveElement::get(&self.reader, index); + Some(result.try_into()) + } else { + None + } + } +} + +impl<'a, T> crate::traits::IntoInternalListReader<'a> for Reader<'a, T> +where + T: PrimitiveElement, +{ + fn into_internal_list_reader(self) -> ListReader<'a> { + self.reader + } +} + +pub struct Builder<'a, T> { + marker: PhantomData, + builder: ListBuilder<'a>, +} + +impl<'a, T: Into + TryFrom> Builder<'a, T> { + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn into_reader(self) -> Reader<'a, T> { + Reader { + reader: self.builder.into_reader(), + marker: PhantomData, + } + } + + pub fn set(&mut self, index: u32, value: T) { + assert!(index < self.len()); + PrimitiveElement::set(&self.builder, index, value.into()); + } +} + +impl<'a, T: TryFrom> FromPointerBuilder<'a> for Builder<'a, T> { + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a, T> { + Builder { + builder: builder.init_list(TwoBytes, size), + marker: PhantomData, + } + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + builder: builder.get_list(TwoBytes, default)?, + marker: PhantomData, + }) + } +} + +impl<'a, T: Into + TryFrom> Builder<'a, T> { + /// Gets the `T` at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(&self, index: u32) -> ::core::result::Result { + assert!(index < self.len()); + let result: u16 = PrimitiveElement::get_from_builder(&self.builder, index); + result.try_into() + } + + /// Gets the `T` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(&self, index: u32) -> Option<::core::result::Result> { + if index < self.len() { + let result: u16 = PrimitiveElement::get_from_builder(&self.builder, index); + Some(result.try_into()) + } else { + None + } + } + + pub fn reborrow(&mut self) -> Builder<'_, T> { + Builder { + builder: self.builder.reborrow(), + marker: PhantomData, + } + } +} + +impl<'a, T> crate::traits::SetPointerBuilder for Reader<'a, T> { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a, T>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize) + } +} + +impl<'a, T: TryFrom> ::core::iter::IntoIterator for Reader<'a, T> { + type Item = ::core::result::Result; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T: TryFrom + crate::introspect::Introspect> From> + for crate::dynamic_value::Reader<'a> +{ + fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( + t.reader, + T::introspect(), + )) + } +} + +impl<'a, T: TryFrom + crate::introspect::Introspect> From> + for crate::dynamic_value::Builder<'a> +{ + fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( + t.builder, + T::introspect(), + )) + } +} diff --git a/rust/capnp/introspect.rs b/rust/capnp/introspect.rs new file mode 100644 index 000000000000..d994b180c93a --- /dev/null +++ b/rust/capnp/introspect.rs @@ -0,0 +1,282 @@ +//! Traits and types to support run-time type introspection, i.e. reflection. + +use crate::private::layout::ElementSize; + +/// A type that supports reflection. All types that can appear in a Cap'n Proto message +/// implement this trait. +pub trait Introspect { + /// Retrieves a description of the type. + fn introspect() -> Type; +} + +/// A description of a Cap'n Proto type. The representation is +/// optimized to avoid heap allocation. +/// +/// To examine a `Type`, you should call the `which()` method. +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Type { + /// The type, minus any outer `List( )`. + base: BaseType, + + /// How many times `base` is wrapped in `List( )`. + list_count: usize, +} + +impl Type { + /// Constructs a new `Type` that is not a list. + fn new_base(base: BaseType) -> Self { + Self { + base, + list_count: 0, + } + } + + /// Constructs a new `Type` that is a list wrapping some other `Type`. + pub fn list_of(mut element_type: Type) -> Self { + element_type.list_count += 1; + element_type + } + + /// Unfolds a single layer of the `Type`, to allow for pattern matching. + pub fn which(&self) -> TypeVariant { + if self.list_count > 0 { + TypeVariant::List(Type { + base: self.base, + list_count: self.list_count - 1, + }) + } else { + match self.base { + BaseType::Void => TypeVariant::Void, + BaseType::Bool => TypeVariant::Bool, + BaseType::Int8 => TypeVariant::Int8, + BaseType::Int16 => TypeVariant::Int16, + BaseType::Int32 => TypeVariant::Int32, + BaseType::Int64 => TypeVariant::Int64, + BaseType::UInt8 => TypeVariant::UInt8, + BaseType::UInt16 => TypeVariant::UInt16, + BaseType::UInt32 => TypeVariant::UInt32, + BaseType::UInt64 => TypeVariant::UInt64, + BaseType::Float32 => TypeVariant::Float32, + BaseType::Float64 => TypeVariant::Float64, + BaseType::Text => TypeVariant::Text, + BaseType::Data => TypeVariant::Data, + BaseType::Enum(re) => TypeVariant::Enum(re), + BaseType::Struct(rs) => TypeVariant::Struct(rs), + BaseType::AnyPointer => TypeVariant::AnyPointer, + BaseType::Capability => TypeVariant::Capability, + } + } + } + + /// If this type T appears as List(T), then what is the expected + /// element size of the list? + pub(crate) fn expected_element_size(&self) -> ElementSize { + if self.list_count > 0 { + ElementSize::Pointer + } else { + match self.base { + BaseType::Void => ElementSize::Void, + BaseType::Bool => ElementSize::Bit, + BaseType::Int8 | BaseType::UInt8 => ElementSize::Byte, + BaseType::Int16 | BaseType::UInt16 | BaseType::Enum(_) => ElementSize::TwoBytes, + BaseType::Int32 | BaseType::UInt32 | BaseType::Float32 => ElementSize::FourBytes, + BaseType::Int64 | BaseType::UInt64 | BaseType::Float64 => ElementSize::EightBytes, + BaseType::Text | BaseType::Data | BaseType::AnyPointer | BaseType::Capability => { + ElementSize::Pointer + } + BaseType::Struct(_) => ElementSize::InlineComposite, + } + } + } + + /// Is the `Type` a pointer type? + pub fn is_pointer_type(&self) -> bool { + if self.list_count > 0 { + true + } else { + matches!( + self.base, + BaseType::Text + | BaseType::Data + | BaseType::AnyPointer + | BaseType::Struct(_) + | BaseType::Capability + ) + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq)] +/// A `Type` unfolded one level. Suitable for pattern matching. Can be trivially +/// converted to `Type` via the `From`/`Into` traits. +pub enum TypeVariant { + Void, + Bool, + Int8, + Int16, + Int32, + Int64, + UInt8, + UInt16, + UInt32, + UInt64, + Float32, + Float64, + Text, + Data, + Struct(RawBrandedStructSchema), + AnyPointer, + Capability, + Enum(RawEnumSchema), + List(Type), +} + +impl From for Type { + fn from(tv: TypeVariant) -> Type { + match tv { + TypeVariant::Void => Type::new_base(BaseType::Void), + TypeVariant::Bool => Type::new_base(BaseType::Bool), + TypeVariant::Int8 => Type::new_base(BaseType::Int8), + TypeVariant::Int16 => Type::new_base(BaseType::Int16), + TypeVariant::Int32 => Type::new_base(BaseType::Int32), + TypeVariant::Int64 => Type::new_base(BaseType::Int64), + TypeVariant::UInt8 => Type::new_base(BaseType::UInt8), + TypeVariant::UInt16 => Type::new_base(BaseType::UInt16), + TypeVariant::UInt32 => Type::new_base(BaseType::UInt32), + TypeVariant::UInt64 => Type::new_base(BaseType::UInt64), + TypeVariant::Float32 => Type::new_base(BaseType::Float32), + TypeVariant::Float64 => Type::new_base(BaseType::Float64), + TypeVariant::Text => Type::new_base(BaseType::Text), + TypeVariant::Data => Type::new_base(BaseType::Data), + TypeVariant::Struct(rbs) => Type::new_base(BaseType::Struct(rbs)), + TypeVariant::AnyPointer => Type::new_base(BaseType::AnyPointer), + TypeVariant::Capability => Type::new_base(BaseType::Capability), + TypeVariant::Enum(es) => Type::new_base(BaseType::Enum(es)), + TypeVariant::List(list) => Type::list_of(list), + } + } +} + +/// A Cap'n Proto type, excluding `List`. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum BaseType { + Void, + Bool, + Int8, + Int16, + Int32, + Int64, + UInt8, + UInt16, + UInt32, + UInt64, + Float32, + Float64, + Text, + Data, + Struct(RawBrandedStructSchema), + AnyPointer, + Capability, + Enum(RawEnumSchema), +} + +macro_rules! primitive_introspect( + ($t:ty, $v:ident) => ( + impl Introspect for $t { + fn introspect() -> Type { Type::new_base(BaseType::$v) } + } + ) +); + +primitive_introspect!((), Void); +primitive_introspect!(bool, Bool); +primitive_introspect!(i8, Int8); +primitive_introspect!(i16, Int16); +primitive_introspect!(i32, Int32); +primitive_introspect!(i64, Int64); +primitive_introspect!(u8, UInt8); +primitive_introspect!(u16, UInt16); +primitive_introspect!(u32, UInt32); +primitive_introspect!(u64, UInt64); +primitive_introspect!(f32, Float32); +primitive_introspect!(f64, Float64); + +/// Type information that gets included in the generated code for every +/// user-defined Cap'n Proto struct. +#[derive(Copy, Clone)] +pub struct RawStructSchema { + /// The Node (as defined in schema.capnp), as a single segment message. + pub encoded_node: &'static [crate::Word], + + /// Indices (not ordinals) of fields that don't have a discriminant value. + pub nonunion_members: &'static [u16], + + /// Map from discriminant value to field index. + pub members_by_discriminant: &'static [u16], + // + // TODO: members_by_name, allowing fast field lookup by name. +} + +/// A RawStructSchema with branding information, i.e. resolution of type parameters. +/// To use one of this, you will usually want to convert it to a `schema::StructSchema`, +/// which can be done via `into()`. +#[derive(Copy, Clone)] +pub struct RawBrandedStructSchema { + /// The unbranded base schema. + pub generic: &'static RawStructSchema, + + /// Map from field index (not ordinal) to Type. + pub field_types: fn(u16) -> Type, + + /// Map from (maybe field index, annotation index) to the Type + /// of the value held by that annotation. + pub annotation_types: fn(Option, u32) -> Type, +} + +impl core::cmp::PartialEq for RawBrandedStructSchema { + fn eq(&self, other: &Self) -> bool { + core::ptr::eq(self.generic, other.generic) && self.field_types == other.field_types + // don't need to compare annotation_types. + // that field is equal iff field_types is. + } +} + +impl core::cmp::Eq for RawBrandedStructSchema {} + +impl core::fmt::Debug for RawBrandedStructSchema { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { + write!( + f, + "RawBrandedStructSchema({:?}, {:?})", + self.generic as *const _, self.field_types as *const fn(u16) -> Type + ) + } +} + +/// Type information that gets included in the generated code for every +/// user-defined Cap'n Proto enum. +/// To use one of this, you will usually want to convert it to a `schema::EnumSchema`, +/// which can be done via `into()`. +#[derive(Clone, Copy)] +pub struct RawEnumSchema { + /// The Node (as defined in schema.capnp), as a single segment message. + pub encoded_node: &'static [crate::Word], + + /// Map from (maybe enumerant index, annotation index) to the Type + /// of the value held by that annotation. + pub annotation_types: fn(Option, u32) -> Type, +} + +impl core::cmp::PartialEq for RawEnumSchema { + fn eq(&self, other: &Self) -> bool { + ::core::ptr::eq(self.encoded_node, other.encoded_node) + } +} + +impl core::cmp::Eq for RawEnumSchema {} + +impl core::fmt::Debug for RawEnumSchema { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { + write!(f, "RawEnumSchema({:?})", self.encoded_node as *const _) + } +} diff --git a/rust/capnp/io.rs b/rust/capnp/io.rs new file mode 100644 index 000000000000..59d149b37c26 --- /dev/null +++ b/rust/capnp/io.rs @@ -0,0 +1,202 @@ +//! Custom I/O traits that roughly mirror `std::io::{Read, BufRead, Write}`. +//! This extra layer of indirection enables support of no-std environments. + +use crate::{Error, ErrorKind, Result}; + +/// A rough approximation of std::io::Read. +pub trait Read { + /// Attempts to read some bytes into `buf` and returns the number of bytes read. + /// A return value of Ok(0) means that the end of the stream was reached. + /// + /// Unlike with std::io::Read, implementations are expected to handle EINTR + /// (i.e. std::io::ErrorKind::Interrupted) internally, by looping until either success + /// is achieved or some other error is hit. + fn read(&mut self, buf: &mut [u8]) -> Result; + + fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { + while !buf.is_empty() { + match self.read(buf)? { + 0 => break, + n => { + let tmp = buf; + buf = &mut tmp[n..]; + } + } + } + if !buf.is_empty() { + Err(Error::from_kind(ErrorKind::FailedToFillTheWholeBuffer)) + } else { + Ok(()) + } + } +} + +/// A rough approximation of std::io::BufRead. +pub trait BufRead: Read { + fn fill_buf(&mut self) -> Result<&[u8]>; + fn consume(&mut self, amt: usize); +} + +/// A rough approximation of std::io::Write. +pub trait Write { + fn write_all(&mut self, buf: &[u8]) -> Result<()>; +} + +/// Blanket impls for when `std` is enabled. +#[cfg(feature = "std")] +mod std_impls { + use crate::io::{BufRead, Read, Write}; + use crate::Result; + + impl Read for R + where + R: std::io::Read, + { + fn read(&mut self, buf: &mut [u8]) -> Result { + loop { + match std::io::Read::read(self, buf) { + Ok(n) => return Ok(n), + Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {} + Err(e) => return Err(e.into()), + } + } + } + } + + impl BufRead for R + where + R: std::io::BufRead, + { + fn fill_buf(&mut self) -> Result<&[u8]> { + Ok(std::io::BufRead::fill_buf(self)?) + } + fn consume(&mut self, amt: usize) { + std::io::BufRead::consume(self, amt) + } + } + + impl Write for W + where + W: std::io::Write, + { + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + std::io::Write::write_all(self, buf)?; + Ok(()) + } + } +} + +/// Blanket impls for when `embedded-io` is enabled and `std` is not. +#[cfg(all(feature = "embedded-io", not(feature = "std")))] +mod embedded_io_impls { + use crate::io::{BufRead, Read, Write}; + use crate::Result; + use embedded_io::Error; + + impl Write for W { + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + embedded_io::Write::write_all(self, buf).map_err(|e| match e { + embedded_io::WriteAllError::WriteZero => { + crate::Error::from_kind(crate::ErrorKind::Failed) + } + embedded_io::WriteAllError::Other(e) => crate::Error::from_kind(e.kind().into()), + })?; + Ok(()) + } + } + + impl Read for R { + fn read(&mut self, buf: &mut [u8]) -> Result { + embedded_io::Read::read(self, buf).map_err(|e| crate::Error::from_kind(e.kind().into())) + } + } + + impl BufRead for R { + fn fill_buf(&mut self) -> Result<&[u8]> { + embedded_io::BufRead::fill_buf(self) + .map_err(|e| crate::Error::from_kind(e.kind().into())) + } + + fn consume(&mut self, amt: usize) { + embedded_io::BufRead::consume(self, amt) + } + } +} + +/// Fallback impls, for when neither `std` nor `embedded-io` is enabled. +#[cfg(not(any(feature = "std", feature = "embedded-io")))] +mod no_std_impls { + use crate::io::{BufRead, Read, Write}; + use crate::{Error, ErrorKind, Result}; + + impl<'a> Write for &'a mut [u8] { + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + if buf.len() > self.len() { + return Err(Error::from_kind(ErrorKind::BufferNotLargeEnough)); + } + let amt = buf.len(); + let (a, b) = core::mem::take(self).split_at_mut(amt); + a.copy_from_slice(buf); + *self = b; + Ok(()) + } + } + + #[cfg(feature = "alloc")] + impl Write for alloc::vec::Vec { + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + self.extend_from_slice(buf); + Ok(()) + } + } + + impl Write for &mut W + where + W: Write, + { + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + (**self).write_all(buf) + } + } + + impl<'a> Read for &'a [u8] { + fn read(&mut self, buf: &mut [u8]) -> Result { + let amt = core::cmp::min(buf.len(), self.len()); + let (a, b) = self.split_at(amt); + + buf[..amt].copy_from_slice(a); + *self = b; + Ok(amt) + } + } + + impl Read for &mut R + where + R: Read, + { + fn read(&mut self, buf: &mut [u8]) -> Result { + (**self).read(buf) + } + } + + impl<'a> BufRead for &'a [u8] { + fn fill_buf(&mut self) -> Result<&[u8]> { + Ok(*self) + } + fn consume(&mut self, amt: usize) { + *self = &self[amt..] + } + } + + impl BufRead for &mut R + where + R: BufRead, + { + fn fill_buf(&mut self) -> Result<&[u8]> { + (**self).fill_buf() + } + fn consume(&mut self, amt: usize) { + (**self).consume(amt) + } + } +} diff --git a/rust/capnp/lib.rs b/rust/capnp/lib.rs new file mode 100644 index 000000000000..daafc23c19d5 --- /dev/null +++ b/rust/capnp/lib.rs @@ -0,0 +1,651 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! # Cap'n Proto Runtime Library +//! +//! This crate contains basic facilities for reading and writing +//! [Cap'n Proto](https://capnproto.org) messages in Rust. It is intended to +//! be used in conjunction with code generated by the +//! [capnpc-rust](https://crates.io/crates/capnpc) crate. + +#![cfg_attr(feature = "rpc_try", feature(try_trait_v2))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "alloc")] +#[macro_use] +extern crate alloc; + +/// Code generated from +/// [schema.capnp](https://github.com/capnproto/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp). +pub mod schema_capnp; + +pub mod any_pointer; +pub mod any_pointer_list; +pub mod capability; +pub mod capability_list; +pub mod constant; +pub mod data; +pub mod data_list; +pub mod dynamic_list; +pub mod dynamic_struct; +pub mod dynamic_value; +pub mod enum_list; +pub mod introspect; +pub mod io; +pub mod list_list; +pub mod message; +pub mod primitive_list; +pub mod private; +pub mod raw; +pub mod schema; +pub mod serialize; +pub mod serialize_packed; +pub(crate) mod stringify; +pub mod struct_list; +pub mod text; +pub mod text_list; +pub mod traits; + +#[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +/// +/// 8 bytes, aligned to an 8-byte boundary. +/// +/// Internally, capnproto-rust allocates message buffers using this type, +/// to guarantee alignment. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(C, align(8))] +pub struct Word { + raw_content: [u8; 8], +} + +/// +/// Constructs a word with the given bytes. +/// +#[allow(clippy::too_many_arguments)] +pub const fn word(b0: u8, b1: u8, b2: u8, b3: u8, b4: u8, b5: u8, b6: u8, b7: u8) -> Word { + Word { + raw_content: [b0, b1, b2, b3, b4, b5, b6, b7], + } +} + +impl Word { + /// Allocates a vec of `length` words, all set to zero. + #[cfg(feature = "alloc")] + pub fn allocate_zeroed_vec(length: usize) -> Vec { + vec![word(0, 0, 0, 0, 0, 0, 0, 0); length] + } + + pub fn words_to_bytes(words: &[Self]) -> &[u8] { + unsafe { core::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8) } + } + + pub fn words_to_bytes_mut(words: &mut [Self]) -> &mut [u8] { + unsafe { core::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8) } + } +} + +#[cfg(any(feature = "quickcheck", test))] +impl quickcheck::Arbitrary for Word { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { + crate::word( + quickcheck::Arbitrary::arbitrary(g), + quickcheck::Arbitrary::arbitrary(g), + quickcheck::Arbitrary::arbitrary(g), + quickcheck::Arbitrary::arbitrary(g), + quickcheck::Arbitrary::arbitrary(g), + quickcheck::Arbitrary::arbitrary(g), + quickcheck::Arbitrary::arbitrary(g), + quickcheck::Arbitrary::arbitrary(g), + ) + } +} + +/// Size of a message. Every generated struct has a method `.total_size()` that returns this. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct MessageSize { + pub word_count: u64, + + /// Size of the capability table. + pub cap_count: u32, +} + +impl core::ops::AddAssign for MessageSize { + fn add_assign(&mut self, rhs: Self) { + self.word_count += rhs.word_count; + self.cap_count += rhs.cap_count; + } +} + +/// An enum value or union discriminant that was not found among those defined in a schema. +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct NotInSchema(pub u16); + +impl ::core::fmt::Display for NotInSchema { + fn fmt( + &self, + fmt: &mut ::core::fmt::Formatter, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + write!( + fmt, + "Enum value or union discriminant {} was not present in the schema.", + self.0 + ) + } +} + +#[cfg(feature = "std")] +impl ::std::error::Error for NotInSchema { + fn description(&self) -> &str { + "Enum value or union discriminant was not present in schema." + } +} + +/// Because messages are lazily validated, the return type of any method that reads a pointer field +/// must be wrapped in a Result. +pub type Result = ::core::result::Result; + +/// Describes an arbitrary error that prevented an operation from completing. +#[derive(Debug, Clone)] +pub struct Error { + /// The general kind of the error. Code that decides how to respond to an error + /// should read only this field in making its decision. + pub kind: ErrorKind, + + /// Extra context about error + #[cfg(feature = "alloc")] + pub extra: String, +} + +/// The general nature of an error. The purpose of this enum is not to describe the error itself, +/// but rather to describe how the client might want to respond to the error. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum ErrorKind { + /// Something went wrong + Failed, + + /// The call failed because of a temporary lack of resources. This could be space resources + /// (out of memory, out of disk space) or time resources (request queue overflow, operation + /// timed out). + /// + /// The operation might work if tried again, but it should NOT be repeated immediately as this + /// may simply exacerbate the problem. + Overloaded, + + /// The call required communication over a connection that has been lost. The callee will need + /// to re-establish connections and try again. + Disconnected, + + /// The requested method is not implemented. The caller may wish to revert to a fallback + /// approach based on other methods. + Unimplemented, + + /// Buffer is not large enough + BufferNotLargeEnough, + + /// Cannot create a canonical message with a capability + CannotCreateACanonicalMessageWithACapability, + + /// Cannot set AnyPointer field to a primitive value + CannotSetAnyPointerFieldToAPrimitiveValue, + + /// Don't know how to handle non-STRUCT inline composite. + CantHandleNonStructInlineComposite, + + /// Empty buffer + EmptyBuffer, + + /// Empty slice + EmptySlice, + + /// Enum value or union discriminant {} was not present in schema + EnumValueOrUnionDiscriminantNotPresent(NotInSchema), + + /// Called get_writable_{data|text}_pointer() but existing list pointer is not byte-sized. + ExistingListPointerIsNotByteSized, + + /// Existing list value is incompatible with expected type. + ExistingListValueIsIncompatibleWithExpectedType, + + /// Called get_writable_{data|text|list|struct_list}_pointer() but existing pointer is not a list. + ExistingPointerIsNotAList, + + /// Expected a list or blob. + ExpectedAListOrBlob, + + /// Expected a pointer list, but got a list of data-only structs + ExpectedAPointerListButGotAListOfDataOnlyStructs, + + /// Expected a primitive list, but got a list of pointer-only structs + ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs, + + /// failed to fill the whole buffer + FailedToFillTheWholeBuffer, + + /// field and default mismatch + FieldAndDefaultMismatch, + + /// field not found + FieldNotFound, + + /// Found bit list where struct list was expected; upgrading boolean lists to struct lists is no longer supported + FoundBitListWhereStructListWasExpected, + + /// Found struct list where bit list was expected. + FoundStructListWhereBitListWasExpected, + + /// Cannot represent 4 byte length as `usize`. This may indicate that you are running on 8 or 16 bit platform or message is too large. + FourByteLengthTooBigForUSize, + + /// Cannot represent 4 byte segment length as usize. This may indicate that you are running on 8 or 16 bit platform or segment is too large + FourByteSegmentLengthTooBigForUSize, + + /// group field but type is not Struct + GroupFieldButTypeIsNotStruct, + + /// init() is only valid for struct and AnyPointer fields + InitIsOnlyValidForStructAndAnyPointerFields, + + /// initn() is only valid for list, text, or data fields + InitnIsOnlyValidForListTextOrDataFields, + + /// InlineComposite list with non-STRUCT elements not supported. + InlineCompositeListWithNonStructElementsNotSupported, + + /// InlineComposite list's elements overrun its word count. + InlineCompositeListsElementsOverrunItsWordCount, + + /// InlineComposite lists of non-STRUCT type are not supported. + InlineCompositeListsOfNonStructTypeAreNotSupported, + + /// Too many or too few segments {segment_count} + InvalidNumberOfSegments(usize), + + /// Invalid segment id {id} + InvalidSegmentId(u32), + + /// List(AnyPointer) not supported. + ListAnyPointerNotSupported, + + /// List(Capability) not supported + ListCapabilityNotSupported, + + /// Malformed double-far pointer. + MalformedDoubleFarPointer, + + /// Message contains invalid capability pointer. + MessageContainsInvalidCapabilityPointer, + + /// Message contains list pointer of non-bytes where data was expected. + MessageContainsListPointerOfNonBytesWhereDataWasExpected, + + /// Message contains list pointer of non-bytes where text was expected. + MessageContainsListPointerOfNonBytesWhereTextWasExpected, + + /// Message contains list with incompatible element type. + MessageContainsListWithIncompatibleElementType, + + /// Message contains non-capability pointer where capability pointer was expected. + MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected, + + /// Message contains non-struct pointer where struct pointer was expected. + MessageContainsNonStructPointerWhereStructPointerWasExpected, + + /// Message contains non-list pointer where data was expected. + MessageContainsNonListPointerWhereDataWasExpected, + + /// Message contains non-list pointer where list pointer was expected + MessageContainsNonListPointerWhereListPointerWasExpected, + + /// Message contains non-list pointer where text was expected. + MessageContainsNonListPointerWhereTextWasExpected, + + /// Message contains null capability pointer. + MessageContainsNullCapabilityPointer, + + /// Message contains out-of-bounds pointer, + MessageContainsOutOfBoundsPointer, + + /// Message contains text that is not NUL-terminated + MessageContainsTextThatIsNotNULTerminated, + + /// Message ends prematurely. Header claimed {header} words, but message only has {body} words, + MessageEndsPrematurely(usize, usize), + + /// Message is too deeply nested. + MessageIsTooDeeplyNested, + + /// Message is too deeply-nested or contains cycles. + MessageIsTooDeeplyNestedOrContainsCycles, + + /// Message was not aligned by 8 bytes boundary. Either ensure that message is properly aligned or compile `capnp` crate with \"unaligned\" feature enabled. + MessageNotAlignedBy8BytesBoundary, + + /// Message's size cannot be represented in usize + MessageSizeOverflow, + + /// Message is too large + MessageTooLarge(usize), + + /// Nesting limit exceeded + NestingLimitExceeded, + + /// Not a struct + NotAStruct, + + /// Only one of the section pointers is pointing to ourself + OnlyOneOfTheSectionPointersIsPointingToOurself, + + /// Packed input did not end cleanly on a segment boundary. + PackedInputDidNotEndCleanlyOnASegmentBoundary, + + /// Premature end of file + PrematureEndOfFile, + + /// Premature end of packed input. + PrematureEndOfPackedInput, + + /// Read limit exceeded + ReadLimitExceeded, + + /// setting dynamic capabilities is unsupported + SettingDynamicCapabilitiesIsUnsupported, + + /// Struct reader had bitwidth other than 1 + StructReaderHadBitwidthOtherThan1, + + /// Text blob missing NUL terminator. + TextBlobMissingNULTerminator, + + /// Text contains non-utf8 data + TextContainsNonUtf8Data(core::str::Utf8Error), + + /// Tried to read from null arena + TriedToReadFromNullArena, + + /// type mismatch + TypeMismatch, + + /// Detected unaligned segment. You must either ensure all of your segments are 8-byte aligned, + /// or you must enable the "unaligned" feature in the capnp crate + UnalignedSegment, + + /// Unexpected far pointer + UnexepectedFarPointer, + + /// Unknown pointer type. + UnknownPointerType, +} + +impl Error { + /// Writes to the `extra` field. Does nothing if the "alloc" feature is not enabled. + /// This is intended to be used with the `write!()` macro from core. + pub fn write_fmt(&mut self, fmt: core::fmt::Arguments<'_>) { + #[cfg(feature = "alloc")] + { + use core::fmt::Write; + let _ = self.extra.write_fmt(fmt); + } + } + + #[cfg(feature = "alloc")] + pub fn failed(description: String) -> Self { + Self { + extra: description, + kind: ErrorKind::Failed, + } + } + + pub fn from_kind(kind: ErrorKind) -> Self { + #[cfg(not(feature = "alloc"))] + return Self { kind }; + #[cfg(feature = "alloc")] + return Self { + kind, + extra: String::new(), + }; + } + + #[cfg(feature = "alloc")] + pub fn overloaded(description: String) -> Self { + Self { + extra: description, + kind: ErrorKind::Overloaded, + } + } + #[cfg(feature = "alloc")] + pub fn disconnected(description: String) -> Self { + Self { + extra: description, + kind: ErrorKind::Disconnected, + } + } + + #[cfg(feature = "alloc")] + pub fn unimplemented(description: String) -> Self { + Self { + extra: description, + kind: ErrorKind::Unimplemented, + } + } +} + +#[cfg(feature = "std")] +impl core::convert::From<::std::io::Error> for Error { + fn from(err: ::std::io::Error) -> Self { + use std::io; + let kind = match err.kind() { + io::ErrorKind::TimedOut => ErrorKind::Overloaded, + io::ErrorKind::BrokenPipe + | io::ErrorKind::ConnectionRefused + | io::ErrorKind::ConnectionReset + | io::ErrorKind::ConnectionAborted + | io::ErrorKind::NotConnected => ErrorKind::Disconnected, + _ => ErrorKind::Failed, + }; + #[cfg(feature = "alloc")] + return Self { + kind, + extra: format!("{err}"), + }; + #[cfg(not(feature = "alloc"))] + return Self { kind }; + } +} + +#[cfg(feature = "embedded-io")] +impl From for ErrorKind { + fn from(value: embedded_io::ErrorKind) -> Self { + match value { + embedded_io::ErrorKind::Other => Self::Failed, + embedded_io::ErrorKind::NotFound => Self::Failed, + embedded_io::ErrorKind::PermissionDenied => Self::Failed, + embedded_io::ErrorKind::ConnectionRefused => Self::Failed, + embedded_io::ErrorKind::ConnectionReset => Self::Failed, + embedded_io::ErrorKind::ConnectionAborted => Self::Failed, + embedded_io::ErrorKind::NotConnected => Self::Failed, + embedded_io::ErrorKind::AddrInUse => Self::Failed, + embedded_io::ErrorKind::AddrNotAvailable => Self::Failed, + embedded_io::ErrorKind::BrokenPipe => Self::Failed, + embedded_io::ErrorKind::AlreadyExists => Self::Failed, + embedded_io::ErrorKind::InvalidInput => Self::Failed, + embedded_io::ErrorKind::InvalidData => Self::Failed, + embedded_io::ErrorKind::TimedOut => Self::Failed, + embedded_io::ErrorKind::Interrupted => Self::Failed, + embedded_io::ErrorKind::Unsupported => Self::Failed, + embedded_io::ErrorKind::OutOfMemory => Self::Failed, + _ => Self::Failed, + } + } +} + +#[cfg(feature = "alloc")] +impl core::convert::From for Error { + fn from(err: alloc::string::FromUtf8Error) -> Self { + Self::failed(format!("{err}")) + } +} + +impl core::convert::From for Error { + fn from(err: core::str::Utf8Error) -> Self { + Self::from_kind(ErrorKind::TextContainsNonUtf8Data(err)) + } +} + +impl core::convert::From for Error { + fn from(e: NotInSchema) -> Self { + Self::from_kind(ErrorKind::EnumValueOrUnionDiscriminantNotPresent(e)) + } +} + +impl core::fmt::Display for ErrorKind { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { + match self { + Self::Failed => write!(fmt, "Failed"), + Self::Overloaded => write!(fmt, "Overloaded"), + Self::Disconnected => write!(fmt, "Disconnected"), + Self::Unimplemented => write!(fmt, "Unimplemented"), + Self::BufferNotLargeEnough => write!(fmt, "buffer is not large enough"), + Self::ExistingListPointerIsNotByteSized => write!(fmt, "Called get_writable_{{data|text}}_pointer() but existing list pointer is not byte-sized."), + Self::ExistingPointerIsNotAList => write!(fmt, "Called get_writable_{{data|text|list|struct_list}}_pointer() but existing pointer is not a list."), + Self::CannotCreateACanonicalMessageWithACapability => write!(fmt, "Cannot create a canonical message with a capability"), + Self::FourByteLengthTooBigForUSize => write!(fmt, "Cannot represent 4 byte length as `usize`. This may indicate that you are running on 8 or 16 bit platform or message is too large."), + Self::FourByteSegmentLengthTooBigForUSize => write!(fmt, "Cannot represent 4 byte segment length as usize. This may indicate that you are running on 8 or 16 bit platform or segment is too large"), + Self::CannotSetAnyPointerFieldToAPrimitiveValue => write!(fmt, "cannot set AnyPointer field to a primitive value"), + Self::CantHandleNonStructInlineComposite => write!(fmt, "Don't know how to handle non-STRUCT inline composite."), + Self::EmptyBuffer => write!(fmt, "empty buffer"), + Self::EmptySlice => write!(fmt, "empty slice"), + Self::EnumValueOrUnionDiscriminantNotPresent(val) => write!(fmt, "Enum value or union discriminant {val} was not present in schema"), + Self::ExistingListValueIsIncompatibleWithExpectedType => write!(fmt, "Existing list value is incompatible with expected type."), + Self::ExpectedAListOrBlob => write!(fmt, "Expected a list or blob."), + Self::ExpectedAPointerListButGotAListOfDataOnlyStructs => write!(fmt, "Expected a pointer list, but got a list of data-only structs"), + Self::ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs => write!(fmt, "Expected a primitive list, but got a list of pointer-only structs"), + Self::FailedToFillTheWholeBuffer => write!(fmt, "failed to fill the whole buffer"), + Self::FieldAndDefaultMismatch => write!(fmt, "field and default mismatch"), + Self::FieldNotFound => write!(fmt, "field not found"), + Self::FoundBitListWhereStructListWasExpected => write!(fmt, "Found bit list where struct list was expected; upgrading boolean lists to struct lists is no longer supported."), + Self::FoundStructListWhereBitListWasExpected => write!(fmt, "Found struct list where bit list was expected."), + Self::GroupFieldButTypeIsNotStruct => write!(fmt, "group field but type is not Struct"), + Self::InitIsOnlyValidForStructAndAnyPointerFields => write!(fmt, "init() is only valid for struct and AnyPointer fields"), + Self::InitnIsOnlyValidForListTextOrDataFields => write!(fmt, "initn() is only valid for list, text, or data fields"), + Self::InlineCompositeListWithNonStructElementsNotSupported => write!(fmt, "InlineComposite list with non-STRUCT elements not supported."), + Self::InlineCompositeListsElementsOverrunItsWordCount => write!(fmt, "InlineComposite list's elements overrun its word count."), + Self::InlineCompositeListsOfNonStructTypeAreNotSupported => write!(fmt, "InlineComposite lists of non-STRUCT type are not supported."), + Self::InvalidNumberOfSegments(segment_count) => write!(fmt, "Too many or too few segments {segment_count}"), + Self::InvalidSegmentId(id) => write!(fmt, "Invalid segment id {id}"), + Self::ListAnyPointerNotSupported => write!(fmt, "List(AnyPointer) not supported."), + Self::ListCapabilityNotSupported => write!(fmt, "List(Capability) not supported"), + Self::MalformedDoubleFarPointer => write!(fmt, "Malformed double-far pointer."), + Self::MessageContainsInvalidCapabilityPointer => write!(fmt, "Message contained invalid capability pointer."), + Self::MessageContainsListPointerOfNonBytesWhereDataWasExpected => write!(fmt, "Message contains list pointer of non-bytes where data was expected."), + Self::MessageContainsListPointerOfNonBytesWhereTextWasExpected => write!(fmt, "Message contains list pointer of non-bytes where text was expected."), + Self::MessageContainsListWithIncompatibleElementType => write!(fmt, "Message contains list with incompatible element type."), + Self::MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected => write!(fmt, "Message contains non-capability pointer where capability pointer was expected."), + Self::MessageContainsNonListPointerWhereDataWasExpected => write!(fmt, "Message contains non-list pointer where data was expected."), + Self::MessageContainsNonListPointerWhereListPointerWasExpected => write!(fmt, "Message contains non-list pointer where list pointer was expected"), + Self::MessageContainsNonListPointerWhereTextWasExpected => write!(fmt, "Message contains non-list pointer where text was expected."), + Self::MessageContainsNonStructPointerWhereStructPointerWasExpected => write!(fmt, "Message contains non-struct pointer where struct pointer was expected."), + Self::MessageContainsNullCapabilityPointer => write!(fmt, "Message contains null capability pointer."), + Self::MessageContainsOutOfBoundsPointer => write!(fmt, "Message contains out-of-bounds pointer"), + Self::MessageContainsTextThatIsNotNULTerminated => write!(fmt, "Message contains text that is not NUL-terminated"), + Self::MessageEndsPrematurely(header, body) => write!(fmt, "Message ends prematurely. Header claimed {header} words, but message only has {body} words"), + Self::MessageIsTooDeeplyNested => write!(fmt, "Message is too deeply nested."), + Self::MessageIsTooDeeplyNestedOrContainsCycles => write!(fmt, "Message is too deeply-nested or contains cycles."), + Self::MessageSizeOverflow => write!(fmt, "Message's size cannot be represented in usize"), + Self::MessageTooLarge(val) => write!(fmt, "Message is too large: {val}"), + Self::MessageNotAlignedBy8BytesBoundary => write!(fmt, "Message was not aligned by 8 bytes boundary. Either ensure that message is properly aligned or compile `capnp` crate with \"unaligned\" feature enabled."), + Self::NestingLimitExceeded => write!(fmt, "nesting limit exceeded"), + Self::NotAStruct => write!(fmt, "not a struct"), + Self::OnlyOneOfTheSectionPointersIsPointingToOurself => write!(fmt, "Only one of the section pointers is pointing to ourself"), + Self::PackedInputDidNotEndCleanlyOnASegmentBoundary => write!(fmt, "Packed input did not end cleanly on a segment boundary."), + Self::PrematureEndOfFile => write!(fmt, "Premature end of file"), + Self::PrematureEndOfPackedInput => write!(fmt, "Premature end of packed input."), + Self::ReadLimitExceeded => write!(fmt, "Read limit exceeded"), + Self::SettingDynamicCapabilitiesIsUnsupported => write!(fmt, "setting dynamic capabilities is unsupported"), + Self::StructReaderHadBitwidthOtherThan1 => write!(fmt, "struct reader had bitwidth other than 1"), + Self::TextBlobMissingNULTerminator => write!(fmt, "Text blob missing NUL terminator."), + Self::TextContainsNonUtf8Data(e) => write!(fmt, "Text contains non-utf8 data: {e}"), + Self::TriedToReadFromNullArena => write!(fmt, "Tried to read from null arena"), + Self::TypeMismatch => write!(fmt, "type mismatch"), + Self::UnalignedSegment => write!(fmt, "Detected unaligned segment. You must either ensure all of your segments are 8-byte aligned, or you must enable the \"unaligned\" feature in the capnp crate"), + Self::UnexepectedFarPointer => write!(fmt, "Unexpected far pointer"), + Self::UnknownPointerType => write!(fmt, "Unknown pointer type."), + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { + #[cfg(feature = "alloc")] + let result = if self.extra.is_empty() { + write!(fmt, "{}", self.kind) + } else { + write!(fmt, "{}: {}", self.kind, self.extra) + }; + #[cfg(not(feature = "alloc"))] + let result = write!(fmt, "{}", self.kind); + result + } +} + +#[cfg(feature = "std")] +impl ::std::error::Error for Error { + #[cfg(feature = "alloc")] + fn description(&self) -> &str { + &self.extra + } + fn cause(&self) -> Option<&dyn (::std::error::Error)> { + None + } +} + +/// Helper struct that allows `MessageBuilder::get_segments_for_output()` to avoid heap allocations +/// in the single-segment case. +#[cfg(feature = "alloc")] +pub enum OutputSegments<'a> { + SingleSegment([&'a [u8]; 1]), + MultiSegment(Vec<&'a [u8]>), +} + +#[cfg(feature = "alloc")] +impl<'a> core::ops::Deref for OutputSegments<'a> { + type Target = [&'a [u8]]; + fn deref(&self) -> &[&'a [u8]] { + match self { + OutputSegments::SingleSegment(s) => s, + OutputSegments::MultiSegment(v) => v, + } + } +} + +#[cfg(feature = "alloc")] +impl<'s> message::ReaderSegments for OutputSegments<'s> { + fn get_segment(&self, id: u32) -> Option<&[u8]> { + match self { + OutputSegments::SingleSegment(s) => s.get(id as usize).copied(), + OutputSegments::MultiSegment(v) => v.get(id as usize).copied(), + } + } +} diff --git a/rust/capnp/list_list.rs b/rust/capnp/list_list.rs new file mode 100644 index 000000000000..7c31560958d3 --- /dev/null +++ b/rust/capnp/list_list.rs @@ -0,0 +1,296 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of lists. + +use crate::introspect; +use crate::private::layout::{ListBuilder, ListReader, Pointer, PointerBuilder, PointerReader}; +use crate::traits::{FromPointerBuilder, FromPointerReader, IndexMove, ListIter}; +use crate::Result; + +#[derive(Clone, Copy)] +pub struct Owned +where + T: crate::traits::Owned, +{ + marker: ::core::marker::PhantomData, +} + +impl introspect::Introspect for Owned +where + T: introspect::Introspect + crate::traits::Owned, +{ + fn introspect() -> introspect::Type { + introspect::Type::list_of(T::introspect()) + } +} + +impl crate::traits::Owned for Owned +where + T: crate::traits::Owned, +{ + type Reader<'a> = Reader<'a, T>; + type Builder<'a> = Builder<'a, T>; +} + +pub struct Reader<'a, T> +where + T: crate::traits::Owned, +{ + marker: ::core::marker::PhantomData>, + reader: ListReader<'a>, +} + +impl<'a, T> Reader<'a, T> +where + T: crate::traits::Owned, +{ + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, Result>> { + ListIter::new(self, self.len()) + } +} + +impl<'a, T> Clone for Reader<'a, T> +where + T: crate::traits::Owned, +{ + fn clone(&self) -> Reader<'a, T> { + *self + } +} + +impl<'a, T> Copy for Reader<'a, T> where T: crate::traits::Owned {} + +impl<'a, T> IndexMove>> for Reader<'a, T> +where + T: crate::traits::Owned, +{ + fn index_move(&self, index: u32) -> Result> { + self.get(index) + } +} + +impl<'a, T> FromPointerReader<'a> for Reader<'a, T> +where + T: crate::traits::Owned, +{ + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(Pointer, default)?, + marker: ::core::marker::PhantomData, + }) + } +} + +impl<'a, T> Reader<'a, T> +where + T: crate::traits::Owned, +{ + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> Result> { + assert!(index < self.len()); + FromPointerReader::get_from_pointer(&self.reader.get_pointer_element(index), None) + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option>> { + if index < self.len() { + Some(FromPointerReader::get_from_pointer( + &self.reader.get_pointer_element(index), + None, + )) + } else { + None + } + } +} + +impl<'a, T> crate::traits::IntoInternalListReader<'a> for Reader<'a, T> +where + T: crate::traits::Owned, +{ + fn into_internal_list_reader(self) -> ListReader<'a> { + self.reader + } +} + +pub struct Builder<'a, T> +where + T: crate::traits::Owned, +{ + marker: ::core::marker::PhantomData, + builder: ListBuilder<'a>, +} + +impl<'a, T> Builder<'a, T> +where + T: crate::traits::Owned, +{ + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn into_reader(self) -> Reader<'a, T> { + Reader { + reader: self.builder.into_reader(), + marker: ::core::marker::PhantomData, + } + } +} + +impl<'a, T> Builder<'a, T> +where + T: crate::traits::Owned, +{ + pub fn init(self, index: u32, size: u32) -> T::Builder<'a> { + FromPointerBuilder::init_pointer(self.builder.get_pointer_element(index), size) + } +} + +impl<'a, T> Builder<'a, T> +where + T: crate::traits::Owned, +{ + pub fn reborrow(&mut self) -> Builder<'_, T> { + Builder { + builder: self.builder.reborrow(), + marker: ::core::marker::PhantomData, + } + } +} + +impl<'a, T> FromPointerBuilder<'a> for Builder<'a, T> +where + T: crate::traits::Owned, +{ + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a, T> { + Builder { + marker: ::core::marker::PhantomData, + builder: builder.init_list(Pointer, size), + } + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + marker: ::core::marker::PhantomData, + builder: builder.get_list(Pointer, default)?, + }) + } +} + +impl<'a, T> Builder<'a, T> +where + T: crate::traits::Owned, +{ + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> Result> { + assert!(index < self.len()); + FromPointerBuilder::get_from_pointer(self.builder.get_pointer_element(index), None) + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option>> { + if index < self.len() { + Some(FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_element(index), + None, + )) + } else { + None + } + } + + pub fn set<'b>(&mut self, index: u32, value: T::Reader<'a>) -> Result<()> + where + T::Reader<'a>: crate::traits::IntoInternalListReader<'b>, + { + use crate::traits::IntoInternalListReader; + assert!(index < self.len()); + self.builder + .reborrow() + .get_pointer_element(index) + .set_list(&value.into_internal_list_reader(), false) + } +} + +impl<'a, T> crate::traits::SetPointerBuilder for Reader<'a, T> +where + T: crate::traits::Owned, +{ + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a, T>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize) + } +} + +impl<'a, T> ::core::iter::IntoIterator for Reader<'a, T> +where + T: crate::traits::Owned, +{ + type Item = Result>; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T: crate::traits::Owned> From> for crate::dynamic_value::Reader<'a> { + fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( + t.reader, + T::introspect(), + )) + } +} + +impl<'a, T: crate::traits::Owned> From> for crate::dynamic_value::Builder<'a> { + fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( + t.builder, + T::introspect(), + )) + } +} diff --git a/rust/capnp/message.rs b/rust/capnp/message.rs new file mode 100644 index 000000000000..fe40e0a7c313 --- /dev/null +++ b/rust/capnp/message.rs @@ -0,0 +1,878 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Untyped root container for a Cap'n Proto value. +//! +//! ## Notes about type specialization +//! This module provides [TypedReader] and [TypedBuilder] structs which are strongly-typed variants +//! of [Reader] and [Builder]. +//! +//! Code autogenerated by capnpc will have an individual module for each of structures and each of +//! modules will have `Owned` struct which implements [Owned] trait. +//! +//! Example from a real auto-generated file: +//! +//! ```ignore +//! pub mod simple_struct { +//! #[derive(Copy, Clone)] +//! pub struct Owned(()); +//! impl <'a> ::capnp::traits::Owned<'a> for Owned { type Reader = Reader<'a>; type Builder = Builder<'a>; } +//! .... +//! } +//! ``` +//! +//! [TypedReader] and [TypedBuilder] accept generic type parameter `T`. This parameter must be +//! a corresponding `Owned` type which was auto-generated inside the corresponding module. +//! +//! For example, for auto-generated module `crate::test_data::simple_struct` you'd supply +//! `crate::test_data::simple_struct::Owned` type into [TypedReader]/[TypedBuilder] +//! +//! ```ignore +//! include!(concat!(env!("OUT_DIR"), "/simple_struct_capnp.rs")); +//! +//! use capnp::message::{self, TypedBuilder, TypedReader}; +//! +//! fn main() { +//! let mut builder = TypedBuilder::::new_default(); +//! let mut builder_root = builder.init_root(); +//! builder_root.set_x(10); +//! builder_root.set_y(20); +//! +//! let mut buffer = vec![]; +//! capnp::serialize_packed::write_message(&mut buffer, builder.borrow_inner()).unwrap(); +//! +//! let reader = capnp::serialize_packed::read_message(buffer.as_slice(), ReaderOptions::new()).unwrap(); +//! let typed_reader = TypedReader::<_, simple_struct::Owned>::new(reader); +//! +//! let reader_root = typed_reader.get().unwrap(); +//! assert_eq!(reader_root.get_x(), 10); +//! assert_eq!(reader_root.get_x(), 20); +//! } +//! +//! ``` +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::convert::From; + +use crate::any_pointer; +#[cfg(feature = "alloc")] +use crate::private::arena::{BuilderArena, BuilderArenaImpl}; +use crate::private::arena::{ReaderArena, ReaderArenaImpl}; +use crate::private::layout; +use crate::private::units::BYTES_PER_WORD; +#[cfg(feature = "alloc")] +use crate::traits::{FromPointerBuilder, SetPointerBuilder}; +use crate::traits::{FromPointerReader, Owned}; +#[cfg(feature = "alloc")] +use crate::OutputSegments; +use crate::Result; + +/// Options controlling how data is read. +#[derive(Clone, Copy, Debug)] +pub struct ReaderOptions { + /// Limits how many total (8-byte) words of data are allowed to be traversed. Traversal is counted + /// when a new struct or list builder is obtained, e.g. from a get() accessor. This means that + /// calling the getter for the same sub-struct multiple times will cause it to be double-counted. + /// Once the traversal limit is reached, an error will be reported. + /// + /// This limit exists for security reasons. It is possible for an attacker to construct a message + /// in which multiple pointers point at the same location. This is technically invalid, but hard + /// to detect. Using such a message, an attacker could cause a message which is small on the wire + /// to appear much larger when actually traversed, possibly exhausting server resources leading to + /// denial-of-service. + /// + /// It makes sense to set a traversal limit that is much larger than the underlying message. + /// Together with sensible coding practices (e.g. trying to avoid calling sub-object getters + /// multiple times, which is expensive anyway), this should provide adequate protection without + /// inconvenience. + /// + /// A traversal limit of `None` means that no limit is enforced. + pub traversal_limit_in_words: Option, + + /// Limits how deeply nested a message structure can be, e.g. structs containing other structs or + /// lists of structs. + /// + /// Like the traversal limit, this limit exists for security reasons. Since it is common to use + /// recursive code to traverse recursive data structures, an attacker could easily cause a stack + /// overflow by sending a very-depply-nested (or even cyclic) message, without the message even + /// being very large. The default limit of 64 is probably low enough to prevent any chance of + /// stack overflow, yet high enough that it is never a problem in practice. + pub nesting_limit: i32, +} + +pub const DEFAULT_READER_OPTIONS: ReaderOptions = ReaderOptions { + traversal_limit_in_words: Some(8 * 1024 * 1024), + nesting_limit: 64, +}; + +impl Default for ReaderOptions { + fn default() -> Self { + DEFAULT_READER_OPTIONS + } +} + +impl ReaderOptions { + pub fn new() -> Self { + DEFAULT_READER_OPTIONS + } + + pub fn nesting_limit(&mut self, value: i32) -> &mut Self { + self.nesting_limit = value; + self + } + + pub fn traversal_limit_in_words(&mut self, value: Option) -> &mut Self { + self.traversal_limit_in_words = value; + self + } +} + +/// An object that manages the buffers underlying a Cap'n Proto message reader. +pub trait ReaderSegments { + /// Gets the segment with index `idx`. Returns `None` if `idx` is out of range. + /// + /// The segment must be 8-byte aligned or the "unaligned" feature must + /// be enabled in the capnp crate. (Otherwise reading the segment will return an error.) + /// + /// The returned slice is required to point to memory that remains valid until the ReaderSegments + /// object is dropped. In safe Rust, it should not be possible to violate this requirement. + fn get_segment(&self, idx: u32) -> Option<&[u8]>; + + /// Gets the number of segments. + fn len(&self) -> usize { + for i in 0.. { + if self.get_segment(i as u32).is_none() { + return i; + } + } + unreachable!() + } + + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl ReaderSegments for &S +where + S: ReaderSegments, +{ + fn get_segment(&self, idx: u32) -> Option<&[u8]> { + (**self).get_segment(idx) + } + + fn len(&self) -> usize { + (**self).len() + } +} + +/// An array of segments. +pub struct SegmentArray<'a> { + segments: &'a [&'a [u8]], +} + +impl<'a> SegmentArray<'a> { + pub fn new(segments: &'a [&'a [u8]]) -> SegmentArray<'a> { + SegmentArray { segments } + } +} + +impl<'b> ReaderSegments for SegmentArray<'b> { + fn get_segment(&self, id: u32) -> Option<&[u8]> { + self.segments.get(id as usize).copied() + } + + fn len(&self) -> usize { + self.segments.len() + } +} + +impl<'b> ReaderSegments for [&'b [u8]] { + fn get_segment(&self, id: u32) -> Option<&[u8]> { + self.get(id as usize).copied() + } + + fn len(&self) -> usize { + self.len() + } +} + +/// A container used to read a message. +pub struct Reader +where + S: ReaderSegments, +{ + arena: ReaderArenaImpl, +} + +impl Reader +where + S: ReaderSegments, +{ + pub fn new(segments: S, options: ReaderOptions) -> Self { + Self { + arena: ReaderArenaImpl::new(segments, options), + } + } + + fn get_root_internal(&self) -> Result> { + let (segment_start, _seg_len) = self.arena.get_segment(0)?; + let pointer_reader = layout::PointerReader::get_root( + &self.arena, + 0, + segment_start, + self.arena.nesting_limit(), + )?; + Ok(any_pointer::Reader::new(pointer_reader)) + } + + /// Gets the root of the message, interpreting it as the given type. + pub fn get_root<'a, T: FromPointerReader<'a>>(&'a self) -> Result { + self.get_root_internal()?.get_as() + } + + pub fn into_segments(self) -> S { + self.arena.into_segments() + } + + /// Checks whether the message is [canonical](https://capnproto.org/encoding.html#canonicalization). + pub fn is_canonical(&self) -> Result { + let (segment_start, seg_len) = self.arena.get_segment(0)?; + + if self.arena.get_segment(1).is_ok() { + // TODO(cleanup, apibump): should there be a nicer way to ask the arena how many + // segments there are? + + // There is more than one segment, so the message cannot be canonical. + return Ok(false); + } + + let pointer_reader = layout::PointerReader::get_root( + &self.arena, + 0, + segment_start, + self.arena.nesting_limit(), + )?; + let read_head = ::core::cell::Cell::new(unsafe { segment_start.add(BYTES_PER_WORD) }); + let root_is_canonical = pointer_reader.is_canonical(&read_head)?; + let all_words_consumed = (read_head.get() as usize - segment_start as usize) + / BYTES_PER_WORD + == seg_len as usize; + Ok(root_is_canonical && all_words_consumed) + } + + /// Gets the [canonical](https://capnproto.org/encoding.html#canonicalization) form + /// of this message. Works by copying the message twice. For a canonicalization + /// method that only requires one copy, see `message::Builder::set_root_canonical()`. + #[cfg(feature = "alloc")] + pub fn canonicalize(&self) -> Result> { + let root = self.get_root_internal()?; + let size = root.target_size()?.word_count + 1; + let mut message = Builder::new(HeapAllocator::new().first_segment_words(size as u32)); + message.set_root_canonical(root)?; + let output_segments = message.get_segments_for_output(); + assert_eq!(1, output_segments.len()); + let output = output_segments[0]; + assert!((output.len() / BYTES_PER_WORD) as u64 <= size); + let mut result = crate::Word::allocate_zeroed_vec(output.len() / BYTES_PER_WORD); + crate::Word::words_to_bytes_mut(&mut result[..]).copy_from_slice(output); + Ok(result) + } + + pub fn into_typed(self) -> TypedReader { + TypedReader::new(self) + } +} + +/// A message reader whose value is known to be of type `T`. +/// Please see [module documentation](self) for more info about reader type specialization. +pub struct TypedReader +where + S: ReaderSegments, + T: Owned, +{ + marker: ::core::marker::PhantomData, + message: Reader, +} + +impl TypedReader +where + S: ReaderSegments, + T: Owned, +{ + pub fn new(message: Reader) -> Self { + Self { + marker: ::core::marker::PhantomData, + message, + } + } + + pub fn get(&self) -> Result> { + self.message.get_root() + } + + pub fn into_inner(self) -> Reader { + self.message + } +} + +impl From> for TypedReader +where + S: ReaderSegments, + T: Owned, +{ + fn from(message: Reader) -> Self { + Self::new(message) + } +} + +#[cfg(feature = "alloc")] +impl From> for TypedReader, T> +where + A: Allocator, + T: Owned, +{ + fn from(message: Builder) -> Self { + let reader = message.into_reader(); + reader.into_typed() + } +} + +#[cfg(feature = "alloc")] +impl From> for TypedReader, T> +where + A: Allocator, + T: Owned, +{ + fn from(builder: TypedBuilder) -> Self { + builder.into_reader() + } +} + +/// An object that allocates memory for a Cap'n Proto message as it is being built. +/// Users of capnproto-rust who wish to provide memory in non-standard ways should +/// implement this trait. Objects implementing this trait are intended to be wrapped +/// by `capnp::private::BuilderArena`, which handles calling the methods at the appropriate +/// times, including calling `deallocate_segment()` on drop. +/// +/// # Safety +/// Implementions must ensure all of the following: +/// 1. The memory returned by `allocate_segment` is initialized to all zeroes. +/// 2. The memory returned by `allocate_segment` is valid until `deallocate_segment()` +/// is called on it. +/// 3. The allocated memory does not overlap with other allocated memory. +/// 4. The allocated memory is 8-byte aligned (or the "unaligned" feature is enabled +/// for the capnp crate). +pub unsafe trait Allocator { + /// Allocates zeroed memory for a new segment, returning a pointer to the start of the segment + /// and a u32 indicating the length of the segment in words. The allocated segment must be + /// at least `minimum_size` words long (`minimum_size * 8` bytes long). Allocator implementations + /// commonly allocate much more than the minimum, to reduce the total number of segments needed. + /// A reasonable strategy is to allocate the maximum of `minimum_size` and twice the size of the + /// previous segment. + fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32); + + /// Indicates that a segment, previously allocated via allocate_segment(), is no longer in use. + /// `word_size` is the length of the segment in words, as returned from `allocate_segment()`. + /// `words_used` is always less than or equal to `word_size`, and indicates how many + /// words (contiguous from the start of the segment) were possibly written with non-zero values. + /// + /// # Safety + /// Callers must only call this method on a pointer that has previously been been returned + /// from `allocate_segment()`, and only once on each such segment. `word_size` must + /// equal the word size returned from `allocate_segment()`, and `words_used` must be at + /// most `word_size`. + unsafe fn deallocate_segment(&mut self, ptr: *mut u8, word_size: u32, words_used: u32); +} + +/// A container used to build a message. +#[cfg(feature = "alloc")] +pub struct Builder +where + A: Allocator, +{ + arena: BuilderArenaImpl, +} + +#[cfg(feature = "alloc")] +unsafe impl Send for Builder where A: Send + Allocator {} + +#[cfg(feature = "alloc")] +fn _assert_kinds() { + fn _assert_send() {} + fn _assert_reader() { + _assert_send::>(); + } + fn _assert_builder() { + _assert_send::>(); + } +} + +#[cfg(feature = "alloc")] +impl Builder +where + A: Allocator, +{ + pub fn new(allocator: A) -> Self { + Self { + arena: BuilderArenaImpl::new(allocator), + } + } + + fn get_root_internal(&mut self) -> any_pointer::Builder<'_> { + if self.arena.is_empty() { + self.arena + .allocate_segment(1) + .expect("allocate root pointer"); + self.arena.allocate(0, 1).expect("allocate root pointer"); + } + let (seg_start, _seg_len) = self.arena.get_segment_mut(0); + let location: *mut u8 = seg_start; + let Self { arena } = self; + + any_pointer::Builder::new(layout::PointerBuilder::get_root(arena, 0, location)) + } + + /// Initializes the root as a value of the given type. + pub fn init_root<'a, T: FromPointerBuilder<'a>>(&'a mut self) -> T { + let root = self.get_root_internal(); + root.init_as() + } + + /// Initializes the root as a value of the given list type, with the given length. + pub fn initn_root<'a, T: FromPointerBuilder<'a>>(&'a mut self, length: u32) -> T { + let root = self.get_root_internal(); + root.initn_as(length) + } + + /// Gets the root, interpreting it as the given type. + pub fn get_root<'a, T: FromPointerBuilder<'a>>(&'a mut self) -> Result { + let root = self.get_root_internal(); + root.get_as() + } + + pub fn get_root_as_reader<'a, T: FromPointerReader<'a>>(&'a self) -> Result { + if self.arena.is_empty() { + any_pointer::Reader::new(layout::PointerReader::new_default()).get_as() + } else { + let (segment_start, _segment_len) = self.arena.get_segment(0)?; + let pointer_reader = layout::PointerReader::get_root( + self.arena.as_reader(), + 0, + segment_start, + 0x7fffffff, + )?; + let root = any_pointer::Reader::new(pointer_reader); + root.get_as() + } + } + + /// Sets the root to a deep copy of the given value. + pub fn set_root(&mut self, value: From) -> Result<()> { + let mut root = self.get_root_internal(); + root.set_as(value) + } + + /// Sets the root to a canonicalized version of `value`. If this was the first action taken + /// on this `Builder`, then a subsequent call to `get_segments_for_output()` should return + /// a single segment, containing the full canonicalized message. + pub fn set_root_canonical(&mut self, value: From) -> Result<()> { + if self.arena.is_empty() { + self.arena + .allocate_segment(1) + .expect("allocate root pointer"); + self.arena.allocate(0, 1).expect("allocate root pointer"); + } + let (seg_start, _seg_len) = self.arena.get_segment_mut(0); + let pointer = layout::PointerBuilder::get_root(&mut self.arena, 0, seg_start); + SetPointerBuilder::set_pointer_builder(pointer, value, true)?; + assert_eq!(self.get_segments_for_output().len(), 1); + Ok(()) + } + + pub fn get_segments_for_output(&self) -> OutputSegments { + self.arena.get_segments_for_output() + } + + pub fn into_reader(self) -> Reader { + Reader::new( + self, + ReaderOptions { + traversal_limit_in_words: None, + nesting_limit: i32::max_value(), + }, + ) + } + + pub fn into_typed(self) -> TypedBuilder { + TypedBuilder::new(self) + } + + /// Retrieves the underlying `Allocator`, deallocating all currently-allocated + /// segments. + pub fn into_allocator(self) -> A { + self.arena.into_allocator() + } +} + +#[cfg(feature = "alloc")] +impl ReaderSegments for Builder +where + A: Allocator, +{ + fn get_segment(&self, id: u32) -> Option<&[u8]> { + self.get_segments_for_output().get(id as usize).copied() + } + + fn len(&self) -> usize { + self.get_segments_for_output().len() + } +} + +/// Stongly typed variant of the [Builder] +/// +/// Generic type parameters: +/// - `T` - type of the capnp message which this builder is specialized on. Please see +/// [module documentation](self) for more info about builder type specialization. +/// - `A` - type of allocator +#[cfg(feature = "alloc")] +pub struct TypedBuilder +where + T: Owned, + A: Allocator, +{ + marker: ::core::marker::PhantomData, + message: Builder, +} + +#[cfg(feature = "alloc")] +impl TypedBuilder +where + T: Owned, +{ + pub fn new_default() -> Self { + Self::new(Builder::new_default()) + } +} + +#[cfg(feature = "alloc")] +impl TypedBuilder +where + T: Owned, + A: Allocator, +{ + pub fn new(message: Builder) -> Self { + Self { + marker: ::core::marker::PhantomData, + message, + } + } + + pub fn init_root(&mut self) -> T::Builder<'_> { + self.message.init_root() + } + + pub fn initn_root(&mut self, length: u32) -> T::Builder<'_> { + self.message.initn_root(length) + } + + pub fn get_root(&mut self) -> Result> { + self.message.get_root() + } + + pub fn get_root_as_reader(&self) -> Result> { + self.message.get_root_as_reader() + } + + pub fn set_root(&mut self, value: T::Reader<'_>) -> Result<()> { + self.message.set_root(value) + } + + pub fn into_inner(self) -> Builder { + self.message + } + + pub fn borrow_inner(&self) -> &Builder { + &self.message + } + + pub fn borrow_inner_mut(&mut self) -> &mut Builder { + &mut self.message + } + + pub fn into_reader(self) -> TypedReader, T> { + TypedReader::new(self.message.into_reader()) + } +} + +#[cfg(feature = "alloc")] +impl From> for TypedBuilder +where + T: Owned, + A: Allocator, +{ + fn from(builder: Builder) -> Self { + Self::new(builder) + } +} + +/// Standard segment allocator. Allocates each segment via `alloc::alloc::alloc_zeroed()`. +#[derive(Debug)] +#[cfg(feature = "alloc")] +pub struct HeapAllocator { + // Minimum number of words in the next allocation. + next_size: u32, + + // How to update next_size after an allocation. + allocation_strategy: AllocationStrategy, + + // Maximum number of words to allocate. + max_segment_words: u32, +} + +#[derive(Clone, Copy, Debug)] +pub enum AllocationStrategy { + /// Allocates the same number of words for each segment, to the extent possible. + /// This strategy is primarily useful for testing cross-segment pointers. + FixedSize, + + /// Increases segment size by a multiplicative factor for each subsequent segment. + GrowHeuristically, +} + +pub const SUGGESTED_FIRST_SEGMENT_WORDS: u32 = 1024; +pub const SUGGESTED_ALLOCATION_STRATEGY: AllocationStrategy = AllocationStrategy::GrowHeuristically; + +#[cfg(feature = "alloc")] +impl Default for HeapAllocator { + fn default() -> Self { + Self { + next_size: SUGGESTED_FIRST_SEGMENT_WORDS, + allocation_strategy: SUGGESTED_ALLOCATION_STRATEGY, + max_segment_words: 1 << 29, + } + } +} + +#[cfg(feature = "alloc")] +impl HeapAllocator { + pub fn new() -> Self { + Self::default() + } + + /// Sets the size of the initial segment in words, where 1 word = 8 bytes. + pub fn first_segment_words(mut self, value: u32) -> Self { + assert!(value <= self.max_segment_words); + self.next_size = value; + self + } + + /// Sets the allocation strategy for segments after the first one. + pub fn allocation_strategy(mut self, value: AllocationStrategy) -> Self { + self.allocation_strategy = value; + self + } + + /// Sets the maximum number of words allowed in a single allocation. + pub fn max_segment_words(mut self, value: u32) -> Self { + assert!(self.next_size <= value); + self.max_segment_words = value; + self + } +} + +#[cfg(feature = "alloc")] +unsafe impl Allocator for HeapAllocator { + fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) { + let size = core::cmp::max(minimum_size, self.next_size); + let layout = + alloc::alloc::Layout::from_size_align(size as usize * BYTES_PER_WORD, 8).unwrap(); + let ptr = unsafe { alloc::alloc::alloc_zeroed(layout) }; + if ptr.is_null() { + alloc::alloc::handle_alloc_error(layout); + } + match self.allocation_strategy { + AllocationStrategy::GrowHeuristically => { + if size < self.max_segment_words - self.next_size { + self.next_size += size; + } else { + self.next_size = self.max_segment_words; + } + } + AllocationStrategy::FixedSize => {} + } + (ptr, size) + } + + unsafe fn deallocate_segment(&mut self, ptr: *mut u8, word_size: u32, _words_used: u32) { + unsafe { + alloc::alloc::dealloc( + ptr, + alloc::alloc::Layout::from_size_align(word_size as usize * BYTES_PER_WORD, 8) + .unwrap(), + ); + } + self.next_size = SUGGESTED_FIRST_SEGMENT_WORDS; + } +} + +#[cfg(feature = "alloc")] +#[test] +fn test_allocate_max() { + let allocation_size = 1 << 24; + let mut allocator = HeapAllocator::new() + .max_segment_words((1 << 25) - 1) + .first_segment_words(allocation_size); + + let (a1, s1) = allocator.allocate_segment(allocation_size); + let (a2, s2) = allocator.allocate_segment(allocation_size); + let (a3, s3) = allocator.allocate_segment(allocation_size); + + assert_eq!(s1, allocation_size); + + // Allocation size tops out at max_segment_words. + assert_eq!(s2, allocator.max_segment_words); + assert_eq!(s3, allocator.max_segment_words); + + unsafe { + allocator.deallocate_segment(a1, s1, 0); + allocator.deallocate_segment(a2, s2, 0); + allocator.deallocate_segment(a3, s3, 0); + } +} + +#[cfg(feature = "alloc")] +impl Builder { + /// Constructs a new `message::Builder` whose first segment has length + /// `SUGGESTED_FIRST_SEGMENT_WORDS`. + pub fn new_default() -> Self { + Self::new(HeapAllocator::new()) + } +} + +/// An Allocator whose first segment is a backed by a user-provided buffer. +/// +/// Recall that an `Allocator` implementation must ensure that allocated segments are +/// initially *zeroed*. `ScratchSpaceHeapAllocator` ensures that is the case by zeroing +/// the entire buffer upon initial construction, and then zeroing any *potentially used* +/// part of the buffer upon `deallocate_segment()`. +/// +/// You can reuse a `ScratchSpaceHeapAllocator` by calling `message::Builder::into_allocator()`, +/// or by initally passing it to `message::Builder::new()` as a `&mut ScratchSpaceHeapAllocator`. +/// Such reuse can save significant amounts of zeroing. +#[cfg(feature = "alloc")] +pub struct ScratchSpaceHeapAllocator<'a> { + scratch_space: &'a mut [u8], + scratch_space_allocated: bool, + allocator: HeapAllocator, +} + +#[cfg(feature = "alloc")] +impl<'a> ScratchSpaceHeapAllocator<'a> { + /// Writes zeroes into the entire buffer and constructs a new allocator from it. + /// + /// If the buffer is large, this operation could be relatively expensive. If you want to reuse + /// the same scratch space in a later message, you should reuse the entire + /// `ScratchSpaceHeapAllocator`, to avoid paying this full cost again. + pub fn new(scratch_space: &'a mut [u8]) -> ScratchSpaceHeapAllocator<'a> { + #[cfg(not(feature = "unaligned"))] + { + if scratch_space.as_ptr() as usize % BYTES_PER_WORD != 0 { + panic!( + "Scratch space must be 8-byte aligned, or you must enable the \"unaligned\" \ + feature in the capnp crate" + ); + } + } + + // We need to ensure that the buffer is zeroed. + for b in &mut scratch_space[..] { + *b = 0; + } + ScratchSpaceHeapAllocator { + scratch_space, + scratch_space_allocated: false, + allocator: HeapAllocator::new(), + } + } + + /// Sets the size of the second segment in words, where 1 word = 8 bytes. + /// (The first segment is the scratch space passed to `ScratchSpaceHeapAllocator::new()`. + pub fn second_segment_words(self, value: u32) -> ScratchSpaceHeapAllocator<'a> { + ScratchSpaceHeapAllocator { + allocator: self.allocator.first_segment_words(value), + ..self + } + } + + /// Sets the allocation strategy for segments after the second one. + pub fn allocation_strategy(self, value: AllocationStrategy) -> ScratchSpaceHeapAllocator<'a> { + ScratchSpaceHeapAllocator { + allocator: self.allocator.allocation_strategy(value), + ..self + } + } +} + +#[cfg(feature = "alloc")] +unsafe impl<'a> Allocator for ScratchSpaceHeapAllocator<'a> { + fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) { + if (minimum_size as usize) < (self.scratch_space.len() / BYTES_PER_WORD) + && !self.scratch_space_allocated + { + self.scratch_space_allocated = true; + ( + self.scratch_space.as_mut_ptr(), + (self.scratch_space.len() / BYTES_PER_WORD) as u32, + ) + } else { + self.allocator.allocate_segment(minimum_size) + } + } + + unsafe fn deallocate_segment(&mut self, ptr: *mut u8, word_size: u32, words_used: u32) { + if ptr == self.scratch_space.as_mut_ptr() { + // Rezero the slice to allow reuse of the allocator. We only need to write + // words that we know might contain nonzero values. + unsafe { + core::ptr::write_bytes(ptr, 0u8, (words_used as usize) * BYTES_PER_WORD); + } + self.scratch_space_allocated = false; + } else { + self.allocator + .deallocate_segment(ptr, word_size, words_used); + } + } +} + +#[cfg(feature = "alloc")] +unsafe impl<'a, A> Allocator for &'a mut A +where + A: Allocator, +{ + fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) { + (*self).allocate_segment(minimum_size) + } + + unsafe fn deallocate_segment(&mut self, ptr: *mut u8, word_size: u32, words_used: u32) { + (*self).deallocate_segment(ptr, word_size, words_used) + } +} diff --git a/rust/capnp/primitive_list.rs b/rust/capnp/primitive_list.rs new file mode 100644 index 000000000000..4ea31a7b50eb --- /dev/null +++ b/rust/capnp/primitive_list.rs @@ -0,0 +1,279 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of primitives. + +use core::marker; + +use crate::introspect; +use crate::private::layout::{ + data_bits_per_element, ListBuilder, ListReader, PointerBuilder, PointerReader, PrimitiveElement, +}; +use crate::traits::{FromPointerBuilder, FromPointerReader, IndexMove, ListIter}; +use crate::Result; + +#[derive(Clone, Copy)] +pub struct Owned { + marker: marker::PhantomData, +} + +impl introspect::Introspect for Owned +where + T: introspect::Introspect, +{ + fn introspect() -> introspect::Type { + introspect::Type::list_of(T::introspect()) + } +} + +impl crate::traits::Owned for Owned +where + T: PrimitiveElement + introspect::Introspect, +{ + type Reader<'a> = Reader<'a, T>; + type Builder<'a> = Builder<'a, T>; +} + +#[derive(Clone, Copy)] +pub struct Reader<'a, T> +where + T: PrimitiveElement, +{ + marker: marker::PhantomData, + reader: ListReader<'a>, +} + +impl<'a, T: PrimitiveElement> Reader<'a, T> { + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, T> { + let l = self.len(); + ListIter::new(self, l) + } +} + +impl<'a, T: PrimitiveElement> FromPointerReader<'a> for Reader<'a, T> { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(T::element_size(), default)?, + marker: marker::PhantomData, + }) + } +} + +impl<'a, T: PrimitiveElement> IndexMove for Reader<'a, T> { + fn index_move(&self, index: u32) -> T { + self.get(index) + } +} + +impl<'a, T: PrimitiveElement> Reader<'a, T> { + /// Gets the `T` at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(&self, index: u32) -> T { + assert!(index < self.len()); + PrimitiveElement::get(&self.reader, index) + } + + /// Gets the `T` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(&self, index: u32) -> Option { + if index < self.len() { + Some(PrimitiveElement::get(&self.reader, index)) + } else { + None + } + } + + #[cfg(target_endian = "little")] + /// Returns something if the slice is as expected in memory. + pub fn as_slice(&self) -> Option<&[T]> { + if self.reader.get_element_size() == T::element_size() { + let bytes = self.reader.into_raw_bytes(); + Some(unsafe { + use core::slice; + slice::from_raw_parts( + bytes.as_ptr() as *mut T, + 8 * bytes.len() / (data_bits_per_element(T::element_size())) as usize, + ) + }) + } else { + None + } + } +} + +impl<'a, T> crate::traits::IntoInternalListReader<'a> for Reader<'a, T> +where + T: PrimitiveElement, +{ + fn into_internal_list_reader(self) -> ListReader<'a> { + self.reader + } +} + +pub struct Builder<'a, T> +where + T: PrimitiveElement, +{ + marker: marker::PhantomData, + builder: ListBuilder<'a>, +} + +impl<'a, T> Builder<'a, T> +where + T: PrimitiveElement, +{ + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn into_reader(self) -> Reader<'a, T> { + Reader { + marker: marker::PhantomData, + reader: self.builder.into_reader(), + } + } + + pub fn set(&mut self, index: u32, value: T) { + assert!(index < self.len()); + PrimitiveElement::set(&self.builder, index, value); + } + + #[cfg(target_endian = "little")] + pub fn as_slice(&mut self) -> Option<&mut [T]> { + if self.builder.get_element_size() == T::element_size() { + let bytes = self.builder.into_raw_bytes(); + Some(unsafe { + core::slice::from_raw_parts_mut( + bytes.as_mut_ptr() as *mut T, + 8 * bytes.len() / (data_bits_per_element(T::element_size())) as usize, + ) + }) + } else { + None + } + } +} + +impl<'a, T: PrimitiveElement> FromPointerBuilder<'a> for Builder<'a, T> { + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a, T> { + Builder { + builder: builder.init_list(T::element_size(), size), + marker: marker::PhantomData, + } + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + builder: builder.get_list(T::element_size(), default)?, + marker: marker::PhantomData, + }) + } +} + +impl<'a, T: PrimitiveElement> Builder<'a, T> { + /// Gets the `T` at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(&self, index: u32) -> T { + assert!(index < self.len()); + PrimitiveElement::get_from_builder(&self.builder, index) + } + + /// Gets the `T` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(&self, index: u32) -> Option { + if index < self.len() { + Some(PrimitiveElement::get_from_builder(&self.builder, index)) + } else { + None + } + } + + pub fn reborrow(&mut self) -> Builder<'_, T> { + Builder { + marker: marker::PhantomData, + builder: self.builder.reborrow(), + } + } +} + +impl<'a, T> crate::traits::SetPointerBuilder for Reader<'a, T> +where + T: PrimitiveElement, +{ + fn set_pointer_builder<'b>( + mut pointer: PointerBuilder<'b>, + value: Reader<'a, T>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize) + } +} + +impl<'a, T> ::core::iter::IntoIterator for Reader<'a, T> +where + T: PrimitiveElement, +{ + type Item = T; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T: PrimitiveElement + crate::introspect::Introspect> From> + for crate::dynamic_value::Reader<'a> +{ + fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( + t.reader, + T::introspect(), + )) + } +} + +impl<'a, T: PrimitiveElement + crate::introspect::Introspect> From> + for crate::dynamic_value::Builder<'a> +{ + fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( + t.builder, + T::introspect(), + )) + } +} diff --git a/rust/capnp/private/arena.rs b/rust/capnp/private/arena.rs new file mode 100644 index 000000000000..46626c1f0ce3 --- /dev/null +++ b/rust/capnp/private/arena.rs @@ -0,0 +1,417 @@ +// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +#[cfg(feature = "alloc")] +use core::slice; +use core::u64; + +use crate::message; +#[cfg(feature = "alloc")] +use crate::message::Allocator; +use crate::message::ReaderSegments; +use crate::private::read_limiter::ReadLimiter; +use crate::private::units::*; +#[cfg(feature = "alloc")] +use crate::OutputSegments; +use crate::{Error, ErrorKind, Result}; + +pub type SegmentId = u32; + +pub trait ReaderArena { + // return pointer to start of segment, and number of words in that segment + fn get_segment(&self, id: u32) -> Result<(*const u8, u32)>; + + unsafe fn check_offset( + &self, + segment_id: u32, + start: *const u8, + offset_in_words: i32, + ) -> Result<*const u8>; + fn contains_interval(&self, segment_id: u32, start: *const u8, size: usize) -> Result<()>; + fn amplified_read(&self, virtual_amount: u64) -> Result<()>; + + fn nesting_limit(&self) -> i32; + + // TODO(apibump): Consider putting extract_cap(), inject_cap(), drop_cap() here + // and on message::Reader. Then we could get rid of Imbue and ImbueMut, and + // layout::StructReader, layout::ListReader, etc. could drop their `cap_table` fields. +} + +pub struct ReaderArenaImpl { + segments: S, + read_limiter: ReadLimiter, + nesting_limit: i32, +} + +#[cfg(feature = "sync_reader")] +fn _assert_sync() { + fn _assert_sync() {} + fn _assert_reader() { + _assert_sync::>(); + } +} + +impl ReaderArenaImpl +where + S: ReaderSegments, +{ + pub fn new(segments: S, options: message::ReaderOptions) -> Self { + let limiter = ReadLimiter::new(options.traversal_limit_in_words); + Self { + segments, + read_limiter: limiter, + nesting_limit: options.nesting_limit, + } + } + + pub fn into_segments(self) -> S { + self.segments + } +} + +impl ReaderArena for ReaderArenaImpl +where + S: ReaderSegments, +{ + fn get_segment(&self, id: u32) -> Result<(*const u8, u32)> { + match self.segments.get_segment(id) { + Some(seg) => { + #[cfg(not(feature = "unaligned"))] + { + if seg.as_ptr() as usize % BYTES_PER_WORD != 0 { + return Err(Error::from_kind(ErrorKind::UnalignedSegment)); + } + } + + Ok((seg.as_ptr(), (seg.len() / BYTES_PER_WORD) as u32)) + } + None => Err(Error::from_kind(ErrorKind::InvalidSegmentId(id))), + } + } + + unsafe fn check_offset( + &self, + segment_id: u32, + start: *const u8, + offset_in_words: i32, + ) -> Result<*const u8> { + let (segment_start, segment_len) = self.get_segment(segment_id)?; + let this_start: usize = segment_start as usize; + let this_size: usize = segment_len as usize * BYTES_PER_WORD; + let offset: i64 = i64::from(offset_in_words) * BYTES_PER_WORD as i64; + let start_idx = start as usize; + if start_idx < this_start || ((start_idx - this_start) as i64 + offset) as usize > this_size + { + Err(Error::from_kind( + ErrorKind::MessageContainsOutOfBoundsPointer, + )) + } else { + unsafe { Ok(start.offset(offset as isize)) } + } + } + + fn contains_interval(&self, id: u32, start: *const u8, size_in_words: usize) -> Result<()> { + let (segment_start, segment_len) = self.get_segment(id)?; + let this_start: usize = segment_start as usize; + let this_size: usize = segment_len as usize * BYTES_PER_WORD; + let start = start as usize; + let size = size_in_words * BYTES_PER_WORD; + + if !(start >= this_start && start - this_start + size <= this_size) { + Err(Error::from_kind( + ErrorKind::MessageContainsOutOfBoundsPointer, + )) + } else { + self.read_limiter.can_read(size_in_words) + } + } + + fn amplified_read(&self, virtual_amount: u64) -> Result<()> { + self.read_limiter.can_read(virtual_amount as usize) + } + + fn nesting_limit(&self) -> i32 { + self.nesting_limit + } +} + +pub trait BuilderArena: ReaderArena { + fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option; + fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32); + fn get_segment_mut(&mut self, id: u32) -> (*mut u8, u32); + + fn as_reader(&self) -> &dyn ReaderArena; +} + +/// A wrapper around a memory segment used in building a message. +#[cfg(feature = "alloc")] +struct BuilderSegment { + /// Pointer to the start of the segment. + ptr: *mut u8, + + /// Total number of words the segment could potentially use. That is, all + /// bytes from `ptr` to `ptr + (capacity * 8)` may be used in the segment. + capacity: u32, + + /// Number of words already used in the segment. + allocated: u32, +} + +#[cfg(feature = "alloc")] +pub struct BuilderArenaImplInner +where + A: Allocator, +{ + allocator: Option, // None if has already be deallocated. + + // TODO(perf): Try using smallvec to avoid heap allocations in the single-segment case? + segments: Vec, +} + +#[cfg(feature = "alloc")] +pub struct BuilderArenaImpl +where + A: Allocator, +{ + inner: BuilderArenaImplInner, +} + +#[cfg(feature = "alloc")] +impl BuilderArenaImpl +where + A: Allocator, +{ + pub fn new(allocator: A) -> Self { + Self { + inner: BuilderArenaImplInner { + allocator: Some(allocator), + segments: Vec::new(), + }, + } + } + + /// Allocates a new segment with capacity for at least `minimum_size` words. + pub fn allocate_segment(&mut self, minimum_size: u32) -> Result<()> { + self.inner.allocate_segment(minimum_size) + } + + pub fn get_segments_for_output(&self) -> OutputSegments { + let reff = &self.inner; + if reff.segments.len() == 1 { + let seg = &reff.segments[0]; + + // The user must mutably borrow the `message::Builder` to be able to modify segment memory. + // No such borrow will be possible while `self` is still immutably borrowed from this method, + // so returning this slice is safe. + let slice = unsafe { + slice::from_raw_parts(seg.ptr as *const _, seg.allocated as usize * BYTES_PER_WORD) + }; + OutputSegments::SingleSegment([slice]) + } else { + let mut v = Vec::with_capacity(reff.segments.len()); + for seg in &reff.segments { + // See safety argument in above branch. + let slice = unsafe { + slice::from_raw_parts( + seg.ptr as *const _, + seg.allocated as usize * BYTES_PER_WORD, + ) + }; + v.push(slice); + } + OutputSegments::MultiSegment(v) + } + } + + pub fn len(&self) -> usize { + self.inner.segments.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Retrieves the underlying `Allocator`, deallocating all currently-allocated + /// segments. + pub fn into_allocator(mut self) -> A { + self.inner.deallocate_all(); + self.inner.allocator.take().unwrap() + } +} + +#[cfg(feature = "alloc")] +impl ReaderArena for BuilderArenaImpl +where + A: Allocator, +{ + fn get_segment(&self, id: u32) -> Result<(*const u8, u32)> { + let seg = &self.inner.segments[id as usize]; + Ok((seg.ptr, seg.allocated)) + } + + unsafe fn check_offset( + &self, + _segment_id: u32, + start: *const u8, + offset_in_words: i32, + ) -> Result<*const u8> { + unsafe { Ok(start.offset((i64::from(offset_in_words) * BYTES_PER_WORD as i64) as isize)) } + } + + fn contains_interval(&self, _id: u32, _start: *const u8, _size: usize) -> Result<()> { + Ok(()) + } + + fn amplified_read(&self, _virtual_amount: u64) -> Result<()> { + Ok(()) + } + + fn nesting_limit(&self) -> i32 { + 0x7fffffff + } +} + +#[cfg(feature = "alloc")] +impl BuilderArenaImplInner +where + A: Allocator, +{ + /// Allocates a new segment with capacity for at least `minimum_size` words. + fn allocate_segment(&mut self, minimum_size: WordCount32) -> Result<()> { + let seg = match &mut self.allocator { + Some(a) => a.allocate_segment(minimum_size), + None => unreachable!(), + }; + self.segments.push(BuilderSegment { + ptr: seg.0, + capacity: seg.1, + allocated: 0, + }); + Ok(()) + } + + fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option { + let seg = &mut self.segments[segment_id as usize]; + if amount > seg.capacity - seg.allocated { + None + } else { + let result = seg.allocated; + seg.allocated += amount; + Some(result) + } + } + + fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32) { + // first try the existing segments, then try allocating a new segment. + let allocated_len = self.segments.len() as u32; + for segment_id in 0..allocated_len { + if let Some(idx) = self.allocate(segment_id, amount) { + return (segment_id, idx); + } + } + + // Need to allocate a new segment. + + self.allocate_segment(amount).expect("allocate new segment"); + ( + allocated_len, + self.allocate(allocated_len, amount) + .expect("use freshly-allocated segment"), + ) + } + + fn deallocate_all(&mut self) { + if let Some(a) = &mut self.allocator { + for seg in &self.segments { + unsafe { + a.deallocate_segment(seg.ptr, seg.capacity, seg.allocated); + } + } + } + } + + fn get_segment_mut(&mut self, id: u32) -> (*mut u8, u32) { + let seg = &self.segments[id as usize]; + (seg.ptr, seg.capacity) + } +} + +#[cfg(feature = "alloc")] +impl BuilderArena for BuilderArenaImpl +where + A: Allocator, +{ + fn allocate(&mut self, segment_id: u32, amount: WordCount32) -> Option { + self.inner.allocate(segment_id, amount) + } + + fn allocate_anywhere(&mut self, amount: u32) -> (SegmentId, u32) { + self.inner.allocate_anywhere(amount) + } + + fn get_segment_mut(&mut self, id: u32) -> (*mut u8, u32) { + self.inner.get_segment_mut(id) + } + + fn as_reader(&self) -> &dyn ReaderArena { + self + } +} + +#[cfg(feature = "alloc")] +impl Drop for BuilderArenaImplInner +where + A: Allocator, +{ + fn drop(&mut self) { + self.deallocate_all() + } +} + +pub struct NullArena; + +impl ReaderArena for NullArena { + fn get_segment(&self, _id: u32) -> Result<(*const u8, u32)> { + Err(Error::from_kind(ErrorKind::TriedToReadFromNullArena)) + } + + unsafe fn check_offset( + &self, + _segment_id: u32, + start: *const u8, + offset_in_words: i32, + ) -> Result<*const u8> { + unsafe { Ok(start.add(offset_in_words as usize * BYTES_PER_WORD)) } + } + + fn contains_interval(&self, _id: u32, _start: *const u8, _size: usize) -> Result<()> { + Ok(()) + } + + fn amplified_read(&self, _virtual_amount: u64) -> Result<()> { + Ok(()) + } + + fn nesting_limit(&self) -> i32 { + 0x7fffffff + } +} diff --git a/rust/capnp/private/capability.rs b/rust/capnp/private/capability.rs new file mode 100644 index 000000000000..ba725fb60535 --- /dev/null +++ b/rust/capnp/private/capability.rs @@ -0,0 +1,155 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#![cfg(feature = "alloc")] +use alloc::boxed::Box; +use alloc::vec::Vec; + +use crate::any_pointer; +use crate::capability::{Params, Promise, RemotePromise, Request, Results}; +use crate::MessageSize; + +pub trait ResponseHook { + fn get(&self) -> crate::Result>; +} + +pub trait RequestHook { + fn get(&mut self) -> any_pointer::Builder<'_>; + fn get_brand(&self) -> usize; + fn send(self: Box) -> RemotePromise; + fn tail_send( + self: Box, + ) -> Option<( + u32, + crate::capability::Promise<(), crate::Error>, + Box, + )>; +} + +pub trait ClientHook { + fn add_ref(&self) -> Box; + fn new_call( + &self, + interface_id: u64, + method_id: u16, + size_hint: Option, + ) -> Request; + + fn call( + &self, + interface_id: u64, + method_id: u16, + params: Box, + results: Box, + ) -> crate::capability::Promise<(), crate::Error>; + + /// If this capability is associated with an rpc connection, then this method + /// returns an identifier for that connection. + fn get_brand(&self) -> usize; + + /// Returns a (locally) unique identifier for this capabilitiy. + fn get_ptr(&self) -> usize; + + /// If this ClientHook is a promise that has already resolved, returns the inner, resolved version + /// of the capability. The caller may permanently replace this client with the resolved one if + /// desired. Returns null if the client isn't a promise or hasn't resolved yet -- use + /// `whenMoreResolved()` to distinguish between them. + fn get_resolved(&self) -> Option>; + + /// If this client is a settled reference (not a promise), return nullptr. Otherwise, return a + /// promise that eventually resolves to a new client that is closer to being the final, settled + /// client (i.e. the value eventually returned by `getResolved()`). Calling this repeatedly + /// should eventually produce a settled client. + fn when_more_resolved( + &self, + ) -> Option, crate::Error>>; + + /// Repeatedly calls whenMoreResolved() until it returns nullptr. + fn when_resolved(&self) -> Promise<(), crate::Error>; +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.add_ref() + } +} + +pub trait ResultsHook { + fn get(&mut self) -> crate::Result>; + fn allow_cancellation(&self); + fn tail_call(self: Box, request: Box) -> Promise<(), crate::Error>; + fn direct_tail_call( + self: Box, + request: Box, + ) -> ( + crate::capability::Promise<(), crate::Error>, + Box, + ); +} + +pub trait ParamsHook { + fn get(&self) -> crate::Result>; +} + +// Where should this live? +pub fn internal_get_typed_params(typeless: Params) -> Params { + Params { + hook: typeless.hook, + marker: ::core::marker::PhantomData, + } +} + +pub fn internal_get_typed_results(typeless: Results) -> Results { + Results { + hook: typeless.hook, + marker: ::core::marker::PhantomData, + } +} + +pub fn internal_get_untyped_results(typeful: Results) -> Results { + Results { + hook: typeful.hook, + marker: ::core::marker::PhantomData, + } +} + +pub trait PipelineHook { + fn add_ref(&self) -> Box; + fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box; + + /// Version of get_pipelined_cap() passing the array by move. May avoid a copy in some cases. + /// Default implementation just calls the other version. + fn get_pipelined_cap_move(&self, ops: Vec) -> Box { + self.get_pipelined_cap(&ops) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.add_ref() + } +} + +#[derive(Clone, Copy)] +pub enum PipelineOp { + Noop, + GetPointerField(u16), +} diff --git a/rust/capnp/private/layout.rs b/rust/capnp/private/layout.rs new file mode 100644 index 000000000000..02ecb6e7bfb5 --- /dev/null +++ b/rust/capnp/private/layout.rs @@ -0,0 +1,4210 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, vec::Vec}; +use core::cell::Cell; +use core::mem; +use core::ptr; + +use crate::data; +use crate::private::arena::{BuilderArena, NullArena, ReaderArena, SegmentId}; +#[cfg(feature = "alloc")] +use crate::private::capability::ClientHook; +use crate::private::mask::Mask; +use crate::private::primitive::{Primitive, WireValue}; +use crate::private::units::*; +use crate::private::zero; +use crate::text; +use crate::{Error, ErrorKind, MessageSize, Result}; + +pub use self::ElementSize::{ + Bit, Byte, EightBytes, FourBytes, InlineComposite, Pointer, TwoBytes, Void, +}; + +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum ElementSize { + Void = 0, + Bit = 1, + Byte = 2, + TwoBytes = 3, + FourBytes = 4, + EightBytes = 5, + Pointer = 6, + InlineComposite = 7, +} + +impl ElementSize { + fn from(val: u8) -> Self { + match val { + 0 => Self::Void, + 1 => Self::Bit, + 2 => Self::Byte, + 3 => Self::TwoBytes, + 4 => Self::FourBytes, + 5 => Self::EightBytes, + 6 => Self::Pointer, + 7 => Self::InlineComposite, + _ => panic!("illegal element size: {val}"), + } + } +} + +pub fn data_bits_per_element(size: ElementSize) -> BitCount32 { + match size { + Void => 0, + Bit => 1, + Byte => 8, + TwoBytes => 16, + FourBytes => 32, + EightBytes => 64, + Pointer => 0, + InlineComposite => 0, + } +} + +pub fn pointers_per_element(size: ElementSize) -> WirePointerCount32 { + match size { + Pointer => 1, + _ => 0, + } +} + +#[derive(Clone, Copy, Debug)] +pub struct StructSize { + pub data: WordCount16, + pub pointers: WirePointerCount16, +} + +impl StructSize { + pub fn total(&self) -> WordCount32 { + u32::from(self.data) + u32::from(self.pointers) * WORDS_PER_POINTER as WordCount32 + } +} + +#[repr(u8)] +#[derive(Clone, Copy, PartialEq)] +pub enum WirePointerKind { + Struct = 0, + List = 1, + Far = 2, + Other = 3, +} + +pub enum PointerType { + Null, + Struct, + List, + Capability, +} + +impl WirePointerKind { + fn from(val: u8) -> Self { + match val { + 0 => Self::Struct, + 1 => Self::List, + 2 => Self::Far, + 3 => Self::Other, + _ => panic!("illegal element size: {val}"), + } + } +} + +#[repr(C)] +pub struct WirePointer { + offset_and_kind: WireValue, + upper32bits: WireValue, +} + +#[test] +#[cfg(feature = "unaligned")] +fn wire_pointer_align() { + // We cast *u8 to *WirePointer, so we need to make sure its alignment allows that. + assert_eq!(core::mem::align_of::(), 1); +} + +impl WirePointer { + #[inline] + pub fn kind(&self) -> WirePointerKind { + WirePointerKind::from(self.offset_and_kind.get() as u8 & 3) + } + + #[inline] + pub fn is_positional(&self) -> bool { + (self.offset_and_kind.get() & 2) == 0 // match Struct and List but not Far and Other. + } + + #[inline] + pub fn is_capability(&self) -> bool { + self.offset_and_kind.get() == WirePointerKind::Other as u32 + } + + #[inline] + pub unsafe fn target(ptr: *const Self) -> *const u8 { + let this_addr: *const u8 = ptr as *const _; + unsafe { this_addr.offset(8 * (1 + (((*ptr).offset_and_kind.get() as i32) >> 2)) as isize) } + } + + // At one point, we had `&self` here instead of `ptr: *const Self`, but miri + // flagged that as running afoul of "stacked borrow" rules. + #[inline] + fn target_from_segment( + ptr: *const Self, + arena: &dyn ReaderArena, + segment_id: u32, + ) -> Result<*const u8> { + let this_addr: *const u8 = ptr as *const _; + unsafe { + let offset = 1 + (((*ptr).offset_and_kind.get() as i32) >> 2); + arena.check_offset(segment_id, this_addr, offset) + } + } + + // At one point, we had `&mut self` here instead of `ptr: *mut Self`, but miri + // flagged that as running afoul of "stacked borrow" rules. + #[inline] + fn mut_target(ptr: *mut Self) -> *mut u8 { + let this_addr: *mut u8 = ptr as *mut _; + unsafe { + this_addr.wrapping_offset( + BYTES_PER_WORD as isize + * (1 + (((*ptr).offset_and_kind.get() as i32) >> 2)) as isize, + ) + } + } + + #[inline] + pub fn set_kind_and_target(&mut self, kind: WirePointerKind, target: *mut u8) { + let this_addr: isize = self as *const _ as isize; + let target_addr: isize = target as *const _ as isize; + self.offset_and_kind.set( + ((((target_addr - this_addr) / BYTES_PER_WORD as isize) as i32 - 1) << 2) as u32 + | (kind as u32), + ) + } + + #[inline] + pub fn set_kind_with_zero_offset(&mut self, kind: WirePointerKind) { + self.offset_and_kind.set(kind as u32) + } + + #[inline] + pub fn set_kind_and_target_for_empty_struct(&mut self) { + //# This pointer points at an empty struct. Assuming the + //# WirePointer itself is in-bounds, we can set the target to + //# point either at the WirePointer itself or immediately after + //# it. The latter would cause the WirePointer to be "null" + //# (since for an empty struct the upper 32 bits are going to + //# be zero). So we set an offset of -1, as if the struct were + //# allocated immediately before this pointer, to distinguish + //# it from null. + + self.offset_and_kind.set(0xfffffffc); + } + + #[inline] + pub fn inline_composite_list_element_count(&self) -> ElementCount32 { + self.offset_and_kind.get() >> 2 + } + + #[inline] + pub fn set_kind_and_inline_composite_list_element_count( + &mut self, + kind: WirePointerKind, + element_count: ElementCount32, + ) { + self.offset_and_kind + .set((element_count << 2) | (kind as u32)) + } + + #[inline] + pub fn far_position_in_segment(&self) -> WordCount32 { + self.offset_and_kind.get() >> 3 + } + + #[inline] + pub fn is_double_far(&self) -> bool { + ((self.offset_and_kind.get() >> 2) & 1) != 0 + } + + #[inline] + pub fn set_far(&mut self, is_double_far: bool, pos: WordCount32) { + self.offset_and_kind + .set((pos << 3) | (u32::from(is_double_far) << 2) | WirePointerKind::Far as u32); + } + + #[inline] + pub fn set_cap(&mut self, index: u32) { + self.offset_and_kind.set(WirePointerKind::Other as u32); + self.upper32bits.set(index); + } + + #[inline] + pub fn struct_data_size(&self) -> WordCount16 { + self.upper32bits.get() as WordCount16 + } + + #[inline] + pub fn struct_ptr_count(&self) -> WordCount16 { + (self.upper32bits.get() >> 16) as WordCount16 + } + + #[inline] + pub fn struct_word_size(&self) -> WordCount32 { + u32::from(self.struct_data_size()) + + u32::from(self.struct_ptr_count()) * WORDS_PER_POINTER as u32 + } + + #[inline] + pub fn set_struct_size(&mut self, size: StructSize) { + self.upper32bits + .set(u32::from(size.data) | (u32::from(size.pointers) << 16)) + } + + #[inline] + pub fn set_struct_size_from_pieces(&mut self, ds: WordCount16, rc: WirePointerCount16) { + self.set_struct_size(StructSize { + data: ds, + pointers: rc, + }) + } + + #[inline] + pub fn list_element_size(&self) -> ElementSize { + ElementSize::from(self.upper32bits.get() as u8 & 7) + } + + #[inline] + pub fn list_element_count(&self) -> ElementCount32 { + self.upper32bits.get() >> 3 + } + + #[inline] + pub fn list_inline_composite_word_count(&self) -> WordCount32 { + self.list_element_count() + } + + #[inline] + pub fn set_list_size_and_count(&mut self, es: ElementSize, ec: ElementCount32) { + assert!(ec < (1 << 29), "Lists are limited to 2**29 elements"); + self.upper32bits.set((ec << 3) | (es as u32)); + } + + #[inline] + pub fn set_list_inline_composite(&mut self, wc: WordCount32) { + assert!( + wc < (1 << 29), + "Inline composite lists are limited to 2**29 words" + ); + self.upper32bits.set((wc << 3) | (InlineComposite as u32)); + } + + #[inline] + pub fn far_segment_id(&self) -> SegmentId { + self.upper32bits.get() as SegmentId + } + + #[inline] + pub fn set_far_segment_id(&mut self, si: SegmentId) { + self.upper32bits.set(si) + } + + #[inline] + pub fn cap_index(&self) -> u32 { + self.upper32bits.get() + } + + #[inline] + pub fn set_cap_index(&mut self, index: u32) { + self.upper32bits.set(index) + } + + #[inline] + pub fn is_null(&self) -> bool { + self.offset_and_kind.get() == 0 && self.upper32bits.get() == 0 + } +} + +mod wire_helpers { + #[cfg(feature = "alloc")] + use alloc::boxed::Box; + use core::{ptr, slice}; + + use crate::data; + use crate::private::arena::*; + #[cfg(feature = "alloc")] + use crate::private::capability::ClientHook; + use crate::private::layout::ElementSize::*; + use crate::private::layout::{data_bits_per_element, pointers_per_element}; + use crate::private::layout::{CapTableBuilder, CapTableReader}; + use crate::private::layout::{ + ElementSize, ListBuilder, ListReader, StructBuilder, StructReader, StructSize, WirePointer, + WirePointerKind, + }; + use crate::private::units::*; + use crate::text; + use crate::{Error, ErrorKind, MessageSize, Result}; + + pub struct SegmentAnd { + #[allow(dead_code)] + segment_id: u32, + pub value: T, + } + + #[inline] + pub fn round_bytes_up_to_words(bytes: ByteCount32) -> WordCount32 { + //# This code assumes 64-bit words. + (bytes + 7) / BYTES_PER_WORD as u32 + } + + //# The maximum object size is 4GB - 1 byte. If measured in bits, + //# this would overflow a 32-bit counter, so we need to accept + //# BitCount64. However, 32 bits is enough for the returned + //# ByteCounts and WordCounts. + #[inline] + pub fn round_bits_up_to_words(bits: BitCount64) -> WordCount32 { + //# This code assumes 64-bit words. + ((bits + 63) / (BITS_PER_WORD as u64)) as WordCount32 + } + + #[allow(dead_code)] + #[inline] + pub fn round_bits_up_to_bytes(bits: BitCount64) -> ByteCount32 { + ((bits + 7) / (BITS_PER_BYTE as u64)) as ByteCount32 + } + + #[inline] + pub fn bounds_check( + arena: &dyn ReaderArena, + segment_id: u32, + start: *const u8, + size_in_words: usize, + _kind: WirePointerKind, + ) -> Result<()> { + arena.contains_interval(segment_id, start, size_in_words) + } + + #[inline] + pub fn amplified_read(arena: &dyn ReaderArena, virtual_amount: u64) -> Result<()> { + arena.amplified_read(virtual_amount) + } + + #[inline] + pub unsafe fn allocate( + arena: &mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + amount: WordCount32, + kind: WirePointerKind, + ) -> (*mut u8, *mut WirePointer, u32) { + let is_null = (*reff).is_null(); + if !is_null { + zero_object(arena, segment_id, reff) + } + + if amount == 0 && kind == WirePointerKind::Struct { + (*reff).set_kind_and_target_for_empty_struct(); + return (reff as *mut _, reff, segment_id); + } + + match arena.allocate(segment_id, amount) { + None => { + //# Need to allocate in a different segment. We'll need to + //# allocate an extra pointer worth of space to act as + //# the landing pad for a far pointer. + + let amount_plus_ref = amount + POINTER_SIZE_IN_WORDS as u32; + let (segment_id, word_idx) = arena.allocate_anywhere(amount_plus_ref); + let (seg_start, _seg_len) = arena.get_segment_mut(segment_id); + let ptr = seg_start.offset(word_idx as isize * BYTES_PER_WORD as isize); + + //# Set up the original pointer to be a far pointer to + //# the new segment. + (*reff).set_far(false, word_idx); + (*reff).set_far_segment_id(segment_id); + + //# Initialize the landing pad to indicate that the + //# data immediately follows the pad. + let reff = ptr as *mut WirePointer; + + let ptr1 = ptr.add(BYTES_PER_WORD); + (*reff).set_kind_and_target(kind, ptr1); + (ptr1, reff, segment_id) + } + Some(idx) => { + let (seg_start, _seg_len) = arena.get_segment_mut(segment_id); + let ptr = (seg_start).offset(idx as isize * BYTES_PER_WORD as isize); + (*reff).set_kind_and_target(kind, ptr); + (ptr, reff, segment_id) + } + } + } + + #[inline] + pub unsafe fn follow_builder_fars( + arena: &mut dyn BuilderArena, + reff: *mut WirePointer, + ref_target: *mut u8, + segment_id: u32, + ) -> Result<(*mut u8, *mut WirePointer, u32)> { + // If `ref` is a far pointer, follow it. On return, `ref` will have been updated to point at + // a WirePointer that contains the type information about the target object, and a pointer + // to the object contents is returned. The caller must NOT use `ref->target()` as this may + // or may not actually return a valid pointer. `segment` is also updated to point at the + // segment which actually contains the object. + // + // If `ref` is not a far pointer, this simply returns `ref_target`. Usually, `ref_target` + // should be the same as `ref->target()`, but may not be in cases where `ref` is only a tag. + + if (*reff).kind() == WirePointerKind::Far { + let segment_id = (*reff).far_segment_id(); + let (seg_start, _seg_len) = arena.get_segment_mut(segment_id); + let pad: *mut WirePointer = + (seg_start as *mut WirePointer).offset((*reff).far_position_in_segment() as isize); + if !(*reff).is_double_far() { + Ok((WirePointer::mut_target(pad), pad, segment_id)) + } else { + //# Landing pad is another far pointer. It is followed by a + //# tag describing the pointed-to object. + let reff = pad.offset(1); + + let segment_id = (*pad).far_segment_id(); + let (segment_start, _segment_len) = arena.get_segment_mut(segment_id); + let ptr = segment_start + .offset((*pad).far_position_in_segment() as isize * BYTES_PER_WORD as isize); + Ok((ptr, reff, segment_id)) + } + } else { + Ok((ref_target, reff, segment_id)) + } + } + + /// Follows a WirePointer to get a triple containing: + /// - the pointed-to object + /// - the resolved WirePointer, whose kind is something other than WirePointerKind::Far + /// - the segment on which the pointed-to object lives + #[inline] + pub unsafe fn follow_fars( + arena: &dyn ReaderArena, + reff: *const WirePointer, + segment_id: u32, + ) -> Result<(*const u8, *const WirePointer, u32)> { + if (*reff).kind() == WirePointerKind::Far { + let far_segment_id = (*reff).far_segment_id(); + + let (seg_start, _seg_len) = arena.get_segment(far_segment_id)?; + let ptr = seg_start + .offset((*reff).far_position_in_segment() as isize * BYTES_PER_WORD as isize); + + let pad_words: usize = if (*reff).is_double_far() { 2 } else { 1 }; + bounds_check(arena, far_segment_id, ptr, pad_words, WirePointerKind::Far)?; + + let pad: *const WirePointer = ptr as *const _; + + if !(*reff).is_double_far() { + Ok(( + WirePointer::target_from_segment(pad, arena, far_segment_id)?, + pad, + far_segment_id, + )) + } else { + // Landing pad is another far pointer. It is followed by a tag describing the + // pointed-to object. + + let tag = pad.offset(1); + let double_far_segment_id = (*pad).far_segment_id(); + let (segment_start, _segment_len) = arena.get_segment(double_far_segment_id)?; + let ptr = segment_start + .offset((*pad).far_position_in_segment() as isize * BYTES_PER_WORD as isize); + Ok((ptr, tag, double_far_segment_id)) + } + } else { + Ok(( + WirePointer::target_from_segment(reff, arena, segment_id)?, + reff, + segment_id, + )) + } + } + + pub unsafe fn zero_object( + arena: &mut dyn BuilderArena, + segment_id: u32, + reff: *mut WirePointer, + ) { + //# Zero out the pointed-to object. Use when the pointer is + //# about to be overwritten making the target object no longer + //# reachable. + + match (*reff).kind() { + WirePointerKind::Struct | WirePointerKind::List | WirePointerKind::Other => { + zero_object_helper(arena, segment_id, reff, WirePointer::mut_target(reff)) + } + WirePointerKind::Far => { + let segment_id = (*reff).far_segment_id(); + let (seg_start, _seg_len) = arena.get_segment_mut(segment_id); + let pad: *mut WirePointer = (seg_start as *mut WirePointer) + .offset((*reff).far_position_in_segment() as isize); + + if (*reff).is_double_far() { + let segment_id = (*pad).far_segment_id(); + + let (seg_start, _seg_len) = arena.get_segment_mut(segment_id); + let ptr = seg_start.offset( + (*pad).far_position_in_segment() as isize * BYTES_PER_WORD as isize, + ); + zero_object_helper(arena, segment_id, pad.offset(1), ptr); + + ptr::write_bytes(pad, 0u8, 2); + } else { + zero_object(arena, segment_id, pad); + ptr::write_bytes(pad, 0u8, 1); + } + } + } + } + + pub unsafe fn zero_object_helper( + arena: &mut dyn BuilderArena, + segment_id: u32, + tag: *mut WirePointer, + ptr: *mut u8, + ) { + match (*tag).kind() { + WirePointerKind::Other => { + panic!("Don't know how to handle OTHER") + } + WirePointerKind::Struct => { + let pointer_section: *mut WirePointer = ptr + .offset((*tag).struct_data_size() as isize * BYTES_PER_WORD as isize) + as *mut _; + + let count = (*tag).struct_ptr_count() as isize; + for i in 0..count { + zero_object(arena, segment_id, pointer_section.offset(i)); + } + ptr::write_bytes( + ptr, + 0u8, + (*tag).struct_word_size() as usize * BYTES_PER_WORD, + ); + } + WirePointerKind::List => match (*tag).list_element_size() { + Void => {} + Bit | Byte | TwoBytes | FourBytes | EightBytes => ptr::write_bytes( + ptr, + 0u8, + BYTES_PER_WORD + * round_bits_up_to_words( + u64::from((*tag).list_element_count()) + * u64::from(data_bits_per_element((*tag).list_element_size())), + ) as usize, + ), + Pointer => { + let count = (*tag).list_element_count() as usize; + for i in 0..count as isize { + zero_object( + arena, + segment_id, + ptr.offset(i * BYTES_PER_WORD as isize) as *mut _, + ); + } + ptr::write_bytes(ptr, 0u8, count * BYTES_PER_WORD); + } + InlineComposite => { + let element_tag: *mut WirePointer = ptr as *mut _; + + assert!( + (*element_tag).kind() == WirePointerKind::Struct, + "Don't know how to handle non-STRUCT inline composite" + ); + + let data_size = (*element_tag).struct_data_size(); + let pointer_count = (*element_tag).struct_ptr_count(); + let mut pos = ptr.add(BYTES_PER_WORD); + let count = (*element_tag).inline_composite_list_element_count(); + if pointer_count > 0 { + for _ in 0..count { + pos = pos.offset(data_size as isize * BYTES_PER_WORD as isize); + for _ in 0..pointer_count { + zero_object(arena, segment_id, pos as *mut WirePointer); + pos = pos.add(BYTES_PER_WORD); + } + } + } + ptr::write_bytes( + ptr, + 0u8, + BYTES_PER_WORD * ((*element_tag).struct_word_size() * count + 1) as usize, + ); + } + }, + WirePointerKind::Far => { + panic!("Unexpected FAR pointer") + } + } + } + + #[inline] + pub unsafe fn zero_pointer_and_fars( + arena: &mut dyn BuilderArena, + _segment_id: u32, + reff: *mut WirePointer, + ) -> Result<()> { + // Zero out the pointer itself and, if it is a far pointer, zero the landing pad as well, + // but do not zero the object body. Used when upgrading. + + if (*reff).kind() == WirePointerKind::Far { + let far_segment_id = (*reff).far_segment_id(); + let (seg_start, _seg_len) = arena.get_segment_mut(far_segment_id); + let pad = seg_start + .offset((*reff).far_position_in_segment() as isize * BYTES_PER_WORD as isize); + let num_elements = if (*reff).is_double_far() { 2 } else { 1 }; + ptr::write_bytes(pad, 0, num_elements * BYTES_PER_WORD); + } + ptr::write_bytes(reff, 0, 1); + Ok(()) + } + + pub unsafe fn total_size( + arena: &dyn ReaderArena, + segment_id: u32, + reff: *const WirePointer, + mut nesting_limit: i32, + ) -> Result { + let mut result = MessageSize { + word_count: 0, + cap_count: 0, + }; + + if (*reff).is_null() { + return Ok(result); + }; + + if nesting_limit <= 0 { + return Err(Error::from_kind(ErrorKind::MessageIsTooDeeplyNested)); + } + + nesting_limit -= 1; + + let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?; + + match (*reff).kind() { + WirePointerKind::Struct => { + bounds_check( + arena, + segment_id, + ptr, + (*reff).struct_word_size() as usize, + WirePointerKind::Struct, + )?; + result.word_count += u64::from((*reff).struct_word_size()); + + let pointer_section: *const WirePointer = ptr + .offset((*reff).struct_data_size() as isize * BYTES_PER_WORD as isize) + as *const _; + let count: isize = (*reff).struct_ptr_count() as isize; + for i in 0..count { + result += + total_size(arena, segment_id, pointer_section.offset(i), nesting_limit)?; + } + } + WirePointerKind::List => { + match (*reff).list_element_size() { + Void => {} + Bit | Byte | TwoBytes | FourBytes | EightBytes => { + let total_words = round_bits_up_to_words( + u64::from((*reff).list_element_count()) + * u64::from(data_bits_per_element((*reff).list_element_size())), + ); + bounds_check( + arena, + segment_id, + ptr, + total_words as usize, + WirePointerKind::List, + )?; + result.word_count += u64::from(total_words); + } + Pointer => { + let count = (*reff).list_element_count(); + bounds_check( + arena, + segment_id, + ptr, + count as usize * WORDS_PER_POINTER, + WirePointerKind::List, + )?; + + result.word_count += u64::from(count) * WORDS_PER_POINTER as u64; + + for i in 0..count as isize { + result += total_size( + arena, + segment_id, + (ptr as *const WirePointer).offset(i), + nesting_limit, + )?; + } + } + InlineComposite => { + let word_count = (*reff).list_inline_composite_word_count(); + bounds_check( + arena, + segment_id, + ptr, + word_count as usize + POINTER_SIZE_IN_WORDS, + WirePointerKind::List, + )?; + + let element_tag: *const WirePointer = ptr as *const _; + let count = (*element_tag).inline_composite_list_element_count(); + + if (*element_tag).kind() != WirePointerKind::Struct { + return Err(Error::from_kind( + ErrorKind::CantHandleNonStructInlineComposite, + )); + } + + let actual_size = + u64::from((*element_tag).struct_word_size()) * u64::from(count); + if actual_size > u64::from(word_count) { + return Err(Error::from_kind( + ErrorKind::InlineCompositeListsElementsOverrunItsWordCount, + )); + } + + // Count the actual size rather than the claimed word count because + // that's what we end up with if we make a copy. + result.word_count += actual_size + POINTER_SIZE_IN_WORDS as u64; + + let data_size = (*element_tag).struct_data_size(); + let pointer_count = (*element_tag).struct_ptr_count(); + + if pointer_count > 0 { + let mut pos = ptr.add(BYTES_PER_WORD); + for _ in 0..count { + pos = pos.offset(data_size as isize * BYTES_PER_WORD as isize); + + for _ in 0..pointer_count { + result += total_size( + arena, + segment_id, + pos as *const WirePointer, + nesting_limit, + )?; + pos = pos.add(BYTES_PER_WORD); + } + } + } + } + } + } + WirePointerKind::Far => { + return Err(Error::from_kind(ErrorKind::MalformedDoubleFarPointer)); + } + WirePointerKind::Other => { + if (*reff).is_capability() { + result.cap_count += 1; + } else { + return Err(Error::from_kind(ErrorKind::UnknownPointerType)); + } + } + } + + Ok(result) + } + + // Helper for copy_message(). + unsafe fn copy_struct( + arena: &mut dyn BuilderArena, + segment_id: u32, + cap_table: CapTableBuilder, + dst: *mut u8, + src: *const u8, + data_size: isize, + pointer_count: isize, + ) { + ptr::copy_nonoverlapping(src, dst, data_size as usize * BYTES_PER_WORD); + + let src_refs: *const WirePointer = (src as *const WirePointer).offset(data_size); + let dst_refs: *mut WirePointer = (dst as *mut WirePointer).offset(data_size); + + for ii in 0..pointer_count { + copy_message( + arena, + segment_id, + cap_table, + dst_refs.offset(ii), + src_refs.offset(ii), + ); + } + } + + // Copies from a trusted message. + // Returns (new_dst_ptr, new_dst, new_segment_id). + pub unsafe fn copy_message( + arena: &mut dyn BuilderArena, + segment_id: u32, + cap_table: CapTableBuilder, + dst: *mut WirePointer, + src: *const WirePointer, + ) -> (*mut u8, *mut WirePointer, u32) { + match (*src).kind() { + WirePointerKind::Struct => { + if (*src).is_null() { + ptr::write_bytes(dst, 0, 1); + (ptr::null_mut(), dst, segment_id) + } else { + let src_ptr = WirePointer::target(src); + let (dst_ptr, dst, segment_id) = allocate( + arena, + dst, + segment_id, + (*src).struct_word_size(), + WirePointerKind::Struct, + ); + copy_struct( + arena, + segment_id, + cap_table, + dst_ptr, + src_ptr, + (*src).struct_data_size() as isize, + (*src).struct_ptr_count() as isize, + ); + (*dst).set_struct_size_from_pieces( + (*src).struct_data_size(), + (*src).struct_ptr_count(), + ); + (dst_ptr, dst, segment_id) + } + } + WirePointerKind::List => match (*src).list_element_size() { + ElementSize::Void + | ElementSize::Bit + | ElementSize::Byte + | ElementSize::TwoBytes + | ElementSize::FourBytes + | ElementSize::EightBytes => { + let word_count = round_bits_up_to_words( + u64::from((*src).list_element_count()) + * u64::from(data_bits_per_element((*src).list_element_size())), + ); + let src_ptr = WirePointer::target(src); + let (dst_ptr, dst, segment_id) = + allocate(arena, dst, segment_id, word_count, WirePointerKind::List); + ptr::copy_nonoverlapping( + src_ptr, + dst_ptr, + word_count as usize * BYTES_PER_WORD, + ); + (*dst).set_list_size_and_count( + (*src).list_element_size(), + (*src).list_element_count(), + ); + (dst_ptr, dst, segment_id) + } + + ElementSize::Pointer => { + let src_refs: *const WirePointer = WirePointer::target(src) as _; + let (dst_refs, dst, segment_id) = allocate( + arena, + dst, + segment_id, + (*src).list_element_count(), + WirePointerKind::List, + ); + for ii in 0..((*src).list_element_count() as isize) { + copy_message( + arena, + segment_id, + cap_table, + dst_refs.offset(ii * BYTES_PER_WORD as isize) as *mut WirePointer, + src_refs.offset(ii), + ); + } + (*dst) + .set_list_size_and_count(ElementSize::Pointer, (*src).list_element_count()); + (dst_refs, dst, segment_id) + } + ElementSize::InlineComposite => { + let src_ptr = WirePointer::target(src); + let (dst_ptr, dst, segment_id) = allocate( + arena, + dst, + segment_id, + (*src).list_inline_composite_word_count() + 1, + WirePointerKind::List, + ); + + (*dst).set_list_inline_composite((*src).list_inline_composite_word_count()); + + let src_tag: *const WirePointer = src_ptr as _; + ptr::copy_nonoverlapping(src_tag, dst_ptr as *mut WirePointer, 1); + + let mut src_element = src_ptr.add(BYTES_PER_WORD); + let mut dst_element = dst_ptr.add(BYTES_PER_WORD); + + if (*src_tag).kind() != WirePointerKind::Struct { + panic!("unsupported INLINE_COMPOSITE list"); + } + for _ in 0..(*src_tag).inline_composite_list_element_count() { + copy_struct( + arena, + segment_id, + cap_table, + dst_element, + src_element, + (*src_tag).struct_data_size() as isize, + (*src_tag).struct_ptr_count() as isize, + ); + src_element = src_element.offset( + BYTES_PER_WORD as isize * (*src_tag).struct_word_size() as isize, + ); + dst_element = dst_element.offset( + BYTES_PER_WORD as isize * (*src_tag).struct_word_size() as isize, + ); + } + (dst_ptr, dst, segment_id) + } + }, + WirePointerKind::Other => { + panic!("Unchecked message contained an OTHER pointer.") + } + WirePointerKind::Far => { + panic!("Unchecked message contained a far pointer.") + } + } + } + + pub unsafe fn transfer_pointer( + arena: &mut dyn BuilderArena, + dst_segment_id: u32, + dst: *mut WirePointer, + src_segment_id: u32, + src: *mut WirePointer, + ) { + //# Make *dst point to the same object as *src. Both must + //# reside in the same message, but can be in different + //# segments. Not always-inline because this is rarely used. + // + //# Caller MUST zero out the source pointer after calling this, + //# to make sure no later code mistakenly thinks the source + //# location still owns the object. transferPointer() doesn't + //# do this zeroing itself because many callers transfer + //# several pointers in a loop then zero out the whole section. + + assert!((*dst).is_null()); + // We expect the caller to ensure the target is already null so won't leak. + + if (*src).is_null() { + ptr::write_bytes(dst, 0, 1); + } else if (*src).is_positional() { + transfer_pointer_split( + arena, + dst_segment_id, + dst, + src_segment_id, + src, + WirePointer::mut_target(src), + ); + } else { + ptr::copy_nonoverlapping(src, dst, 1); + } + } + + pub unsafe fn transfer_pointer_split( + arena: &mut dyn BuilderArena, + dst_segment_id: u32, + dst: *mut WirePointer, + src_segment_id: u32, + src_tag: *mut WirePointer, + src_ptr: *mut u8, + ) { + // Like the other transfer_pointer, but splits src into a tag and a + // target. Particularly useful for OrphanBuilder. + + if dst_segment_id == src_segment_id { + // Same segment, so create a direct pointer. + + if (*src_tag).kind() == WirePointerKind::Struct && (*src_tag).struct_word_size() == 0 { + (*dst).set_kind_and_target_for_empty_struct(); + } else { + (*dst).set_kind_and_target((*src_tag).kind(), src_ptr); + } + // We can just copy the upper 32 bits. (Use memcpy() to comply with aliasing rules.) + ptr::copy_nonoverlapping(&(*src_tag).upper32bits, &mut (*dst).upper32bits, 1); + } else { + // Need to create a far pointer. Try to allocate it in the same segment as the source, + // so that it doesn't need to be a double-far. + + match arena.allocate(src_segment_id, 1) { + None => { + //# Darn, need a double-far. + let (far_segment_id, word_idx) = arena.allocate_anywhere(2); + let (seg_start, _seg_len) = arena.get_segment_mut(far_segment_id); + let landing_pad: *mut WirePointer = + (seg_start as *mut WirePointer).offset(word_idx as isize); + + let (src_seg_start, _seg_len) = arena.get_segment_mut(src_segment_id); + + (*landing_pad).set_far( + false, + ((src_ptr as usize - src_seg_start as usize) / BYTES_PER_WORD) as u32, + ); + (*landing_pad).set_far_segment_id(src_segment_id); + + let landing_pad1 = landing_pad.offset(1); + (*landing_pad1).set_kind_with_zero_offset((*src_tag).kind()); + + ptr::copy_nonoverlapping( + &(*src_tag).upper32bits, + &mut (*landing_pad1).upper32bits, + 1, + ); + + (*dst).set_far(true, word_idx); + (*dst).set_far_segment_id(far_segment_id); + } + Some(landing_pad_word) => { + //# Simple landing pad is just a pointer. + let (seg_start, seg_len) = arena.get_segment_mut(src_segment_id); + assert!(landing_pad_word < seg_len); + let landing_pad: *mut WirePointer = + (seg_start as *mut WirePointer).offset(landing_pad_word as isize); + (*landing_pad).set_kind_and_target((*src_tag).kind(), src_ptr); + ptr::copy_nonoverlapping( + &(*src_tag).upper32bits, + &mut (*landing_pad).upper32bits, + 1, + ); + + (*dst).set_far(false, landing_pad_word); + (*dst).set_far_segment_id(src_segment_id); + } + } + } + } + + #[inline] + pub unsafe fn init_struct_pointer( + arena: &mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + cap_table: CapTableBuilder, + size: StructSize, + ) -> StructBuilder<'_> { + let (ptr, reff, segment_id) = allocate( + arena, + reff, + segment_id, + size.total(), + WirePointerKind::Struct, + ); + (*reff).set_struct_size(size); + + StructBuilder { + arena, + segment_id, + cap_table, + data: ptr as *mut _, + pointers: ptr.offset((size.data as usize) as isize * BYTES_PER_WORD as isize) as *mut _, + data_size: u32::from(size.data) * (BITS_PER_WORD as BitCount32), + pointer_count: size.pointers, + } + } + + #[inline] + pub unsafe fn get_writable_struct_pointer<'a>( + arena: &'a mut dyn BuilderArena, + mut reff: *mut WirePointer, + mut segment_id: u32, + cap_table: CapTableBuilder, + size: StructSize, + default: Option<&'a [crate::Word]>, + ) -> Result> { + let mut ref_target = WirePointer::mut_target(reff); + + if (*reff).is_null() { + match default { + None => { + return Ok(init_struct_pointer( + arena, reff, segment_id, cap_table, size, + )) + } + Some(d) if (*(d.as_ptr() as *const WirePointer)).is_null() => { + return Ok(init_struct_pointer( + arena, reff, segment_id, cap_table, size, + )) + } + Some(d) => { + let (new_ref_target, new_reff, new_segment_id) = copy_message( + arena, + segment_id, + cap_table, + reff, + d.as_ptr() as *const WirePointer, + ); + reff = new_reff; + segment_id = new_segment_id; + ref_target = new_ref_target; + } + } + } + + let (old_ptr, old_ref, old_segment_id) = + follow_builder_fars(arena, reff, ref_target, segment_id)?; + if (*old_ref).kind() != WirePointerKind::Struct { + return Err(Error::from_kind( + ErrorKind::MessageContainsNonStructPointerWhereStructPointerWasExpected, + )); + } + + let old_data_size = (*old_ref).struct_data_size(); + let old_pointer_count = (*old_ref).struct_ptr_count(); + let old_pointer_section: *mut WirePointer = + old_ptr.offset(old_data_size as isize * BYTES_PER_WORD as isize) as *mut _; + + if old_data_size < size.data || old_pointer_count < size.pointers { + //# The space allocated for this struct is too small. + //# Unlike with readers, we can't just run with it and do + //# bounds checks at access time, because how would we + //# handle writes? Instead, we have to copy the struct to a + //# new space now. + + let new_data_size = ::core::cmp::max(old_data_size, size.data); + let new_pointer_count = ::core::cmp::max(old_pointer_count, size.pointers); + let total_size = + u32::from(new_data_size) + u32::from(new_pointer_count) * WORDS_PER_POINTER as u32; + + //# Don't let allocate() zero out the object just yet. + zero_pointer_and_fars(arena, segment_id, reff)?; + + let (ptr, reff, segment_id) = + allocate(arena, reff, segment_id, total_size, WirePointerKind::Struct); + (*reff).set_struct_size_from_pieces(new_data_size, new_pointer_count); + + // Copy data section. + // Note: copy_nonoverlapping's third argument is an element count, not a byte count. + ptr::copy_nonoverlapping(old_ptr, ptr, old_data_size as usize * BYTES_PER_WORD); + + //# Copy pointer section. + let new_pointer_section: *mut WirePointer = + ptr.offset(new_data_size as isize * BYTES_PER_WORD as isize) as *mut _; + for i in 0..old_pointer_count as isize { + transfer_pointer( + arena, + segment_id, + new_pointer_section.offset(i), + old_segment_id, + old_pointer_section.offset(i), + ); + } + + ptr::write_bytes( + old_ptr, + 0, + (old_data_size as usize + old_pointer_count as usize) * BYTES_PER_WORD, + ); + + Ok(StructBuilder { + arena, + segment_id, + cap_table, + data: ptr as *mut _, + pointers: new_pointer_section, + data_size: u32::from(new_data_size) * BITS_PER_WORD as u32, + pointer_count: new_pointer_count, + }) + } else { + Ok(StructBuilder { + arena, + segment_id: old_segment_id, + cap_table, + data: old_ptr, + pointers: old_pointer_section, + data_size: u32::from(old_data_size) * BITS_PER_WORD as u32, + pointer_count: old_pointer_count, + }) + } + } + + #[inline] + pub unsafe fn init_list_pointer( + arena: &mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + cap_table: CapTableBuilder, + element_count: ElementCount32, + element_size: ElementSize, + ) -> ListBuilder<'_> { + assert!( + element_size != InlineComposite, + "Should have called initStructListPointer() instead" + ); + + let data_size = data_bits_per_element(element_size); + let pointer_count = pointers_per_element(element_size); + let step = data_size + pointer_count * BITS_PER_POINTER as u32; + let word_count = round_bits_up_to_words(u64::from(element_count) * u64::from(step)); + let (ptr, reff, segment_id) = + allocate(arena, reff, segment_id, word_count, WirePointerKind::List); + + (*reff).set_list_size_and_count(element_size, element_count); + + ListBuilder { + arena, + segment_id, + cap_table, + ptr, + step, + element_count, + element_size, + struct_data_size: data_size, + struct_pointer_count: pointer_count as u16, + } + } + + #[inline] + pub unsafe fn init_struct_list_pointer( + arena: &mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + cap_table: CapTableBuilder, + element_count: ElementCount32, + element_size: StructSize, + ) -> ListBuilder<'_> { + let words_per_element = element_size.total(); + + //# Allocate the list, prefixed by a single WirePointer. + let word_count: WordCount32 = element_count * words_per_element; + let (ptr, reff, segment_id) = allocate( + arena, + reff, + segment_id, + POINTER_SIZE_IN_WORDS as u32 + word_count, + WirePointerKind::List, + ); + let ptr = ptr as *mut WirePointer; + + //# Initialize the pointer. + (*reff).set_list_inline_composite(word_count); + (*ptr).set_kind_and_inline_composite_list_element_count( + WirePointerKind::Struct, + element_count, + ); + (*ptr).set_struct_size(element_size); + + let ptr1 = ptr.add(POINTER_SIZE_IN_WORDS); + + ListBuilder { + arena, + segment_id, + cap_table, + ptr: ptr1 as *mut _, + step: words_per_element * BITS_PER_WORD as u32, + element_count, + element_size: ElementSize::InlineComposite, + struct_data_size: u32::from(element_size.data) * (BITS_PER_WORD as u32), + struct_pointer_count: element_size.pointers, + } + } + + #[inline] + pub unsafe fn get_writable_list_pointer( + arena: &mut dyn BuilderArena, + mut orig_ref: *mut WirePointer, + mut orig_segment_id: u32, + cap_table: CapTableBuilder, + element_size: ElementSize, + default_value: *const u8, + ) -> Result> { + assert!( + element_size != InlineComposite, + "Use get_writable_struct_list_pointer() for struct lists" + ); + + let mut orig_ref_target = WirePointer::mut_target(orig_ref); + + if (*orig_ref).is_null() { + if default_value.is_null() || (*(default_value as *const WirePointer)).is_null() { + return Ok(ListBuilder::new_default(arena)); + } + let (new_orig_ref_target, new_orig_ref, new_orig_segment_id) = copy_message( + arena, + orig_segment_id, + cap_table, + orig_ref, + default_value as *const WirePointer, + ); + orig_ref_target = new_orig_ref_target; + orig_ref = new_orig_ref; + orig_segment_id = new_orig_segment_id; + } + + // We must verify that the pointer has the right size. Unlike in + // get_writable_struct_list_pointer(), we never need to "upgrade" the data, because this + // method is called only for non-struct lists, and there is no allowed upgrade path *to* a + // non-struct list, only *from* them. + + let (mut ptr, reff, segment_id) = + follow_builder_fars(arena, orig_ref, orig_ref_target, orig_segment_id)?; + + if (*reff).kind() != WirePointerKind::List { + return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList)); + } + + let old_size = (*reff).list_element_size(); + + if old_size == InlineComposite { + // The existing element size is InlineComposite, which means that it is at least two + // words, which makes it bigger than the expected element size. Since fields can only + // grow when upgraded, the existing data must have been written with a newer version of + // the protocol. We therefore never need to upgrade the data in this case, but we do + // need to validate that it is a valid upgrade from what we expected. + + // Read the tag to get the actual element count. + let tag: *const WirePointer = ptr as *const _; + + if (*tag).kind() != WirePointerKind::Struct { + return Err(Error::from_kind( + ErrorKind::InlineCompositeListWithNonStructElementsNotSupported, + )); + } + + ptr = ptr.add(BYTES_PER_WORD); + + let data_size = (*tag).struct_data_size(); + let pointer_count = (*tag).struct_ptr_count(); + + match element_size { + Void => {} // Anything is a valid upgrade from Void. + Bit => { + return Err(Error::from_kind( + ErrorKind::FoundStructListWhereBitListWasExpected, + )); + } + Byte | TwoBytes | FourBytes | EightBytes => { + if data_size < 1 { + return Err(Error::from_kind( + ErrorKind::ExistingListValueIsIncompatibleWithExpectedType, + )); + } + } + Pointer => { + if pointer_count < 1 { + return Err(Error::from_kind( + ErrorKind::ExistingListValueIsIncompatibleWithExpectedType, + )); + } + // Adjust the pointer to point at the reference segment. + ptr = ptr.offset(data_size as isize * BYTES_PER_WORD as isize); + } + InlineComposite => { + unreachable!() + } + } + // OK, looks valid. + + Ok(ListBuilder { + arena, + segment_id, + cap_table, + ptr: ptr as *mut _, + element_count: (*tag).inline_composite_list_element_count(), + element_size: ElementSize::InlineComposite, + step: (*tag).struct_word_size() * BITS_PER_WORD as u32, + struct_data_size: u32::from(data_size) * BITS_PER_WORD as u32, + struct_pointer_count: pointer_count, + }) + } else { + let data_size = data_bits_per_element(old_size); + let pointer_count = pointers_per_element(old_size); + + if data_size < data_bits_per_element(element_size) + || pointer_count < pointers_per_element(element_size) + { + return Err(Error::from_kind( + ErrorKind::ExistingListValueIsIncompatibleWithExpectedType, + )); + } + + let step = data_size + pointer_count * BITS_PER_POINTER as u32; + + Ok(ListBuilder { + arena, + segment_id, + cap_table, + ptr: ptr as *mut _, + step, + element_count: (*reff).list_element_count(), + element_size: old_size, + struct_data_size: data_size, + struct_pointer_count: pointer_count as u16, + }) + } + } + + #[inline] + pub unsafe fn get_writable_struct_list_pointer( + arena: &mut dyn BuilderArena, + mut orig_ref: *mut WirePointer, + mut orig_segment_id: u32, + cap_table: CapTableBuilder, + element_size: StructSize, + default_value: *const u8, + ) -> Result> { + let mut orig_ref_target = WirePointer::mut_target(orig_ref); + + if (*orig_ref).is_null() { + if default_value.is_null() || (*(default_value as *const WirePointer)).is_null() { + return Ok(ListBuilder::new_default(arena)); + } + let (new_orig_ref_target, new_orig_ref, new_orig_segment_id) = copy_message( + arena, + orig_segment_id, + cap_table, + orig_ref, + default_value as *const WirePointer, + ); + orig_ref_target = new_orig_ref_target; + orig_ref = new_orig_ref; + orig_segment_id = new_orig_segment_id; + } + + // We must verify that the pointer has the right size and potentially upgrade it if not. + + let (mut old_ptr, old_ref, old_segment_id) = + follow_builder_fars(arena, orig_ref, orig_ref_target, orig_segment_id)?; + + if (*old_ref).kind() != WirePointerKind::List { + return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList)); + } + + let old_size = (*old_ref).list_element_size(); + + if old_size == InlineComposite { + // Existing list is InlineComposite, but we need to verify that the sizes match. + + let old_tag: *const WirePointer = old_ptr as *const _; + old_ptr = old_ptr.add(BYTES_PER_WORD); + if (*old_tag).kind() != WirePointerKind::Struct { + return Err(Error::from_kind( + ErrorKind::InlineCompositeListWithNonStructElementsNotSupported, + )); + } + + let old_data_size = (*old_tag).struct_data_size(); + let old_pointer_count = (*old_tag).struct_ptr_count(); + let old_step = + u32::from(old_data_size) + u32::from(old_pointer_count) * WORDS_PER_POINTER as u32; + let element_count = (*old_tag).inline_composite_list_element_count(); + + if old_data_size >= element_size.data && old_pointer_count >= element_size.pointers { + // Old size is at least as large as we need. Ship it. + return Ok(ListBuilder { + arena, + segment_id: old_segment_id, + cap_table, + ptr: old_ptr as *mut _, + element_count, + element_size: ElementSize::InlineComposite, + step: old_step * BITS_PER_WORD as u32, + struct_data_size: u32::from(old_data_size) * BITS_PER_WORD as u32, + struct_pointer_count: old_pointer_count, + }); + } + + // The structs in this list are smaller than expected, probably written using an older + // version of the protocol. We need to make a copy and expand them. + + let new_data_size = ::core::cmp::max(old_data_size, element_size.data); + let new_pointer_count = ::core::cmp::max(old_pointer_count, element_size.pointers); + let new_step = + u32::from(new_data_size) + u32::from(new_pointer_count) * WORDS_PER_POINTER as u32; + let total_size = new_step * element_count; + + // Don't let allocate() zero out the object just yet. + zero_pointer_and_fars(arena, orig_segment_id, orig_ref)?; + + let (mut new_ptr, new_ref, new_segment_id) = allocate( + arena, + orig_ref, + orig_segment_id, + total_size + POINTER_SIZE_IN_WORDS as u32, + WirePointerKind::List, + ); + (*new_ref).set_list_inline_composite(total_size); + + let new_tag: *mut WirePointer = new_ptr as *mut _; + (*new_tag).set_kind_and_inline_composite_list_element_count( + WirePointerKind::Struct, + element_count, + ); + (*new_tag).set_struct_size_from_pieces(new_data_size, new_pointer_count); + new_ptr = new_ptr.add(BYTES_PER_WORD); + + let mut src = old_ptr as *mut WirePointer; + let mut dst = new_ptr as *mut WirePointer; + for _ in 0..element_count { + // Copy data section. + ptr::copy_nonoverlapping(src, dst, old_data_size as usize); + + // Copy pointer section + let new_pointer_section = dst.offset(new_data_size as isize); + let old_pointer_section = src.offset(old_data_size as isize); + for jj in 0..(old_pointer_count as isize) { + transfer_pointer( + arena, + new_segment_id, + new_pointer_section.offset(jj), + old_segment_id, + old_pointer_section.offset(jj), + ); + } + + dst = dst.offset(new_step as isize); + src = src.offset(old_step as isize); + } + + ptr::write_bytes( + old_ptr.offset(-(BYTES_PER_WORD as isize)), + 0, + (u64::from(old_step) * u64::from(element_count)) as usize * BYTES_PER_WORD, + ); + + Ok(ListBuilder { + arena, + segment_id: new_segment_id, + cap_table, + ptr: new_ptr, + element_count, + element_size: ElementSize::InlineComposite, + step: new_step * BITS_PER_WORD as u32, + struct_data_size: u32::from(new_data_size) * BITS_PER_WORD as u32, + struct_pointer_count: new_pointer_count, + }) + } else { + // We're upgrading from a non-struct list. + + let old_data_size = data_bits_per_element(old_size); + let old_pointer_count = pointers_per_element(old_size); + let old_step = old_data_size + old_pointer_count * BITS_PER_POINTER as u32; + let element_count = (*old_ref).list_element_count(); + + if old_size == ElementSize::Void { + // Nothing to copy, just allocate a new list. + Ok(init_struct_list_pointer( + arena, + orig_ref, + orig_segment_id, + cap_table, + element_count, + element_size, + )) + } else { + // Upgrade to an inline composite list. + + if old_size == ElementSize::Bit { + return Err(Error::from_kind( + ErrorKind::FoundBitListWhereStructListWasExpected, + )); + } + + let mut new_data_size = element_size.data; + let mut new_pointer_count = element_size.pointers; + + if old_size == ElementSize::Pointer { + new_pointer_count = ::core::cmp::max(new_pointer_count, 1); + } else { + // Old list contains data elements, so we need at least one word of data. + new_data_size = ::core::cmp::max(new_data_size, 1); + } + + let new_step = u32::from(new_data_size) + + u32::from(new_pointer_count) * WORDS_PER_POINTER as u32; + let total_words = element_count * new_step; + + // Don't let allocate() zero out the object just yet. + zero_pointer_and_fars(arena, orig_segment_id, orig_ref)?; + + let (mut new_ptr, new_ref, new_segment_id) = allocate( + arena, + orig_ref, + orig_segment_id, + total_words + POINTER_SIZE_IN_WORDS as u32, + WirePointerKind::List, + ); + (*new_ref).set_list_inline_composite(total_words); + + let tag: *mut WirePointer = new_ptr as *mut _; + (*tag).set_kind_and_inline_composite_list_element_count( + WirePointerKind::Struct, + element_count, + ); + (*tag).set_struct_size_from_pieces(new_data_size, new_pointer_count); + new_ptr = new_ptr.add(BYTES_PER_WORD); + + if old_size == ElementSize::Pointer { + let mut dst = new_ptr.offset(new_data_size as isize * BYTES_PER_WORD as isize); + let mut src: *mut WirePointer = old_ptr as *mut _; + for _ in 0..element_count { + transfer_pointer(arena, new_segment_id, dst as *mut _, old_segment_id, src); + dst = dst.offset(new_step as isize * BYTES_PER_WORD as isize); + src = src.offset(1); + } + } else { + let mut dst = new_ptr; + let mut src: *mut u8 = old_ptr; + let old_byte_step = old_data_size / BITS_PER_BYTE as u32; + for _ in 0..element_count { + ptr::copy_nonoverlapping(src, dst, old_byte_step as usize); + src = src.offset(old_byte_step as isize); + dst = dst.offset(new_step as isize * BYTES_PER_WORD as isize); + } + } + + // Zero out old location. + ptr::write_bytes( + old_ptr, + 0, + round_bits_up_to_bytes(u64::from(old_step) * u64::from(element_count)) as usize, + ); + + Ok(ListBuilder { + arena, + segment_id: new_segment_id, + cap_table, + ptr: new_ptr, + element_count, + element_size: ElementSize::InlineComposite, + step: new_step * BITS_PER_WORD as u32, + struct_data_size: u32::from(new_data_size) * BITS_PER_WORD as u32, + struct_pointer_count: new_pointer_count, + }) + } + } + } + + #[inline] + pub unsafe fn init_text_pointer( + arena: &mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + size: ByteCount32, + ) -> SegmentAnd> { + //# The byte list must include a NUL terminator. + let byte_size = size + 1; + + //# Allocate the space. + let (ptr, reff, segment_id) = allocate( + arena, + reff, + segment_id, + round_bytes_up_to_words(byte_size), + WirePointerKind::List, + ); + + //# Initialize the pointer. + (*reff).set_list_size_and_count(Byte, byte_size); + + SegmentAnd { + segment_id, + value: text::Builder::new(slice::from_raw_parts_mut(ptr, size as usize)), + } + } + + #[inline] + pub unsafe fn set_text_pointer<'a>( + arena: &'a mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + value: crate::text::Reader<'_>, + ) -> SegmentAnd> { + let value_bytes = value.as_bytes(); + // TODO make sure the string is not longer than 2 ** 29. + let mut allocation = init_text_pointer(arena, reff, segment_id, value_bytes.len() as u32); + allocation + .value + .reborrow() + .as_bytes_mut() + .copy_from_slice(value_bytes); + allocation + } + + #[inline] + pub unsafe fn get_writable_text_pointer<'a>( + arena: &'a mut dyn BuilderArena, + mut reff: *mut WirePointer, + mut segment_id: u32, + default: Option<&'a [crate::Word]>, + ) -> Result> { + let ref_target = if (*reff).is_null() { + match default { + None => return Ok(text::Builder::new(&mut [])), + Some(d) => { + let (new_ref_target, new_reff, new_segment_id) = copy_message( + arena, + segment_id, + Default::default(), + reff, + d.as_ptr() as *const _, + ); + reff = new_reff; + segment_id = new_segment_id; + new_ref_target + } + } + } else { + WirePointer::mut_target(reff) + }; + + let (ptr, reff, _segment_id) = follow_builder_fars(arena, reff, ref_target, segment_id)?; + + if (*reff).kind() != WirePointerKind::List { + return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList)); + } + if (*reff).list_element_size() != Byte { + return Err(Error::from_kind( + ErrorKind::ExistingListPointerIsNotByteSized, + )); + } + + let count = (*reff).list_element_count(); + if count == 0 || *ptr.offset((count - 1) as isize) != 0 { + return Err(Error::from_kind(ErrorKind::TextBlobMissingNULTerminator)); + } + + // Subtract 1 from the size for the NUL terminator. + Ok(text::Builder::with_pos( + slice::from_raw_parts_mut(ptr, (count - 1) as usize), + (count - 1) as usize, + )) + } + + #[inline] + pub unsafe fn init_data_pointer( + arena: &mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + size: ByteCount32, + ) -> SegmentAnd> { + //# Allocate the space. + let (ptr, reff, segment_id) = allocate( + arena, + reff, + segment_id, + round_bytes_up_to_words(size), + WirePointerKind::List, + ); + + //# Initialize the pointer. + (*reff).set_list_size_and_count(Byte, size); + + SegmentAnd { + segment_id, + value: data::builder_from_raw_parts(ptr, size), + } + } + + #[inline] + pub unsafe fn set_data_pointer<'a>( + arena: &'a mut dyn BuilderArena, + reff: *mut WirePointer, + segment_id: u32, + value: &[u8], + ) -> SegmentAnd> { + let allocation = init_data_pointer(arena, reff, segment_id, value.len() as u32); + ptr::copy_nonoverlapping(value.as_ptr(), allocation.value.as_mut_ptr(), value.len()); + allocation + } + + #[inline] + pub unsafe fn get_writable_data_pointer<'a>( + arena: &'a mut dyn BuilderArena, + mut reff: *mut WirePointer, + mut segment_id: u32, + default: Option<&'a [crate::Word]>, + ) -> Result> { + let ref_target = if (*reff).is_null() { + match default { + None => return Ok(&mut []), + Some(d) => { + let (new_ref_target, new_reff, new_segment_id) = copy_message( + arena, + segment_id, + Default::default(), + reff, + d.as_ptr() as *const _, + ); + reff = new_reff; + segment_id = new_segment_id; + new_ref_target + } + } + } else { + WirePointer::mut_target(reff) + }; + + let (ptr, reff, _segment_id) = follow_builder_fars(arena, reff, ref_target, segment_id)?; + + if (*reff).kind() != WirePointerKind::List { + return Err(Error::from_kind(ErrorKind::ExistingPointerIsNotAList)); + } + if (*reff).list_element_size() != Byte { + return Err(Error::from_kind( + ErrorKind::ExistingListPointerIsNotByteSized, + )); + } + + Ok(data::builder_from_raw_parts( + ptr, + (*reff).list_element_count(), + )) + } + + pub unsafe fn set_struct_pointer( + arena: &mut dyn BuilderArena, + segment_id: u32, + cap_table: CapTableBuilder, + reff: *mut WirePointer, + value: StructReader, + canonicalize: bool, + ) -> Result> { + let mut data_size: ByteCount32 = round_bits_up_to_bytes(u64::from(value.data_size)); + let mut ptr_count = value.pointer_count; + + if canonicalize { + // StructReaders should not have bitwidths other than 1, but let's be safe + if !(value.data_size == 1 || value.data_size % BITS_PER_BYTE as u32 == 0) { + return Err(Error::from_kind( + ErrorKind::StructReaderHadBitwidthOtherThan1, + )); + } + + if value.data_size == 1 { + if !value.get_bool_field(0) { + data_size = 0; + } + } else { + 'chop: while data_size != 0 { + let end = data_size; + let mut window = data_size % BYTES_PER_WORD as u32; + if window == 0 { + window = BYTES_PER_WORD as u32; + } + let start = end - window; + let last_word = &value.get_data_section_as_blob()[start as usize..end as usize]; + if last_word == [0; 8] { + data_size -= window; + } else { + break 'chop; + } + } + } + + while ptr_count != 0 && value.get_pointer_field(ptr_count as usize - 1).is_null() { + ptr_count -= 1; + } + } + + let data_words = round_bytes_up_to_words(data_size); + let total_size: WordCount32 = data_words + u32::from(ptr_count) * WORDS_PER_POINTER as u32; + + let (ptr, reff, segment_id) = + allocate(arena, reff, segment_id, total_size, WirePointerKind::Struct); + (*reff).set_struct_size_from_pieces(data_words as u16, ptr_count); + + if value.data_size == 1 { + // Data size could be made 0 by truncation + if data_size != 0 { + *ptr = u8::from(value.get_bool_field(0)) + } + } else { + ptr::copy_nonoverlapping::(value.data, ptr, data_size as usize); + } + + let pointer_section: *mut WirePointer = + ptr.offset(data_words as isize * BYTES_PER_WORD as isize) as *mut _; + for i in 0..ptr_count as isize { + copy_pointer( + arena, + segment_id, + cap_table, + pointer_section.offset(i), + value.arena, + value.segment_id, + value.cap_table, + value.pointers.offset(i), + value.nesting_limit, + canonicalize, + )?; + } + + Ok(SegmentAnd { + segment_id, + value: ptr, + }) + } + + #[cfg(feature = "alloc")] + pub fn set_capability_pointer( + _arena: &mut dyn BuilderArena, + _segment_id: u32, + mut cap_table: CapTableBuilder, + reff: *mut WirePointer, + cap: Box, + ) { + // TODO if ref is not null, zero object. + unsafe { + (*reff).set_cap(cap_table.inject_cap(cap) as u32); + } + } + + pub unsafe fn set_list_pointer( + arena: &mut dyn BuilderArena, + segment_id: u32, + cap_table: CapTableBuilder, + reff: *mut WirePointer, + value: ListReader, + canonicalize: bool, + ) -> Result> { + let total_size = + round_bits_up_to_words(u64::from(value.element_count) * u64::from(value.step)); + + if value.element_size != ElementSize::InlineComposite { + //# List of non-structs. + let (ptr, reff, segment_id) = + allocate(arena, reff, segment_id, total_size, WirePointerKind::List); + + if value.struct_pointer_count == 1 { + //# List of pointers. + (*reff).set_list_size_and_count(Pointer, value.element_count); + for i in 0..value.element_count as isize { + copy_pointer( + arena, + segment_id, + cap_table, + (ptr as *mut WirePointer).offset(i), + value.arena, + value.segment_id, + value.cap_table, + (value.ptr as *const WirePointer).offset(i), + value.nesting_limit, + canonicalize, + )?; + } + } else { + //# List of data. + let element_size = match value.step { + 0 => Void, + 1 => Bit, + 8 => Byte, + 16 => TwoBytes, + 32 => FourBytes, + 64 => EightBytes, + _ => { + panic!("invalid list step size: {}", value.step) + } + }; + + (*reff).set_list_size_and_count(element_size, value.element_count); + + // Be careful to avoid coping any bytes past the end of the list. + // TODO(perf) Is ptr::copy_nonoverlapping faster if word-aligned? + // If so, then perhaps we should only drop to the byte-index level + // in the canonicalize=true case. + let whole_byte_size = + u64::from(value.element_count) * u64::from(value.step) / BITS_PER_BYTE as u64; + ptr::copy_nonoverlapping(value.ptr, ptr, whole_byte_size as usize); + let leftover_bits = + u64::from(value.element_count) * u64::from(value.step) % BITS_PER_BYTE as u64; + if leftover_bits > 0 { + let mask: u8 = (1 << leftover_bits as u8) - 1; + + *ptr.offset(whole_byte_size as isize) = + mask & (*value.ptr.offset(whole_byte_size as isize)) + } + } + + Ok(SegmentAnd { + segment_id, + value: ptr, + }) + } else { + //# List of structs. + + let decl_data_size = value.struct_data_size / BITS_PER_WORD as u32; + let decl_pointer_count = value.struct_pointer_count; + + let mut data_size = 0; + let mut ptr_count = 0; + let mut total_size = total_size; + + if canonicalize { + for ec in 0..value.element_count { + let se = value.get_struct_element(ec); + let mut local_data_size = decl_data_size; + 'data_chop: while local_data_size != 0 { + let end = local_data_size * BYTES_PER_WORD as u32; + let window = BYTES_PER_WORD as u32; + let start = end - window; + let last_word = + &se.get_data_section_as_blob()[start as usize..end as usize]; + if last_word != [0; 8] { + break 'data_chop; + } else { + local_data_size -= 1; + } + } + if local_data_size > data_size { + data_size = local_data_size; + } + let mut local_ptr_count = decl_pointer_count; + while local_ptr_count != 0 + && se.get_pointer_field(local_ptr_count as usize - 1).is_null() + { + local_ptr_count -= 1; + } + if local_ptr_count > ptr_count { + ptr_count = local_ptr_count; + } + } + total_size = (data_size + u32::from(ptr_count)) * value.element_count; + } else { + data_size = decl_data_size; + ptr_count = decl_pointer_count; + } + + let (ptr, reff, segment_id) = allocate( + arena, + reff, + segment_id, + total_size + POINTER_SIZE_IN_WORDS as u32, + WirePointerKind::List, + ); + (*reff).set_list_inline_composite(total_size); + + let tag: *mut WirePointer = ptr as *mut _; + (*tag).set_kind_and_inline_composite_list_element_count( + WirePointerKind::Struct, + value.element_count, + ); + (*tag).set_struct_size_from_pieces(data_size as u16, ptr_count); + let mut dst = ptr.add(BYTES_PER_WORD); + + let mut src: *const u8 = value.ptr; + for _ in 0..value.element_count { + ptr::copy_nonoverlapping(src, dst, data_size as usize * BYTES_PER_WORD); + dst = dst.offset(data_size as isize * BYTES_PER_WORD as isize); + src = src.offset(decl_data_size as isize * BYTES_PER_WORD as isize); + + for _ in 0..ptr_count { + copy_pointer( + arena, + segment_id, + cap_table, + dst as *mut _, + value.arena, + value.segment_id, + value.cap_table, + src as *const WirePointer, + value.nesting_limit, + canonicalize, + )?; + dst = dst.add(BYTES_PER_WORD); + src = src.add(BYTES_PER_WORD); + } + + src = + src.offset((decl_pointer_count - ptr_count) as isize * BYTES_PER_WORD as isize); + } + Ok(SegmentAnd { + segment_id, + value: ptr, + }) + } + } + + pub unsafe fn copy_pointer( + dst_arena: &mut dyn BuilderArena, + dst_segment_id: u32, + dst_cap_table: CapTableBuilder, + dst: *mut WirePointer, + src_arena: &dyn ReaderArena, + src_segment_id: u32, + src_cap_table: CapTableReader, + src: *const WirePointer, + nesting_limit: i32, + canonicalize: bool, + ) -> Result> { + if (*src).is_null() { + ptr::write_bytes(dst, 0, 1); + return Ok(SegmentAnd { + segment_id: dst_segment_id, + value: ptr::null_mut(), + }); + } + + let (mut ptr, src, src_segment_id) = follow_fars(src_arena, src, src_segment_id)?; + + match (*src).kind() { + WirePointerKind::Struct => { + if nesting_limit <= 0 { + return Err(Error::from_kind( + ErrorKind::MessageIsTooDeeplyNestedOrContainsCycles, + )); + } + + bounds_check( + src_arena, + src_segment_id, + ptr, + (*src).struct_word_size() as usize, + WirePointerKind::Struct, + )?; + + set_struct_pointer( + dst_arena, + dst_segment_id, + dst_cap_table, + dst, + StructReader { + arena: src_arena, + segment_id: src_segment_id, + cap_table: src_cap_table, + data: ptr, + pointers: ptr + .offset((*src).struct_data_size() as isize * BYTES_PER_WORD as isize) + as *const _, + data_size: u32::from((*src).struct_data_size()) * BITS_PER_WORD as u32, + pointer_count: (*src).struct_ptr_count(), + nesting_limit: nesting_limit - 1, + }, + canonicalize, + ) + } + WirePointerKind::List => { + let element_size = (*src).list_element_size(); + if nesting_limit <= 0 { + return Err(Error::from_kind( + ErrorKind::MessageIsTooDeeplyNestedOrContainsCycles, + )); + } + + if element_size == InlineComposite { + let word_count = (*src).list_inline_composite_word_count(); + let tag: *const WirePointer = ptr as *const _; + ptr = ptr.add(BYTES_PER_WORD); + + bounds_check( + src_arena, + src_segment_id, + ptr.offset(-(BYTES_PER_WORD as isize)), + word_count as usize + 1, + WirePointerKind::List, + )?; + + if (*tag).kind() != WirePointerKind::Struct { + return Err(Error::from_kind( + ErrorKind::InlineCompositeListsOfNonStructTypeAreNotSupported, + )); + } + + let element_count = (*tag).inline_composite_list_element_count(); + let words_per_element = (*tag).struct_word_size(); + + if u64::from(words_per_element) * u64::from(element_count) + > u64::from(word_count) + { + return Err(Error::from_kind( + ErrorKind::InlineCompositeListsElementsOverrunItsWordCount, + )); + } + + if words_per_element == 0 { + // Watch out for lists of zero-sized structs, which can claim to be + // arbitrarily large without having sent actual data. + amplified_read(src_arena, u64::from(element_count))?; + } + + set_list_pointer( + dst_arena, + dst_segment_id, + dst_cap_table, + dst, + ListReader { + arena: src_arena, + segment_id: src_segment_id, + cap_table: src_cap_table, + ptr: ptr as *const _, + element_count, + element_size, + step: words_per_element * BITS_PER_WORD as u32, + struct_data_size: u32::from((*tag).struct_data_size()) + * BITS_PER_WORD as u32, + struct_pointer_count: (*tag).struct_ptr_count(), + nesting_limit: nesting_limit - 1, + }, + canonicalize, + ) + } else { + let data_size = data_bits_per_element(element_size); + let pointer_count = pointers_per_element(element_size); + let step = data_size + pointer_count * BITS_PER_POINTER as u32; + let element_count = (*src).list_element_count(); + let word_count = + round_bits_up_to_words(u64::from(element_count) * u64::from(step)); + + bounds_check( + src_arena, + src_segment_id, + ptr, + word_count as usize, + WirePointerKind::List, + )?; + + if element_size == Void { + // Watch out for lists of void, which can claim to be arbitrarily large + // without having sent actual data. + amplified_read(src_arena, u64::from(element_count))?; + } + + set_list_pointer( + dst_arena, + dst_segment_id, + dst_cap_table, + dst, + ListReader { + arena: src_arena, + segment_id: src_segment_id, + cap_table: src_cap_table, + ptr: ptr as *const _, + element_count, + element_size, + step, + struct_data_size: data_size, + struct_pointer_count: pointer_count as u16, + nesting_limit: nesting_limit - 1, + }, + canonicalize, + ) + } + } + WirePointerKind::Far => Err(Error::from_kind(ErrorKind::MalformedDoubleFarPointer)), + WirePointerKind::Other => { + if !(*src).is_capability() { + return Err(Error::from_kind(ErrorKind::UnknownPointerType)); + } + if canonicalize { + return Err(Error::from_kind( + ErrorKind::CannotCreateACanonicalMessageWithACapability, + )); + } + #[cfg(feature = "alloc")] + match src_cap_table.extract_cap((*src).cap_index() as usize) { + Some(cap) => { + set_capability_pointer(dst_arena, dst_segment_id, dst_cap_table, dst, cap); + Ok(SegmentAnd { + segment_id: dst_segment_id, + value: ptr::null_mut(), + }) + } + None => Err(Error::from_kind( + ErrorKind::MessageContainsInvalidCapabilityPointer, + )), + } + #[cfg(not(feature = "alloc"))] + return Err(Error::from_kind(ErrorKind::UnknownPointerType)); + } + } + } + + #[inline] + pub unsafe fn read_struct_pointer<'a>( + mut arena: &'a dyn ReaderArena, + mut segment_id: u32, + cap_table: CapTableReader, + mut reff: *const WirePointer, + default: Option<&'a [crate::Word]>, + nesting_limit: i32, + ) -> Result> { + if (*reff).is_null() { + match default { + None => return Ok(StructReader::new_default()), + Some(d) if (*(d.as_ptr() as *const WirePointer)).is_null() => { + return Ok(StructReader::new_default()) + } + Some(d) => { + reff = d.as_ptr() as *const _; + arena = &super::NULL_ARENA; + segment_id = 0; + } + } + } + + if nesting_limit <= 0 { + return Err(Error::from_kind( + ErrorKind::MessageIsTooDeeplyNestedOrContainsCycles, + )); + } + + let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?; + + let data_size_words = (*reff).struct_data_size(); + + if (*reff).kind() != WirePointerKind::Struct { + return Err(Error::from_kind( + ErrorKind::MessageContainsNonStructPointerWhereStructPointerWasExpected, + )); + } + + bounds_check( + arena, + segment_id, + ptr, + (*reff).struct_word_size() as usize, + WirePointerKind::Struct, + )?; + + Ok(StructReader { + arena, + segment_id, + cap_table, + data: ptr, + pointers: ptr.offset(data_size_words as isize * BYTES_PER_WORD as isize) as *const _, + data_size: u32::from(data_size_words) * BITS_PER_WORD as BitCount32, + pointer_count: (*reff).struct_ptr_count(), + nesting_limit: nesting_limit - 1, + }) + } + + #[inline] + #[cfg(feature = "alloc")] + pub unsafe fn read_capability_pointer( + _arena: &dyn ReaderArena, + _segment_id: u32, + cap_table: CapTableReader, + reff: *const WirePointer, + _nesting_limit: i32, + ) -> Result> { + if (*reff).is_null() { + Err(Error::from_kind( + ErrorKind::MessageContainsNullCapabilityPointer, + )) + } else if !(*reff).is_capability() { + Err(Error::from_kind( + ErrorKind::MessageContainsNonCapabilityPointerWhereCapabilityPointerWasExpected, + )) + } else { + let n = (*reff).cap_index() as usize; + match cap_table.extract_cap(n) { + Some(client_hook) => Ok(client_hook), + None => Err(Error::from_kind( + ErrorKind::MessageContainsInvalidCapabilityPointer, + )), + } + } + } + + #[inline] + pub unsafe fn read_list_pointer( + mut arena: &dyn ReaderArena, + mut segment_id: u32, + cap_table: CapTableReader, + mut reff: *const WirePointer, + default_value: *const u8, + expected_element_size: Option, + nesting_limit: i32, + ) -> Result> { + if (*reff).is_null() { + if default_value.is_null() || (*(default_value as *const WirePointer)).is_null() { + return Ok(ListReader::new_default()); + } + reff = default_value as *const _; + arena = &super::NULL_ARENA; + segment_id = 0; + } + + if nesting_limit <= 0 { + return Err(Error::from_kind(ErrorKind::NestingLimitExceeded)); + } + let (mut ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?; + + if (*reff).kind() != WirePointerKind::List { + return Err(Error::from_kind( + ErrorKind::MessageContainsNonListPointerWhereListPointerWasExpected, + )); + } + + let element_size = (*reff).list_element_size(); + match element_size { + InlineComposite => { + let word_count = (*reff).list_inline_composite_word_count(); + + let tag: *const WirePointer = ptr as *const WirePointer; + + ptr = ptr.add(BYTES_PER_WORD); + + bounds_check( + arena, + segment_id, + ptr.offset(-(BYTES_PER_WORD as isize)), + word_count as usize + 1, + WirePointerKind::List, + )?; + + if (*tag).kind() != WirePointerKind::Struct { + return Err(Error::from_kind( + ErrorKind::InlineCompositeListsOfNonStructTypeAreNotSupported, + )); + } + + let size = (*tag).inline_composite_list_element_count(); + let data_size = (*tag).struct_data_size(); + let ptr_count = (*tag).struct_ptr_count(); + let words_per_element = (*tag).struct_word_size(); + + if u64::from(size) * u64::from(words_per_element) > u64::from(word_count) { + return Err(Error::from_kind( + ErrorKind::InlineCompositeListsElementsOverrunItsWordCount, + )); + } + + if words_per_element == 0 { + // Watch out for lists of zero-sized structs, which can claim to be + // arbitrarily large without having sent actual data. + amplified_read(arena, u64::from(size))?; + } + + // If a struct list was not expected, then presumably a non-struct list was upgraded + // to a struct list. We need to manipulate the pointer to point at the first field + // of the struct. Together with the `step` field, this will allow the struct list to + // be accessed as if it were a primitive list without branching. + + // Check whether the size is compatible. + match expected_element_size { + None | Some(Void | InlineComposite) => (), + Some(Bit) => { + return Err(Error::from_kind( + ErrorKind::FoundStructListWhereBitListWasExpected, + )); + } + Some(Byte | TwoBytes | FourBytes | EightBytes) => { + if data_size == 0 { + return Err(Error::from_kind( + ErrorKind::ExpectedAPrimitiveListButGotAListOfPointerOnlyStructs, + )); + } + } + Some(Pointer) => { + if ptr_count == 0 { + return Err(Error::from_kind( + ErrorKind::ExpectedAPointerListButGotAListOfDataOnlyStructs, + )); + } + } + } + + Ok(ListReader { + arena, + segment_id, + cap_table, + ptr: ptr as *const _, + element_count: size, + element_size, + step: words_per_element * BITS_PER_WORD as u32, + struct_data_size: u32::from(data_size) * (BITS_PER_WORD as u32), + struct_pointer_count: ptr_count, + nesting_limit: nesting_limit - 1, + }) + } + _ => { + // This is a primitive or pointer list, but all such lists can also be interpreted + // as struct lists. We need to compute the data size and pointer count for such + // structs. + let data_size = data_bits_per_element((*reff).list_element_size()); + let pointer_count = pointers_per_element((*reff).list_element_size()); + let element_count = (*reff).list_element_count(); + let step = data_size + pointer_count * BITS_PER_POINTER as u32; + + let word_count = round_bits_up_to_words(u64::from(element_count) * u64::from(step)); + bounds_check( + arena, + segment_id, + ptr, + word_count as usize, + WirePointerKind::List, + )?; + + if element_size == Void { + // Watch out for lists of void, which can claim to be arbitrarily large + // without having sent actual data. + amplified_read(arena, u64::from(element_count))?; + } + + if let Some(expected_element_size) = expected_element_size { + if element_size == ElementSize::Bit && expected_element_size != ElementSize::Bit + { + return Err(Error::from_kind( + ErrorKind::FoundBitListWhereStructListWasExpected, + )); + } + + // Verify that the elements are at least as large as the expected type. Note that if + // we expected InlineComposite, the expected sizes here will be zero, because bounds + // checking will be performed at field access time. So this check here is for the + // case where we expected a list of some primitive or pointer type. + + let expected_data_bits_per_element = + data_bits_per_element(expected_element_size); + let expected_pointers_per_element = pointers_per_element(expected_element_size); + + if expected_data_bits_per_element > data_size + || expected_pointers_per_element > pointer_count + { + return Err(Error::from_kind( + ErrorKind::MessageContainsListWithIncompatibleElementType, + )); + } + } + + Ok(ListReader { + arena, + segment_id, + cap_table, + ptr: ptr as *const _, + element_count, + element_size, + step, + struct_data_size: data_size, + struct_pointer_count: pointer_count as u16, + nesting_limit: nesting_limit - 1, + }) + } + } + } + + #[inline] + pub unsafe fn read_text_pointer<'a>( + mut arena: &'a dyn ReaderArena, + mut segment_id: u32, + mut reff: *const WirePointer, + default: Option<&[crate::Word]>, + ) -> Result> { + if (*reff).is_null() { + match default { + None => return Ok("".into()), + Some(d) => { + reff = d.as_ptr() as *const WirePointer; + arena = &super::NULL_ARENA; + segment_id = 0; + } + } + } + + let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?; + let size = (*reff).list_element_count(); + + if (*reff).kind() != WirePointerKind::List { + return Err(Error::from_kind( + ErrorKind::MessageContainsNonListPointerWhereTextWasExpected, + )); + } + + if (*reff).list_element_size() != Byte { + return Err(Error::from_kind( + ErrorKind::MessageContainsListPointerOfNonBytesWhereTextWasExpected, + )); + } + + bounds_check( + arena, + segment_id, + ptr, + round_bytes_up_to_words(size) as usize, + WirePointerKind::List, + )?; + + if size == 0 { + return Err(Error::from_kind( + ErrorKind::MessageContainsTextThatIsNotNULTerminated, + )); + } + + let str_ptr = ptr; + + if (*str_ptr.offset((size - 1) as isize)) != 0u8 { + return Err(Error::from_kind( + ErrorKind::MessageContainsTextThatIsNotNULTerminated, + )); + } + + Ok(text::Reader(slice::from_raw_parts( + str_ptr, + size as usize - 1, + ))) + } + + #[inline] + pub unsafe fn read_data_pointer<'a>( + mut arena: &'a dyn ReaderArena, + mut segment_id: u32, + mut reff: *const WirePointer, + default: Option<&'a [crate::Word]>, + ) -> Result> { + if (*reff).is_null() { + match default { + None => return Ok(&[]), + Some(d) => { + reff = d.as_ptr() as *const WirePointer; + arena = &super::NULL_ARENA; + segment_id = 0; + } + } + } + + let (ptr, reff, segment_id) = follow_fars(arena, reff, segment_id)?; + + let size: u32 = (*reff).list_element_count(); + + if (*reff).kind() != WirePointerKind::List { + return Err(Error::from_kind( + ErrorKind::MessageContainsNonListPointerWhereDataWasExpected, + )); + } + + if (*reff).list_element_size() != Byte { + return Err(Error::from_kind( + ErrorKind::MessageContainsListPointerOfNonBytesWhereDataWasExpected, + )); + } + + bounds_check( + arena, + segment_id, + ptr, + round_bytes_up_to_words(size) as usize, + WirePointerKind::List, + )?; + + Ok(data::reader_from_raw_parts(ptr as *const _, size)) + } +} + +static ZERO: u64 = 0; +fn zero_pointer() -> *const WirePointer { + &ZERO as *const _ as *const _ +} + +static NULL_ARENA: NullArena = NullArena; + +#[cfg(feature = "alloc")] +pub type CapTable = Vec>>; + +#[cfg(not(feature = "alloc"))] +pub struct CapTable; + +#[derive(Copy, Clone)] +pub enum CapTableReader { + // At one point, we had a `Dummy` variant here, but that ended up + // making values of this type take 16 bytes of memory. Now we instead + // represent a null CapTableReader with `Plain(ptr::null())`. + Plain(*const CapTable), +} + +impl Default for CapTableReader { + fn default() -> Self { + CapTableReader::Plain(ptr::null()) + } +} + +#[cfg(feature = "alloc")] +impl CapTableReader { + pub fn extract_cap(&self, index: usize) -> Option> { + match *self { + Self::Plain(hooks) => { + if hooks.is_null() { + return None; + } + let hooks: &Vec>> = unsafe { &*hooks }; + if index >= hooks.len() { + None + } else { + hooks[index].as_ref().map(|hook| hook.add_ref()) + } + } + } + } +} + +#[derive(Copy, Clone)] +pub enum CapTableBuilder { + // At one point, we had a `Dummy` variant here, but that ended up + // making values of this type take 16 bytes of memory. Now we instead + // represent a null CapTableBuilder with `Plain(ptr::null_mut())`. + Plain(*mut CapTable), +} + +impl Default for CapTableBuilder { + fn default() -> Self { + CapTableBuilder::Plain(ptr::null_mut()) + } +} + +impl CapTableBuilder { + pub fn into_reader(self) -> CapTableReader { + match self { + Self::Plain(hooks) => CapTableReader::Plain(hooks), + } + } + + #[cfg(feature = "alloc")] + pub fn extract_cap(&self, index: usize) -> Option> { + match *self { + Self::Plain(hooks) => { + if hooks.is_null() { + return None; + } + let hooks: &Vec>> = unsafe { &*hooks }; + if index >= hooks.len() { + None + } else { + hooks[index].as_ref().map(|hook| hook.add_ref()) + } + } + } + } + + #[cfg(feature = "alloc")] + pub fn inject_cap(&mut self, cap: Box) -> usize { + match *self { + Self::Plain(hooks) => { + if hooks.is_null() { + panic!( + "Called inject_cap() on a null capability table. You need \ + to call imbue_mut() on this message before adding capabilities." + ); + } + let hooks: &mut Vec>> = unsafe { &mut *hooks }; + hooks.push(Some(cap)); + hooks.len() - 1 + } + } + } + + #[cfg(feature = "alloc")] + pub fn drop_cap(&mut self, index: usize) { + match *self { + Self::Plain(hooks) => { + if hooks.is_null() { + panic!( + "Called drop_cap() on a null capability table. You need \ + to call imbue_mut() on this message before adding capabilities." + ); + } + let hooks: &mut Vec>> = unsafe { &mut *hooks }; + if index < hooks.len() { + hooks[index] = None; + } + } + } + } +} + +#[derive(Clone, Copy)] +pub struct PointerReader<'a> { + arena: &'a dyn ReaderArena, + cap_table: CapTableReader, + pointer: *const WirePointer, + segment_id: u32, + nesting_limit: i32, +} + +impl<'a> PointerReader<'a> { + pub fn new_default<'b>() -> PointerReader<'b> { + PointerReader { + arena: &NULL_ARENA, + segment_id: 0, + cap_table: Default::default(), + pointer: ptr::null(), + nesting_limit: 0x7fffffff, + } + } + + pub fn get_root( + arena: &'a dyn ReaderArena, + segment_id: u32, + location: *const u8, + nesting_limit: i32, + ) -> Result { + wire_helpers::bounds_check( + arena, + segment_id, + location as *const _, + POINTER_SIZE_IN_WORDS, + WirePointerKind::Struct, + )?; + + Ok(PointerReader { + arena, + segment_id, + cap_table: Default::default(), + pointer: location as *const _, + nesting_limit, + }) + } + + pub fn reborrow(&self) -> PointerReader<'_> { + PointerReader { + arena: self.arena, + ..*self + } + } + + pub unsafe fn get_root_unchecked<'b>(location: *const u8) -> PointerReader<'b> { + PointerReader { + arena: &NULL_ARENA, + segment_id: 0, + cap_table: Default::default(), + pointer: location as *const _, + nesting_limit: 0x7fffffff, + } + } + + pub fn imbue(&mut self, cap_table: CapTableReader) { + self.cap_table = cap_table; + } + + #[inline] + pub fn is_null(&self) -> bool { + self.pointer.is_null() || unsafe { (*self.pointer).is_null() } + } + + pub fn total_size(&self) -> Result { + if self.pointer.is_null() { + Ok(MessageSize { + word_count: 0, + cap_count: 0, + }) + } else { + unsafe { + wire_helpers::total_size( + self.arena, + self.segment_id, + self.pointer, + self.nesting_limit, + ) + } + } + } + + pub fn get_struct(self, default: Option<&'a [crate::Word]>) -> Result> { + let reff: *const WirePointer = if self.pointer.is_null() { + zero_pointer() + } else { + self.pointer + }; + unsafe { + wire_helpers::read_struct_pointer( + self.arena, + self.segment_id, + self.cap_table, + reff, + default, + self.nesting_limit, + ) + } + } + + pub fn get_list( + self, + expected_element_size: ElementSize, + default: Option<&'a [crate::Word]>, + ) -> Result> { + let default_value: *const u8 = match default { + None => core::ptr::null(), + Some(d) => d.as_ptr() as *const u8, + }; + let reff = if self.pointer.is_null() { + zero_pointer() + } else { + self.pointer + }; + unsafe { + wire_helpers::read_list_pointer( + self.arena, + self.segment_id, + self.cap_table, + reff, + default_value, + Some(expected_element_size), + self.nesting_limit, + ) + } + } + + fn get_list_any_size(self, default_value: *const u8) -> Result> { + let reff = if self.pointer.is_null() { + zero_pointer() + } else { + self.pointer + }; + unsafe { + wire_helpers::read_list_pointer( + self.arena, + self.segment_id, + self.cap_table, + reff, + default_value, + None, + self.nesting_limit, + ) + } + } + + pub fn get_text(self, default: Option<&[crate::Word]>) -> Result> { + let reff = if self.pointer.is_null() { + zero_pointer() + } else { + self.pointer + }; + unsafe { wire_helpers::read_text_pointer(self.arena, self.segment_id, reff, default) } + } + + pub fn get_data(&self, default: Option<&'a [crate::Word]>) -> Result> { + let reff = if self.pointer.is_null() { + zero_pointer() + } else { + self.pointer + }; + unsafe { wire_helpers::read_data_pointer(self.arena, self.segment_id, reff, default) } + } + + #[cfg(feature = "alloc")] + pub fn get_capability(&self) -> Result> { + let reff: *const WirePointer = if self.pointer.is_null() { + zero_pointer() + } else { + self.pointer + }; + unsafe { + wire_helpers::read_capability_pointer( + self.arena, + self.segment_id, + self.cap_table, + reff, + self.nesting_limit, + ) + } + } + + pub fn get_pointer_type(&self) -> Result { + if self.is_null() { + Ok(PointerType::Null) + } else { + let (_, reff, _) = + unsafe { wire_helpers::follow_fars(self.arena, self.pointer, self.segment_id)? }; + + match unsafe { (*reff).kind() } { + WirePointerKind::Far => Err(Error::from_kind(ErrorKind::UnexepectedFarPointer)), + WirePointerKind::Struct => Ok(PointerType::Struct), + WirePointerKind::List => Ok(PointerType::List), + WirePointerKind::Other => { + if unsafe { (*reff).is_capability() } { + Ok(PointerType::Capability) + } else { + Err(Error::from_kind(ErrorKind::UnknownPointerType)) + } + } + } + } + } + + pub fn is_canonical(&self, read_head: &Cell<*const u8>) -> Result { + if self.pointer.is_null() || unsafe { !(*self.pointer).is_positional() } { + return Ok(false); + } + + match self.get_pointer_type()? { + PointerType::Null => Ok(true), + PointerType::Struct => { + let mut data_trunc = false; + let mut ptr_trunc = false; + let st = self.get_struct(None)?; + if st.get_data_section_size() == 0 && st.get_pointer_section_size() == 0 { + Ok(self.pointer as *const _ == st.get_location()) + } else { + let result = + st.is_canonical(read_head, read_head, &mut data_trunc, &mut ptr_trunc)?; + Ok(result && data_trunc && ptr_trunc) + } + } + PointerType::List => unsafe { + self.get_list_any_size(ptr::null())? + .is_canonical(read_head, self.pointer) + }, + PointerType::Capability => Ok(false), + } + } +} + +pub struct PointerBuilder<'a> { + arena: &'a mut dyn BuilderArena, + segment_id: u32, + cap_table: CapTableBuilder, + pointer: *mut WirePointer, +} + +impl<'a> PointerBuilder<'a> { + #[inline] + pub fn get_root(arena: &'a mut dyn BuilderArena, segment_id: u32, location: *mut u8) -> Self { + PointerBuilder { + arena, + cap_table: Default::default(), + segment_id, + pointer: location as *mut _, + } + } + + #[inline] + pub fn reborrow(&mut self) -> PointerBuilder<'_> { + PointerBuilder { + arena: self.arena, + ..*self + } + } + + pub fn imbue(&mut self, cap_table: CapTableBuilder) { + self.cap_table = cap_table; + } + + #[inline] + pub fn is_null(&self) -> bool { + unsafe { (*self.pointer).is_null() } + } + + pub fn get_struct( + self, + size: StructSize, + default: Option<&'a [crate::Word]>, + ) -> Result> { + unsafe { + wire_helpers::get_writable_struct_pointer( + self.arena, + self.pointer, + self.segment_id, + self.cap_table, + size, + default, + ) + } + } + + pub fn get_list( + self, + element_size: ElementSize, + default: Option<&'a [crate::Word]>, + ) -> Result> { + let default_value: *const u8 = match default { + None => core::ptr::null(), + Some(d) => d.as_ptr() as *const u8, + }; + unsafe { + wire_helpers::get_writable_list_pointer( + self.arena, + self.pointer, + self.segment_id, + self.cap_table, + element_size, + default_value, + ) + } + } + + pub fn get_struct_list( + self, + element_size: StructSize, + default: Option<&'a [crate::Word]>, + ) -> Result> { + let default_value: *const u8 = match default { + None => core::ptr::null(), + Some(d) => d.as_ptr() as *const u8, + }; + unsafe { + wire_helpers::get_writable_struct_list_pointer( + self.arena, + self.pointer, + self.segment_id, + self.cap_table, + element_size, + default_value, + ) + } + } + + pub fn get_text(self, default: Option<&'a [crate::Word]>) -> Result> { + unsafe { + wire_helpers::get_writable_text_pointer( + self.arena, + self.pointer, + self.segment_id, + default, + ) + } + } + + pub fn get_data(self, default: Option<&'a [crate::Word]>) -> Result> { + unsafe { + wire_helpers::get_writable_data_pointer( + self.arena, + self.pointer, + self.segment_id, + default, + ) + } + } + + #[cfg(feature = "alloc")] + pub fn get_capability(&self) -> Result> { + unsafe { + wire_helpers::read_capability_pointer( + self.arena.as_reader(), + self.segment_id, + self.cap_table.into_reader(), + self.pointer, + ::core::i32::MAX, + ) + } + } + + pub fn init_struct(self, size: StructSize) -> StructBuilder<'a> { + unsafe { + wire_helpers::init_struct_pointer( + self.arena, + self.pointer, + self.segment_id, + self.cap_table, + size, + ) + } + } + + pub fn init_list( + self, + element_size: ElementSize, + element_count: ElementCount32, + ) -> ListBuilder<'a> { + unsafe { + wire_helpers::init_list_pointer( + self.arena, + self.pointer, + self.segment_id, + self.cap_table, + element_count, + element_size, + ) + } + } + + pub fn init_struct_list( + self, + element_count: ElementCount32, + element_size: StructSize, + ) -> ListBuilder<'a> { + unsafe { + wire_helpers::init_struct_list_pointer( + self.arena, + self.pointer, + self.segment_id, + self.cap_table, + element_count, + element_size, + ) + } + } + + pub fn init_text(self, size: ByteCount32) -> text::Builder<'a> { + unsafe { + wire_helpers::init_text_pointer(self.arena, self.pointer, self.segment_id, size).value + } + } + + pub fn init_data(self, size: ByteCount32) -> data::Builder<'a> { + unsafe { + wire_helpers::init_data_pointer(self.arena, self.pointer, self.segment_id, size).value + } + } + + pub fn set_struct(&mut self, value: &StructReader, canonicalize: bool) -> Result<()> { + unsafe { + wire_helpers::set_struct_pointer( + self.arena, + self.segment_id, + self.cap_table, + self.pointer, + *value, + canonicalize, + )?; + Ok(()) + } + } + + pub fn set_list(&mut self, value: &ListReader, canonicalize: bool) -> Result<()> { + unsafe { + wire_helpers::set_list_pointer( + self.arena, + self.segment_id, + self.cap_table, + self.pointer, + *value, + canonicalize, + )?; + Ok(()) + } + } + + pub fn set_text(&mut self, value: crate::text::Reader<'_>) { + unsafe { + wire_helpers::set_text_pointer(self.arena, self.pointer, self.segment_id, value); + } + } + + pub fn set_data(&mut self, value: &[u8]) { + unsafe { + wire_helpers::set_data_pointer(self.arena, self.pointer, self.segment_id, value); + } + } + + #[cfg(feature = "alloc")] + pub fn set_capability(&mut self, cap: Box) { + wire_helpers::set_capability_pointer( + self.arena, + self.segment_id, + self.cap_table, + self.pointer, + cap, + ); + } + + pub fn copy_from(&mut self, other: PointerReader, canonicalize: bool) -> Result<()> { + if other.pointer.is_null() { + if !self.pointer.is_null() { + unsafe { + wire_helpers::zero_object(self.arena, self.segment_id, self.pointer); + *self.pointer = mem::zeroed(); + } + } + } else { + unsafe { + wire_helpers::copy_pointer( + self.arena, + self.segment_id, + self.cap_table, + self.pointer, + other.arena, + other.segment_id, + other.cap_table, + other.pointer, + other.nesting_limit, + canonicalize, + )?; + } + } + Ok(()) + } + + pub fn clear(&mut self) { + unsafe { + wire_helpers::zero_object(self.arena, self.segment_id, self.pointer); + ptr::write_bytes(self.pointer, 0, 1); + } + } + + pub fn as_reader(&self) -> PointerReader<'_> { + PointerReader { + arena: self.arena.as_reader(), + segment_id: self.segment_id, + cap_table: self.cap_table.into_reader(), + pointer: self.pointer, + nesting_limit: 0x7fffffff, + } + } + + pub fn into_reader(self) -> PointerReader<'a> { + PointerReader { + arena: self.arena.as_reader(), + segment_id: self.segment_id, + cap_table: self.cap_table.into_reader(), + pointer: self.pointer, + nesting_limit: 0x7fffffff, + } + } +} + +#[derive(Clone, Copy)] +pub struct StructReader<'a> { + arena: &'a dyn ReaderArena, + cap_table: CapTableReader, + data: *const u8, + pointers: *const WirePointer, + segment_id: u32, + data_size: BitCount32, + pointer_count: WirePointerCount16, + nesting_limit: i32, +} + +impl<'a> StructReader<'a> { + pub fn new_default<'b>() -> StructReader<'b> { + StructReader { + arena: &NULL_ARENA, + segment_id: 0, + cap_table: Default::default(), + data: ptr::null(), + pointers: ptr::null(), + data_size: 0, + pointer_count: 0, + nesting_limit: 0x7fffffff, + } + } + + pub fn imbue(&mut self, cap_table: CapTableReader) { + self.cap_table = cap_table + } + + pub fn get_data_section_size(&self) -> BitCount32 { + self.data_size + } + + pub fn get_pointer_section_size(&self) -> WirePointerCount16 { + self.pointer_count + } + + pub fn get_pointer_section_as_list(&self) -> ListReader<'a> { + ListReader { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + ptr: self.pointers as *const _, + element_count: u32::from(self.pointer_count), + element_size: ElementSize::Pointer, + step: BITS_PER_WORD as BitCount32, + struct_data_size: 0, + struct_pointer_count: 0, + nesting_limit: self.nesting_limit, + } + } + + pub fn get_data_section_as_blob(&self) -> &'a [u8] { + if self.data_size == 0 { + // Explictly handle this case to avoid forming a slice to a null pointer, + // which would be undefined behavior. + &[] + } else { + unsafe { + ::core::slice::from_raw_parts(self.data, self.data_size as usize / BITS_PER_BYTE) + } + } + } + + #[inline] + pub fn get_data_field(&self, offset: ElementCount) -> T { + // We need to check the offset because the struct may have + // been created with an old version of the protocol that did + // not contain the field. + if (offset + 1) * bits_per_element::() <= self.data_size as usize { + let dwv: *const ::Raw = self.data as *const _; + unsafe { ::get(&*dwv.add(offset)) } + } else { + T::zero() + } + } + + #[inline] + pub fn get_bool_field(&self, offset: ElementCount) -> bool { + let boffset: BitCount32 = offset as BitCount32; + if boffset < self.data_size { + unsafe { + let b: *const u8 = self.data.add(boffset as usize / BITS_PER_BYTE); + ((*b) & (1u8 << (boffset % BITS_PER_BYTE as u32) as usize)) != 0 + } + } else { + false + } + } + + #[inline] + pub fn get_data_field_mask( + &self, + offset: ElementCount, + mask: ::T, + ) -> T { + Mask::mask(self.get_data_field(offset), mask) + } + + #[inline] + pub fn get_bool_field_mask(&self, offset: ElementCount, mask: bool) -> bool { + self.get_bool_field(offset) ^ mask + } + + #[inline] + pub fn get_pointer_field(&self, ptr_index: WirePointerCount) -> PointerReader<'a> { + if ptr_index < self.pointer_count as WirePointerCount { + PointerReader { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + pointer: unsafe { self.pointers.add(ptr_index) }, + nesting_limit: self.nesting_limit, + } + } else { + PointerReader::new_default() + } + } + + #[inline] + pub fn is_pointer_field_null(&self, ptr_index: WirePointerCount) -> bool { + if ptr_index < self.pointer_count as WirePointerCount { + unsafe { (*self.pointers.add(ptr_index)).is_null() } + } else { + true + } + } + + pub fn total_size(&self) -> Result { + let mut result = MessageSize { + word_count: u64::from(wire_helpers::round_bits_up_to_words(u64::from( + self.data_size, + ))) + u64::from(self.pointer_count) * WORDS_PER_POINTER as u64, + cap_count: 0, + }; + + for i in 0..self.pointer_count as isize { + unsafe { + result += wire_helpers::total_size( + self.arena, + self.segment_id, + self.pointers.offset(i), + self.nesting_limit, + )?; + } + } + + // TODO when we have read limiting: segment->unread() + + Ok(result) + } + + fn get_location(&self) -> *const u8 { + self.data + } + + pub fn is_canonical( + &self, + read_head: &Cell<*const u8>, + ptr_head: &Cell<*const u8>, + data_trunc: &mut bool, + ptr_trunc: &mut bool, + ) -> Result { + if self.get_location() != read_head.get() { + return Ok(false); + } + + if self.get_data_section_size() % BITS_PER_WORD as u32 != 0 { + // legacy non-word-size struct + return Ok(false); + } + + let data_size = self.get_data_section_size() / BITS_PER_WORD as u32; + + // mark whether the struct is properly truncated + if data_size != 0 { + *data_trunc = self.get_data_field::((data_size - 1) as usize) != 0; + } else { + *data_trunc = true; + } + + if self.pointer_count != 0 { + *ptr_trunc = !self + .get_pointer_field(self.pointer_count as usize - 1) + .is_null(); + } else { + *ptr_trunc = true; + } + + read_head.set(unsafe { + (read_head.get()).offset( + (data_size as isize + self.pointer_count as isize) * (BYTES_PER_WORD as isize), + ) + }); + + for ptr_idx in 0..self.pointer_count { + if !self + .get_pointer_field(ptr_idx as usize) + .is_canonical(ptr_head)? + { + return Ok(false); + } + } + + Ok(true) + } +} + +pub struct StructBuilder<'a> { + arena: &'a mut dyn BuilderArena, + cap_table: CapTableBuilder, + data: *mut u8, + pointers: *mut WirePointer, + segment_id: u32, + data_size: BitCount32, + pointer_count: WirePointerCount16, +} + +impl<'a> StructBuilder<'a> { + #[inline] + pub fn reborrow(&mut self) -> StructBuilder<'_> { + StructBuilder { + arena: self.arena, + ..*self + } + } + + pub fn as_reader(&self) -> StructReader<'_> { + StructReader { + arena: self.arena.as_reader(), + cap_table: self.cap_table.into_reader(), + data: self.data, + pointers: self.pointers, + pointer_count: self.pointer_count, + segment_id: self.segment_id, + data_size: self.data_size, + nesting_limit: 0x7fffffff, + } + } + + pub fn into_reader(self) -> StructReader<'a> { + StructReader { + arena: self.arena.as_reader(), + cap_table: self.cap_table.into_reader(), + data: self.data, + pointers: self.pointers, + pointer_count: self.pointer_count, + segment_id: self.segment_id, + data_size: self.data_size, + nesting_limit: 0x7fffffff, + } + } + + pub fn imbue(&mut self, cap_table: CapTableBuilder) { + self.cap_table = cap_table + } + + #[inline] + pub fn set_data_field(&self, offset: ElementCount, value: T) { + let ptr: *mut ::Raw = self.data as *mut _; + unsafe { ::set(&mut *ptr.add(offset), value) } + } + + #[inline] + pub fn set_data_field_mask( + &self, + offset: ElementCount, + value: T, + mask: ::T, + ) { + self.set_data_field(offset, Mask::mask(value, mask)); + } + + #[inline] + pub fn get_data_field(&self, offset: ElementCount) -> T { + let ptr: *const ::Raw = self.data as *const _; + unsafe { ::get(&*ptr.add(offset)) } + } + + #[inline] + pub fn get_data_field_mask( + &self, + offset: ElementCount, + mask: ::T, + ) -> T { + Mask::mask(self.get_data_field(offset), mask) + } + + #[inline] + pub fn set_bool_field(&self, offset: ElementCount, value: bool) { + //# This branch should be compiled out whenever this is + //# inlined with a constant offset. + let boffset: BitCount0 = offset; + let b = unsafe { self.data.add(boffset / BITS_PER_BYTE) }; + let bitnum = boffset % BITS_PER_BYTE; + unsafe { (*b) = ((*b) & !(1 << bitnum)) | (u8::from(value) << bitnum) } + } + + #[inline] + pub fn set_bool_field_mask(&self, offset: ElementCount, value: bool, mask: bool) { + self.set_bool_field(offset, value ^ mask); + } + + #[inline] + pub fn get_bool_field(&self, offset: ElementCount) -> bool { + let boffset: BitCount0 = offset; + let b = unsafe { self.data.add(boffset / BITS_PER_BYTE) }; + unsafe { ((*b) & (1 << (boffset % BITS_PER_BYTE))) != 0 } + } + + #[inline] + pub fn get_bool_field_mask(&self, offset: ElementCount, mask: bool) -> bool { + self.get_bool_field(offset) ^ mask + } + + #[inline] + pub fn get_pointer_field(self, ptr_index: WirePointerCount) -> PointerBuilder<'a> { + PointerBuilder { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + pointer: unsafe { self.pointers.add(ptr_index) }, + } + } + + #[inline] + pub fn get_pointer_field_mut(&mut self, ptr_index: WirePointerCount) -> PointerBuilder<'_> { + PointerBuilder { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + pointer: unsafe { self.pointers.add(ptr_index) }, + } + } + + #[inline] + pub fn is_pointer_field_null(&self, ptr_index: WirePointerCount) -> bool { + unsafe { (*self.pointers.add(ptr_index)).is_null() } + } + + pub fn copy_content_from(&mut self, other: &StructReader) -> Result<()> { + use core::cmp::min; + // Determine the amount of data the builders have in common. + let shared_data_size = min(self.data_size, other.data_size); + let shared_pointer_count = min(self.pointer_count, other.pointer_count); + + if (shared_data_size > 0 && other.data == self.data) + || (shared_pointer_count > 0 && other.pointers == self.pointers) + { + // At least one of the section pointers is pointing to ourself. Verify that the other is too + // (but ignore empty sections). + if (shared_data_size == 0 || other.data == self.data) + && (shared_pointer_count == 0 || other.pointers == self.pointers) + { + return Err(Error::from_kind( + ErrorKind::OnlyOneOfTheSectionPointersIsPointingToOurself, + )); + } + + // So `other` appears to be a reader for this same struct. No copying is needed. + return Ok(()); + } + + unsafe { + if self.data_size > shared_data_size { + // Since the target is larger than the source, make sure to zero out the extra bits that the + // source doesn't have. + if self.data_size == 1 { + self.set_bool_field(0, false); + } else { + let unshared = self + .data + .offset((shared_data_size / BITS_PER_BYTE as u32) as isize); + ptr::write_bytes( + unshared, + 0, + ((self.data_size - shared_data_size) / BITS_PER_BYTE as u32) as usize, + ); + } + } + + // Copy over the shared part. + if shared_data_size == 1 { + self.set_bool_field(0, other.get_bool_field(0)); + } else { + ptr::copy_nonoverlapping( + other.data, + self.data, + (shared_data_size / BITS_PER_BYTE as u32) as usize, + ); + } + + // Zero out all pointers in the target. + for i in 0..self.pointer_count as isize { + wire_helpers::zero_object( + self.arena, + self.segment_id, + self.pointers.offset(i) as *mut _, + ); + } + ptr::write_bytes(self.pointers, 0u8, self.pointer_count as usize); + + for i in 0..shared_pointer_count as isize { + wire_helpers::copy_pointer( + self.arena, + self.segment_id, + self.cap_table, + self.pointers.offset(i), + other.arena, + other.segment_id, + other.cap_table, + other.pointers.offset(i), + other.nesting_limit, + false, + )?; + } + } + + Ok(()) + } +} + +#[derive(Clone, Copy)] +pub struct ListReader<'a> { + arena: &'a dyn ReaderArena, + cap_table: CapTableReader, + ptr: *const u8, + segment_id: u32, + element_count: ElementCount32, + step: BitCount32, + struct_data_size: BitCount32, + nesting_limit: i32, + struct_pointer_count: WirePointerCount16, + element_size: ElementSize, +} + +impl<'a> ListReader<'a> { + pub fn new_default<'b>() -> ListReader<'b> { + ListReader { + arena: &NULL_ARENA, + segment_id: 0, + cap_table: Default::default(), + ptr: ptr::null(), + element_count: 0, + element_size: ElementSize::Void, + step: 0, + struct_data_size: 0, + struct_pointer_count: 0, + nesting_limit: 0x7fffffff, + } + } + + pub fn imbue(&mut self, cap_table: CapTableReader) { + self.cap_table = cap_table + } + + #[inline] + pub fn len(&self) -> ElementCount32 { + self.element_count + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub(crate) fn get_step_size_in_bits(&self) -> u32 { + self.step + } + + pub(crate) fn get_element_size(&self) -> ElementSize { + self.element_size + } + + pub(crate) fn into_raw_bytes(self) -> &'a [u8] { + if self.element_count == 0 { + // Explictly handle this case to avoid forming a slice to a null pointer, + // which would be undefined behavior. + &[] + } else { + let num_bytes = wire_helpers::round_bits_up_to_bytes( + u64::from(self.step) * u64::from(self.element_count), + ) as usize; + unsafe { ::core::slice::from_raw_parts(self.ptr, num_bytes) } + } + } + + #[inline] + pub fn get_struct_element(&self, index: ElementCount32) -> StructReader<'a> { + let index_byte: ByteCount32 = + ((u64::from(index) * u64::from(self.step)) / BITS_PER_BYTE as u64) as u32; + + let struct_data: *const u8 = unsafe { self.ptr.offset(index_byte as isize) }; + + let struct_pointers: *const WirePointer = + unsafe { struct_data.add(self.struct_data_size as usize / BITS_PER_BYTE) as *const _ }; + + StructReader { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + data: struct_data, + pointers: struct_pointers, + data_size: self.struct_data_size, + pointer_count: self.struct_pointer_count, + nesting_limit: self.nesting_limit - 1, + } + } + + #[inline] + pub fn get_pointer_element(self, index: ElementCount32) -> PointerReader<'a> { + let offset = (self.struct_data_size as u64 / BITS_PER_BYTE as u64 + + u64::from(index) * u64::from(self.step) / BITS_PER_BYTE as u64) + as isize; + PointerReader { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + pointer: unsafe { self.ptr.offset(offset) } as *const _, + nesting_limit: self.nesting_limit, + } + } + + pub unsafe fn is_canonical( + &self, + read_head: &Cell<*const u8>, + reff: *const WirePointer, + ) -> Result { + match self.element_size { + ElementSize::InlineComposite => { + read_head.set(unsafe { read_head.get().add(BYTES_PER_WORD) }); // tag word + if self.ptr as *const _ != read_head.get() { + return Ok(false); + } + if self.struct_data_size % BITS_PER_WORD as u32 != 0 { + return Ok(false); + } + let struct_size = (self.struct_data_size / BITS_PER_WORD as u32) + + u32::from(self.struct_pointer_count); + let word_count = unsafe { (*reff).list_inline_composite_word_count() }; + if struct_size * self.element_count != word_count { + return Ok(false); + } + if struct_size == 0 { + return Ok(true); + } + let list_end = unsafe { + read_head + .get() + .add((self.element_count * struct_size) as usize * BYTES_PER_WORD) + }; + let pointer_head = Cell::new(list_end); + let mut list_data_trunc = false; + let mut list_ptr_trunc = false; + for idx in 0..self.element_count { + let mut data_trunc = false; + let mut ptr_trunc = false; + if !self.get_struct_element(idx).is_canonical( + read_head, + &pointer_head, + &mut data_trunc, + &mut ptr_trunc, + )? { + return Ok(false); + } + list_data_trunc |= data_trunc; + list_ptr_trunc |= ptr_trunc; + } + assert_eq!(read_head.get(), list_end); + read_head.set(pointer_head.get()); + Ok(list_data_trunc && list_ptr_trunc) + } + ElementSize::Pointer => { + if self.ptr as *const _ != read_head.get() { + return Ok(false); + } + read_head.set(unsafe { + read_head + .get() + .offset(self.element_count as isize * BYTES_PER_WORD as isize) + }); + for idx in 0..self.element_count { + if !self.get_pointer_element(idx).is_canonical(read_head)? { + return Ok(false); + } + } + Ok(true) + } + element_size => { + if self.ptr != read_head.get() as *const _ { + return Ok(false); + } + let bit_size = + u64::from(self.element_count) * u64::from(data_bits_per_element(element_size)); + let mut word_size = bit_size / BITS_PER_WORD as u64; + if bit_size % BITS_PER_WORD as u64 != 0 { + word_size += 1 + } + + let byte_size = bit_size / BITS_PER_BYTE as u64; + let mut byte_read_head: *const u8 = read_head.get(); + byte_read_head = unsafe { byte_read_head.offset(byte_size as isize) }; + let read_head_end = unsafe { + read_head + .get() + .offset(word_size as isize * BYTES_PER_WORD as isize) + }; + + let leftover_bits = bit_size % BITS_PER_BYTE as u64; + if leftover_bits > 0 { + let mask: u8 = !((1 << leftover_bits as u8) - 1); + let partial_byte = unsafe { *byte_read_head }; + + if partial_byte & mask != 0 { + return Ok(false); + } + byte_read_head = unsafe { byte_read_head.offset(1_isize) }; + } + + while byte_read_head != read_head_end { + if unsafe { *byte_read_head } != 0 { + return Ok(false); + } + byte_read_head = unsafe { byte_read_head.offset(1_isize) }; + } + + read_head.set(read_head_end); + Ok(true) + } + } + } +} + +pub struct ListBuilder<'a> { + arena: &'a mut dyn BuilderArena, + cap_table: CapTableBuilder, + ptr: *mut u8, + segment_id: u32, + element_count: ElementCount32, + step: BitCount32, + struct_data_size: BitCount32, + struct_pointer_count: WirePointerCount16, + element_size: ElementSize, +} + +impl<'a> ListBuilder<'a> { + #[inline] + pub fn new_default(arena: &mut dyn BuilderArena) -> ListBuilder<'_> { + ListBuilder { + arena, + segment_id: 0, + cap_table: Default::default(), + ptr: ptr::null_mut(), + element_count: 0, + element_size: ElementSize::Void, + step: 0, + struct_data_size: 0, + struct_pointer_count: 0, + } + } + + pub fn into_reader(self) -> ListReader<'a> { + ListReader { + arena: self.arena.as_reader(), + segment_id: self.segment_id, + cap_table: self.cap_table.into_reader(), + ptr: self.ptr as *const _, + element_count: self.element_count, + element_size: self.element_size, + step: self.step, + struct_data_size: self.struct_data_size, + struct_pointer_count: self.struct_pointer_count, + nesting_limit: 0x7fffffff, + } + } + + #[inline] + pub fn reborrow(&mut self) -> ListBuilder<'_> { + ListBuilder { + arena: self.arena, + ..*self + } + } + + pub fn imbue(&mut self, cap_table: CapTableBuilder) { + self.cap_table = cap_table + } + + #[inline] + pub fn len(&self) -> ElementCount32 { + self.element_count + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + #[inline] + pub fn get_struct_element(self, index: ElementCount32) -> StructBuilder<'a> { + let index_byte = ((u64::from(index) * u64::from(self.step)) / BITS_PER_BYTE as u64) as u32; + let struct_data = unsafe { self.ptr.offset(index_byte as isize) }; + let struct_pointers = + unsafe { struct_data.add((self.struct_data_size as usize) / BITS_PER_BYTE) as *mut _ }; + StructBuilder { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + data: struct_data, + pointers: struct_pointers, + data_size: self.struct_data_size, + pointer_count: self.struct_pointer_count, + } + } + + pub(crate) fn get_element_size(&self) -> ElementSize { + self.element_size + } + + #[inline] + pub fn get_pointer_element(self, index: ElementCount32) -> PointerBuilder<'a> { + let offset = (u64::from(index) * u64::from(self.step) / BITS_PER_BYTE as u64) as u32; + PointerBuilder { + arena: self.arena, + segment_id: self.segment_id, + cap_table: self.cap_table, + pointer: unsafe { self.ptr.offset(offset as isize) } as *mut _, + } + } + + pub(crate) fn into_raw_bytes(&self) -> &'a mut [u8] { + if self.element_count == 0 { + // Explictly handle this case to avoid forming a slice to a null pointer, + // which would be undefined behavior. + &mut [] + } else { + let num_bytes = wire_helpers::round_bits_up_to_bytes( + u64::from(self.step) * u64::from(self.element_count), + ) as usize; + unsafe { ::core::slice::from_raw_parts_mut(self.ptr, num_bytes) } + } + } +} + +/** + An element that can be stored in a `primitive_list`. +*/ +pub trait PrimitiveElement { + /// Gets the element at position `index`. Bounds checking is *not* performed. + fn get(list_reader: &ListReader, index: ElementCount32) -> Self; + + /// Gets the element at position `index`. Bounds checking is *not* performed. + fn get_from_builder(list_builder: &ListBuilder, index: ElementCount32) -> Self; + + /// Sets to element at position `index` to be `value`. Bounds checking is *not* performed. + fn set(list_builder: &ListBuilder, index: ElementCount32, value: Self); + + /// Returns the size of an individual element. + fn element_size() -> ElementSize; +} + +impl PrimitiveElement for T { + #[inline] + fn get(list_reader: &ListReader, index: ElementCount32) -> Self { + let offset = (u64::from(index) * u64::from(list_reader.step) / BITS_PER_BYTE as u64) as u32; + unsafe { + let ptr: *const u8 = list_reader.ptr.offset(offset as isize); + ::get(&*(ptr as *const ::Raw)) + } + } + + #[inline] + fn get_from_builder(list_builder: &ListBuilder, index: ElementCount32) -> Self { + let offset = + (u64::from(index) * u64::from(list_builder.step) / BITS_PER_BYTE as u64) as u32; + unsafe { + let ptr: *mut ::Raw = + list_builder.ptr.offset(offset as isize) as *mut _; + ::get(&*ptr) + } + } + + #[inline] + fn set(list_builder: &ListBuilder, index: ElementCount32, value: Self) { + let offset = + (u64::from(index) * u64::from(list_builder.step) / BITS_PER_BYTE as u64) as u32; + unsafe { + let ptr: *mut ::Raw = + list_builder.ptr.offset(offset as isize) as *mut _; + ::set(&mut *ptr, value); + } + } + + fn element_size() -> ElementSize { + match mem::size_of::() { + 0 => Void, + 1 => Byte, + 2 => TwoBytes, + 4 => FourBytes, + 8 => EightBytes, + _ => unreachable!(), + } + } +} + +impl PrimitiveElement for bool { + #[inline] + fn get(list: &ListReader, index: ElementCount32) -> Self { + let bindex = u64::from(index) * u64::from(list.step); + unsafe { + let b: *const u8 = list.ptr.offset((bindex / BITS_PER_BYTE as u64) as isize); + ((*b) & (1 << (bindex % BITS_PER_BYTE as u64))) != 0 + } + } + #[inline] + fn get_from_builder(list: &ListBuilder, index: ElementCount32) -> Self { + let bindex = u64::from(index) * u64::from(list.step); + let b = unsafe { list.ptr.offset((bindex / BITS_PER_BYTE as u64) as isize) }; + unsafe { ((*b) & (1 << (bindex % BITS_PER_BYTE as u64))) != 0 } + } + #[inline] + fn set(list: &ListBuilder, index: ElementCount32, value: Self) { + let bindex = u64::from(index) * u64::from(list.step); + let b = unsafe { list.ptr.offset((bindex / BITS_PER_BYTE as u64) as isize) }; + + let bitnum = bindex % BITS_PER_BYTE as u64; + unsafe { (*b) = ((*b) & !(1 << bitnum)) | (u8::from(value) << bitnum) } + } + fn element_size() -> ElementSize { + Bit + } +} + +impl PrimitiveElement for () { + #[inline] + fn get(_list: &ListReader, _index: ElementCount32) {} + + #[inline] + fn get_from_builder(_list: &ListBuilder, _index: ElementCount32) {} + + #[inline] + fn set(_list: &ListBuilder, _index: ElementCount32, _value: ()) {} + + fn element_size() -> ElementSize { + Void + } +} diff --git a/rust/capnp/private/layout_test.rs b/rust/capnp/private/layout_test.rs new file mode 100644 index 000000000000..8715e9edab43 --- /dev/null +++ b/rust/capnp/private/layout_test.rs @@ -0,0 +1,192 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#![allow(clippy::bool_assert_comparison)] + +use crate::private::layout::PointerReader; + +fn test_at_alignments(words: &[crate::Word], verify: &dyn Fn(PointerReader)) { + verify(unsafe { PointerReader::get_root_unchecked(words.as_ptr() as *const u8) }); + + #[cfg(all(feature = "unaligned", feature = "alloc"))] + { + let mut unaligned_data = crate::Vec::with_capacity((words.len() + 1) * 8); + for offset in 0..8 { + unaligned_data.clear(); + unaligned_data.resize(offset, 0); + unaligned_data.extend(crate::Word::words_to_bytes(words)); + verify(unsafe { + PointerReader::get_root_unchecked((unaligned_data[offset..]).as_ptr()) + }); + } + } +} + +#[test] +fn simple_raw_data_struct() { + let data: &[crate::Word] = &[ + crate::word(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), + crate::word(0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef), + ]; + + test_at_alignments(data, &verify); + fn verify(reader: PointerReader) { + let reader = reader.get_struct(None).unwrap(); + + assert_eq!(0xefcdab8967452301u64, reader.get_data_field::(0)); + assert_eq!(0, reader.get_data_field::(1)); // past end of struct --> default value + + assert_eq!(0x67452301u32, reader.get_data_field::(0)); + assert_eq!(0xefcdab89u32, reader.get_data_field::(1)); + assert_eq!(0, reader.get_data_field::(2)); // past end of struct --> default value + + assert_eq!(0x2301u16, reader.get_data_field::(0)); + assert_eq!(0x6745u16, reader.get_data_field::(1)); + assert_eq!(0xab89u16, reader.get_data_field::(2)); + assert_eq!(0xefcdu16, reader.get_data_field::(3)); + assert_eq!(0u16, reader.get_data_field::(4)); // past end of struct --> default value + // TODO the rest of uints. + + // Bits. + assert_eq!(reader.get_bool_field(0), true); + assert_eq!(reader.get_bool_field(1), false); + assert_eq!(reader.get_bool_field(2), false); + assert_eq!(reader.get_bool_field(3), false); + assert_eq!(reader.get_bool_field(4), false); + assert_eq!(reader.get_bool_field(5), false); + assert_eq!(reader.get_bool_field(6), false); + assert_eq!(reader.get_bool_field(7), false); + + assert_eq!(reader.get_bool_field(8), true); + assert_eq!(reader.get_bool_field(9), true); + assert_eq!(reader.get_bool_field(10), false); + assert_eq!(reader.get_bool_field(11), false); + assert_eq!(reader.get_bool_field(12), false); + assert_eq!(reader.get_bool_field(13), true); + assert_eq!(reader.get_bool_field(14), false); + assert_eq!(reader.get_bool_field(15), false); + + assert_eq!(reader.get_bool_field(63), true); + assert_eq!(reader.get_bool_field(64), false); // past end of struct --> default value + } +} + +#[test] +fn bool_list() { + // [true, false, true, false, + // true, true, true, false, + // false, true] + + let data: &[crate::Word] = &[ + crate::word(0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00), + crate::word(0x75, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + ]; + + test_at_alignments(data, &verify); + fn verify(pointer_reader: PointerReader) { + use crate::private::layout::PrimitiveElement; + use crate::traits::FromPointerReader; + + let reader = pointer_reader + .get_list(crate::private::layout::ElementSize::Bit, None) + .unwrap(); + + assert_eq!(reader.len(), 10); + assert_eq!(bool::get(&reader, 0), true); + assert_eq!(bool::get(&reader, 1), false); + assert_eq!(bool::get(&reader, 2), true); + assert_eq!(bool::get(&reader, 3), false); + assert_eq!(bool::get(&reader, 4), true); + assert_eq!(bool::get(&reader, 5), true); + assert_eq!(bool::get(&reader, 6), true); + assert_eq!(bool::get(&reader, 7), false); + assert_eq!(bool::get(&reader, 8), false); + assert_eq!(bool::get(&reader, 9), true); + + let reader = + crate::primitive_list::Reader::::get_from_pointer(&pointer_reader, None).unwrap(); + + assert_eq!(reader.len(), 10); + assert_eq!(reader.get(0), true); + assert_eq!(reader.get(1), false); + assert_eq!(reader.get(2), true); + assert_eq!(reader.get(3), false); + assert_eq!(reader.get(4), true); + assert_eq!(reader.get(5), true); + assert_eq!(reader.get(6), true); + assert_eq!(reader.get(7), false); + assert_eq!(reader.get(8), false); + assert_eq!(reader.get(9), true); + } +} + +#[test] +fn struct_size() { + let data: &[crate::Word] = &[ + crate::word(0x00, 0x00, 0x00, 0x00, 0x2, 0x00, 0x01, 0x00), + crate::word(0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + crate::word(0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + crate::word(0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + ]; + + test_at_alignments(data, &verify); + fn verify(pointer_reader: PointerReader) { + assert_eq!(pointer_reader.total_size().unwrap().word_count, 3); + } +} + +#[test] +fn struct_list_size() { + let data: &[crate::Word] = &[ + crate::word(0x01, 0, 0, 0, 0x1f, 0, 0, 0), // inline-composite list. 4 words long. + crate::word(0x4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), // 1 element long + crate::word(0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + crate::word(0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + crate::word(0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + ]; + + // The list pointer claims that the list consumes four words, but the struct + // tag says there is only one element and it has a size of one word. + // So there is an inconsistency! total_size() should report the value computed from + // the struct tag, because that's what is relevant when the data is copied. + + test_at_alignments(data, &verify); + fn verify(pointer_reader: PointerReader) { + assert_eq!(pointer_reader.total_size().unwrap().word_count, 2); + } +} + +#[test] +fn empty_struct_list_size() { + let data: &[crate::Word] = &[ + // Struct, one pointer + crate::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00), + // Inline-composite list, zero words long + crate::word(0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00), + // Tag + crate::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + ]; + + test_at_alignments(data, &verify); + fn verify(pointer_reader: PointerReader) { + assert_eq!(2, pointer_reader.total_size().unwrap().word_count); + } +} diff --git a/rust/capnp/private/mask.rs b/rust/capnp/private/mask.rs new file mode 100644 index 000000000000..dfa211521ca7 --- /dev/null +++ b/rust/capnp/private/mask.rs @@ -0,0 +1,62 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +pub trait Mask { + type T; + fn mask(value: Self, mask: Self::T) -> Self; +} + +macro_rules! int_mask( + ($t:ident) => ( + impl Mask for $t { + type T = $t; + #[inline] + fn mask(value: $t, mask: $t) -> $t { + value ^ mask + } + } + ) +); + +int_mask!(i8); +int_mask!(i16); +int_mask!(i32); +int_mask!(i64); +int_mask!(u8); +int_mask!(u16); +int_mask!(u32); +int_mask!(u64); + +impl Mask for f32 { + type T = u32; + #[inline] + fn mask(value: Self, mask: u32) -> Self { + Self::from_bits(value.to_bits() ^ mask) + } +} + +impl Mask for f64 { + type T = u64; + #[inline] + fn mask(value: Self, mask: u64) -> Self { + Self::from_bits(value.to_bits() ^ mask) + } +} diff --git a/rust/capnp/private/mod.rs b/rust/capnp/private/mod.rs new file mode 100644 index 000000000000..1e6bcdab6d6e --- /dev/null +++ b/rust/capnp/private/mod.rs @@ -0,0 +1,36 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Implementation details that should never be directly used by clients. +//! +//! We still need to make this module visible so that generated code can use it. + +pub mod arena; +pub mod capability; +pub mod layout; +mod mask; +mod primitive; +mod read_limiter; +pub mod units; +mod zero; + +#[cfg(test)] +mod layout_test; diff --git a/rust/capnp/private/primitive.rs b/rust/capnp/private/primitive.rs new file mode 100644 index 000000000000..00e41ce40f08 --- /dev/null +++ b/rust/capnp/private/primitive.rs @@ -0,0 +1,119 @@ +pub trait Primitive { + type Raw; + + /// Reads the value, swapping bytes on big-endian processors. + fn get(raw: &Self::Raw) -> Self; + + /// Writes the value, swapping bytes on big-endian processors. + fn set(raw: &mut Self::Raw, value: Self); +} + +#[cfg(feature = "unaligned")] +macro_rules! primitive_impl( + ($typ:ty, $n:expr) => ( + impl Primitive for $typ { + type Raw = [u8; $n]; + + #[inline] + fn get(raw: &Self::Raw) -> Self { + <$typ>::from_le_bytes(*raw) + } + + #[inline] + fn set(raw: &mut Self::Raw, value: Self) { + *raw = value.to_le_bytes(); + } + } + ); + ); + +#[cfg(not(feature = "unaligned"))] +macro_rules! primitive_impl( + ($typ:ty, $n:expr) => ( + impl Primitive for $typ { + type Raw = Self; + + #[inline] + fn get(raw: &Self::Raw) -> Self { + raw.to_le() + } + + #[inline] + fn set(raw: &mut Self::Raw, value: Self) { + *raw = value.to_le() + } + } + ); + ); + +primitive_impl!(u8, 1); +primitive_impl!(i8, 1); +primitive_impl!(u16, 2); +primitive_impl!(i16, 2); +primitive_impl!(u32, 4); +primitive_impl!(i32, 4); +primitive_impl!(u64, 8); +primitive_impl!(i64, 8); + +#[cfg(feature = "unaligned")] +primitive_impl!(f32, 4); + +#[cfg(feature = "unaligned")] +primitive_impl!(f64, 8); + +#[cfg(not(feature = "unaligned"))] +impl Primitive for f32 { + type Raw = Self; + + #[inline] + fn get(raw: &Self::Raw) -> Self { + Self::from_bits(raw.to_bits().to_le()) + } + + #[inline] + fn set(raw: &mut Self::Raw, value: Self) { + *raw = Self::from_bits(value.to_bits().to_le()) + } +} + +#[cfg(not(feature = "unaligned"))] +impl Primitive for f64 { + type Raw = Self; + + #[inline] + fn get(raw: &Self::Raw) -> Self { + Self::from_bits(raw.to_bits().to_le()) + } + + #[inline] + fn set(raw: &mut Self::Raw, value: Self) { + *raw = Self::from_bits(value.to_bits().to_le()) + } +} + +/// A value casted directly from a little-endian byte buffer. On big-endian +/// processors, the bytes of the value need to be swapped upon reading and writing. +#[repr(C)] +pub struct WireValue +where + T: Primitive, +{ + value: ::Raw, +} + +impl WireValue +where + T: Primitive, +{ + /// Reads the value, swapping bytes on big-endian processors. + #[inline] + pub fn get(&self) -> T { + ::get(&self.value) + } + + /// Writes the value, swapping bytes on big-endian processors. + #[inline] + pub fn set(&mut self, value: T) { + ::set(&mut self.value, value) + } +} diff --git a/rust/capnp/private/read_limiter.rs b/rust/capnp/private/read_limiter.rs new file mode 100644 index 000000000000..0bb6a7a8415c --- /dev/null +++ b/rust/capnp/private/read_limiter.rs @@ -0,0 +1,113 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#[cfg(feature = "sync_reader")] +pub use sync::ReadLimiter; + +#[cfg(feature = "sync_reader")] +mod sync { + use crate::{Error, ErrorKind, Result}; + use core::sync::atomic::{AtomicUsize, Ordering}; + + pub struct ReadLimiter { + limit: AtomicUsize, + error_on_limit_exceeded: bool, + } + + impl ReadLimiter { + pub fn new(limit: Option) -> Self { + match limit { + Some(value) => Self { + limit: AtomicUsize::new(value), + error_on_limit_exceeded: true, + }, + None => Self { + limit: AtomicUsize::new(usize::MAX), + error_on_limit_exceeded: false, + }, + } + } + + #[inline] + pub fn can_read(&self, amount: usize) -> Result<()> { + // We use separate AtomicUsize::load() and AtomicUsize::store() steps, which may + // result in undercounting reads if multiple threads are reading at the same. + // That's okay -- a denial of service attack will eventually hit the limit anyway. + // + // We could instead do a single fetch_sub() step, but that seems to be slower. + + let current = self.limit.load(Ordering::Relaxed); + if amount > current && self.error_on_limit_exceeded { + return Err(Error::from_kind(ErrorKind::ReadLimitExceeded)); + } else { + // The common case is current >= amount. Note that we only branch once in that case. + // If we combined the fields into an Option, we would + // need to branch twice in the common case. + self.limit + .store(current.wrapping_sub(amount), Ordering::Relaxed); + } + Ok(()) + } + } +} + +#[cfg(not(feature = "sync_reader"))] +pub use unsync::ReadLimiter; + +#[cfg(not(feature = "sync_reader"))] +mod unsync { + use crate::{Error, ErrorKind, Result}; + use core::cell::Cell; + + pub struct ReadLimiter { + limit: Cell, + error_on_limit_exceeded: bool, + } + + impl ReadLimiter { + pub fn new(limit: Option) -> Self { + match limit { + Some(value) => Self { + limit: Cell::new(value), + error_on_limit_exceeded: true, + }, + None => Self { + limit: Cell::new(usize::MAX), + error_on_limit_exceeded: false, + }, + } + } + + #[inline] + pub fn can_read(&self, amount: usize) -> Result<()> { + let current = self.limit.get(); + if amount > current && self.error_on_limit_exceeded { + Err(Error::from_kind(ErrorKind::ReadLimitExceeded)) + } else { + // The common case is current >= amount. Note that we only branch once in that case. + // If we combined the fields into an Option>, we would + // need to branch twice in the common case. + self.limit.set(current.wrapping_sub(amount)); + Ok(()) + } + } + } +} diff --git a/rust/capnp/private/units.rs b/rust/capnp/private/units.rs new file mode 100644 index 000000000000..90fbf663f777 --- /dev/null +++ b/rust/capnp/private/units.rs @@ -0,0 +1,68 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +pub type BitCount0 = usize; // `BitCount` clashes with a standard trait +pub type BitCount8 = u8; +pub type BitCount16 = u16; +pub type BitCount32 = u32; +pub type BitCount64 = u64; + +pub type ByteCount = usize; +pub type ByteCount8 = u8; +pub type ByteCount16 = u16; +pub type ByteCount32 = u32; +pub type ByteCount64 = u64; + +pub type WordCount = usize; +pub type WordCount8 = u8; +pub type WordCount16 = u16; +pub type WordCount32 = u32; +pub type WordCount64 = u64; + +pub type ElementCount = usize; +pub type ElementCount8 = u8; +pub type ElementCount16 = u16; +pub type ElementCount32 = u32; +pub type ElementCount64 = u64; + +pub type WirePointerCount = usize; +pub type WirePointerCount8 = u8; +pub type WirePointerCount16 = u16; +pub type WirePointerCount32 = u32; +pub type WirePointerCount64 = u64; + +pub const BITS_PER_BYTE: BitCount0 = 8; +pub const BITS_PER_WORD: BitCount0 = 64; +pub const BYTES_PER_WORD: ByteCount = 8; + +pub const BITS_PER_POINTER: BitCount0 = 64; +pub const _BYTES_PER_POINTER: ByteCount = 8; +pub const WORDS_PER_POINTER: WordCount = 1; + +pub const POINTER_SIZE_IN_WORDS: WordCount = 1; + +pub fn _bytes_per_element() -> ByteCount { + ::core::mem::size_of::() +} + +pub fn bits_per_element() -> BitCount0 { + 8 * ::core::mem::size_of::() +} diff --git a/rust/capnp/private/zero.rs b/rust/capnp/private/zero.rs new file mode 100644 index 000000000000..00769cfebafc --- /dev/null +++ b/rust/capnp/private/zero.rs @@ -0,0 +1,46 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +/// At one point the standard library had `::std::num::Zero`. It was never stabilized +/// it eventually got deleted. So we define our own version here. +pub trait Zero { + fn zero() -> Self; +} + +macro_rules! zero_impl( + ($t:ident, $e:expr) => ( + impl Zero for $t { + #[inline] + fn zero() -> $t { $e } + } + ) +); + +zero_impl!(u8, 0); +zero_impl!(u16, 0); +zero_impl!(u32, 0); +zero_impl!(u64, 0); +zero_impl!(i8, 0); +zero_impl!(i16, 0); +zero_impl!(i32, 0); +zero_impl!(i64, 0); +zero_impl!(f32, 0.0); +zero_impl!(f64, 0.0); diff --git a/rust/capnp/raw.rs b/rust/capnp/raw.rs new file mode 100644 index 000000000000..5883b1207be9 --- /dev/null +++ b/rust/capnp/raw.rs @@ -0,0 +1,69 @@ +// Copyright (c) 2018 the capnproto-rust contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Functions providing low level access to encoded data. + +use crate::traits::{IntoInternalListReader, IntoInternalStructReader}; + +/// Gets a slice view of the data section of a struct. +pub fn get_struct_data_section<'a, T>(value: T) -> &'a [u8] +where + T: IntoInternalStructReader<'a>, +{ + value + .into_internal_struct_reader() + .get_data_section_as_blob() +} + +/// Gets the pointer section as a list. +pub fn get_struct_pointer_section<'a, T>(value: T) -> crate::any_pointer_list::Reader<'a> +where + T: IntoInternalStructReader<'a>, +{ + crate::any_pointer_list::Reader::new( + value + .into_internal_struct_reader() + .get_pointer_section_as_list(), + ) +} + +/// Gets the size of the elements in a list. +pub fn get_list_element_size<'a, T>(value: T) -> crate::private::layout::ElementSize +where + T: IntoInternalListReader<'a>, +{ + value.into_internal_list_reader().get_element_size() +} + +/// Gets the number of bits between successive elements in a list. +pub fn get_list_step_size_in_bits<'a, T>(value: T) -> u32 +where + T: IntoInternalListReader<'a>, +{ + value.into_internal_list_reader().get_step_size_in_bits() +} + +/// Gets a slice view of a list, excluding any tag word. +pub fn get_list_bytes<'a, T>(value: T) -> &'a [u8] +where + T: IntoInternalListReader<'a>, +{ + value.into_internal_list_reader().into_raw_bytes() +} diff --git a/rust/capnp/schema.rs b/rust/capnp/schema.rs new file mode 100644 index 000000000000..4120868f4051 --- /dev/null +++ b/rust/capnp/schema.rs @@ -0,0 +1,430 @@ +//! Convenience wrappers of the datatypes defined in schema.capnp. + +use crate::dynamic_value; +use crate::introspect::{self, RawBrandedStructSchema, RawEnumSchema}; +use crate::private::layout; +use crate::schema_capnp::{annotation, enumerant, field, node}; +use crate::struct_list; +use crate::traits::{IndexMove, ListIter, ShortListIter}; +use crate::Result; + +/// A struct node, with generics applied. +#[derive(Clone, Copy)] +pub struct StructSchema { + pub(crate) raw: RawBrandedStructSchema, + pub(crate) proto: node::Reader<'static>, +} + +impl StructSchema { + pub fn new(raw: RawBrandedStructSchema) -> Self { + let proto = + crate::any_pointer::Reader::new(unsafe { + layout::PointerReader::get_root_unchecked( + raw.generic.encoded_node.as_ptr() as *const u8 + ) + }) + .get_as() + .unwrap(); + Self { raw, proto } + } + + pub fn get_proto(&self) -> node::Reader<'static> { + self.proto + } + + pub fn get_fields(self) -> crate::Result { + if let node::Struct(s) = self.proto.which()? { + Ok(FieldList { + fields: s.get_fields()?, + parent: self, + }) + } else { + panic!() + } + } + + pub fn get_field_by_discriminant(self, discriminant: u16) -> Result> { + match self + .raw + .generic + .members_by_discriminant + .get(discriminant as usize) + { + None => Ok(None), + Some(&idx) => Ok(Some(self.get_fields()?.get(idx))), + } + } + + /// Looks up a field by name. Returns `None` if no matching field is found. + pub fn find_field_by_name(&self, name: &str) -> Result> { + for field in self.get_fields()? { + if field.get_proto().get_name()? == name { + return Ok(Some(field)); + } + } + Ok(None) + } + + /// Like `find_field_by_name()`, but returns an error if the field is not found. + pub fn get_field_by_name(&self, name: &str) -> Result { + if let Some(field) = self.find_field_by_name(name)? { + Ok(field) + } else { + let mut error = crate::Error::from_kind(crate::ErrorKind::FieldNotFound); + write!(error, "{}", name); + Err(error) + } + } + + pub fn get_union_fields(self) -> Result { + if let node::Struct(s) = self.proto.which()? { + Ok(FieldSubset { + fields: s.get_fields()?, + indices: self.raw.generic.members_by_discriminant, + parent: self, + }) + } else { + panic!() + } + } + + pub fn get_non_union_fields(self) -> Result { + if let node::Struct(s) = self.proto.which()? { + Ok(FieldSubset { + fields: s.get_fields()?, + indices: self.raw.generic.nonunion_members, + parent: self, + }) + } else { + panic!() + } + } + + pub fn get_annotations(self) -> Result { + Ok(AnnotationList { + annotations: self.proto.get_annotations()?, + child_index: None, + get_annotation_type: self.raw.annotation_types, + }) + } +} + +impl From for StructSchema { + fn from(rs: RawBrandedStructSchema) -> StructSchema { + StructSchema::new(rs) + } +} + +/// A field of a struct, with generics applied. +#[derive(Clone, Copy)] +pub struct Field { + proto: field::Reader<'static>, + index: u16, + pub(crate) parent: StructSchema, +} + +impl Field { + pub fn get_proto(self) -> field::Reader<'static> { + self.proto + } + + pub fn get_type(&self) -> introspect::Type { + (self.parent.raw.field_types)(self.index) + } + + pub fn get_index(&self) -> u16 { + self.index + } + + pub fn get_annotations(self) -> Result { + Ok(AnnotationList { + annotations: self.proto.get_annotations()?, + child_index: Some(self.index), + get_annotation_type: self.parent.raw.annotation_types, + }) + } +} + +/// A list of fields of a struct, with generics applied. +#[derive(Clone, Copy)] +pub struct FieldList { + pub(crate) fields: crate::struct_list::Reader<'static, field::Owned>, + pub(crate) parent: StructSchema, +} + +impl FieldList { + pub fn len(&self) -> u16 { + self.fields.len() as u16 + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn get(self, index: u16) -> Field { + Field { + proto: self.fields.get(index as u32), + index, + parent: self.parent, + } + } + + pub fn iter(self) -> ShortListIter { + ShortListIter::new(self, self.len()) + } +} + +impl IndexMove for FieldList { + fn index_move(&self, index: u16) -> Field { + self.get(index) + } +} + +impl ::core::iter::IntoIterator for FieldList { + type Item = Field; + type IntoIter = ShortListIter; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// A list of a subset of fields of a struct, with generics applied. +#[derive(Clone, Copy)] +pub struct FieldSubset { + fields: struct_list::Reader<'static, field::Owned>, + indices: &'static [u16], + parent: StructSchema, +} + +impl FieldSubset { + pub fn len(&self) -> u16 { + self.indices.len() as u16 + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn get(self, index: u16) -> Field { + let index = self.indices[index as usize]; + Field { + proto: self.fields.get(index as u32), + index, + parent: self.parent, + } + } + + pub fn iter(self) -> ShortListIter { + ShortListIter::new(self, self.len()) + } +} + +impl IndexMove for FieldSubset { + fn index_move(&self, index: u16) -> Field { + self.get(index) + } +} + +impl ::core::iter::IntoIterator for FieldSubset { + type Item = Field; + type IntoIter = ShortListIter; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// An enum, with generics applied. (Generics may affect types of annotations.) +#[derive(Clone, Copy)] +pub struct EnumSchema { + pub(crate) raw: RawEnumSchema, + pub(crate) proto: node::Reader<'static>, +} + +impl EnumSchema { + pub fn new(raw: RawEnumSchema) -> Self { + let proto = crate::any_pointer::Reader::new(unsafe { + layout::PointerReader::get_root_unchecked(raw.encoded_node.as_ptr() as *const u8) + }) + .get_as() + .unwrap(); + Self { raw, proto } + } + + pub fn get_proto(self) -> node::Reader<'static> { + self.proto + } + + pub fn get_enumerants(self) -> crate::Result { + if let node::Enum(s) = self.proto.which()? { + Ok(EnumerantList { + enumerants: s.get_enumerants()?, + parent: self, + }) + } else { + panic!() + } + } + + pub fn get_annotations(self) -> Result { + Ok(AnnotationList { + annotations: self.proto.get_annotations()?, + child_index: None, + get_annotation_type: self.raw.annotation_types, + }) + } +} + +impl From for EnumSchema { + fn from(re: RawEnumSchema) -> EnumSchema { + EnumSchema::new(re) + } +} + +/// An enumerant, with generics applied. (Generics may affect types of annotations.) +#[derive(Clone, Copy)] +pub struct Enumerant { + ordinal: u16, + parent: EnumSchema, + proto: enumerant::Reader<'static>, +} + +impl Enumerant { + pub fn get_containing_enum(self) -> EnumSchema { + self.parent + } + + pub fn get_ordinal(self) -> u16 { + self.ordinal + } + + pub fn get_proto(self) -> enumerant::Reader<'static> { + self.proto + } + + pub fn get_annotations(self) -> Result { + Ok(AnnotationList { + annotations: self.proto.get_annotations()?, + child_index: Some(self.ordinal), + get_annotation_type: self.parent.raw.annotation_types, + }) + } +} + +/// A list of enumerants. +#[derive(Clone, Copy)] +pub struct EnumerantList { + enumerants: struct_list::Reader<'static, enumerant::Owned>, + parent: EnumSchema, +} + +impl EnumerantList { + pub fn len(&self) -> u16 { + self.enumerants.len() as u16 + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn get(self, ordinal: u16) -> Enumerant { + Enumerant { + proto: self.enumerants.get(ordinal as u32), + ordinal, + parent: self.parent, + } + } + + pub fn iter(self) -> ShortListIter { + ShortListIter::new(self, self.len()) + } +} + +impl IndexMove for EnumerantList { + fn index_move(&self, index: u16) -> Enumerant { + self.get(index) + } +} + +impl ::core::iter::IntoIterator for EnumerantList { + type Item = Enumerant; + type IntoIter = ShortListIter; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// An annotation. +#[derive(Clone, Copy)] +pub struct Annotation { + proto: annotation::Reader<'static>, + ty: introspect::Type, +} + +impl Annotation { + /// Gets the value held in this annotation. + pub fn get_value(self) -> Result> { + dynamic_value::Reader::new(self.proto.get_value()?, self.ty) + } + + /// Gets the ID of the annotation node. + pub fn get_id(&self) -> u64 { + self.proto.get_id() + } + + /// Gets the type of the value held in this annotation. + pub fn get_type(&self) -> introspect::Type { + self.ty + } +} + +/// A list of annotations. +#[derive(Clone, Copy)] +pub struct AnnotationList { + annotations: struct_list::Reader<'static, annotation::Owned>, + child_index: Option, + get_annotation_type: fn(Option, u32) -> introspect::Type, +} + +impl AnnotationList { + pub fn len(&self) -> u32 { + self.annotations.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn get(self, index: u32) -> Annotation { + let proto = self.annotations.get(index); + let ty = (self.get_annotation_type)(self.child_index, index); + Annotation { proto, ty } + } + + /// Returns the first annotation in the list that matches `id`. + /// Otherwise returns `None`. + pub fn find(self, id: u64) -> Option { + self.iter().find(|&annotation| annotation.get_id() == id) + } + + pub fn iter(self) -> ListIter { + ListIter::new(self, self.len()) + } +} + +impl IndexMove for AnnotationList { + fn index_move(&self, index: u32) -> Annotation { + self.get(index) + } +} + +impl ::core::iter::IntoIterator for AnnotationList { + type Item = Annotation; + type IntoIter = ListIter; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} diff --git a/rust/capnp/schema_capnp.rs b/rust/capnp/schema_capnp.rs new file mode 100644 index 000000000000..4f92ee288821 --- /dev/null +++ b/rust/capnp/schema_capnp.rs @@ -0,0 +1,14448 @@ +// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. +// DO NOT EDIT. +// source: schema.capnp + +pub mod node { + pub use self::Which::{Annotation, Const, Enum, File, Interface, Struct}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_display_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_display_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_display_name_prefix_length(self) -> u32 { + self.reader.get_data_field::(2) + } + #[inline] + pub fn get_scope_id(self) -> u64 { + self.reader.get_data_field::(2) + } + #[inline] + pub fn get_nested_nodes( + self, + ) -> crate::Result< + crate::struct_list::Reader<'a, crate::schema_capnp::node::nested_node::Owned>, + > { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_nested_nodes(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + #[inline] + pub fn get_parameters( + self, + ) -> crate::Result< + crate::struct_list::Reader<'a, crate::schema_capnp::node::parameter::Owned>, + > { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(5), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_parameters(&self) -> bool { + !self.reader.get_pointer_field(5).is_null() + } + #[inline] + pub fn get_is_generic(self) -> bool { + self.reader.get_bool_field(288) + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(6) { + 0 => ::core::result::Result::Ok(File(())), + 1 => ::core::result::Result::Ok(Struct(self.reader.into())), + 2 => ::core::result::Result::Ok(Enum(self.reader.into())), + 3 => ::core::result::Result::Ok(Interface(self.reader.into())), + 4 => ::core::result::Result::Ok(Const(self.reader.into())), + 5 => ::core::result::Result::Ok(Annotation(self.reader.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 5, + pointers: 6, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_display_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_display_name(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_display_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_display_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_display_name_prefix_length(self) -> u32 { + self.builder.get_data_field::(2) + } + #[inline] + pub fn set_display_name_prefix_length(&mut self, value: u32) { + self.builder.set_data_field::(2, value); + } + #[inline] + pub fn get_scope_id(self) -> u64 { + self.builder.get_data_field::(2) + } + #[inline] + pub fn set_scope_id(&mut self, value: u64) { + self.builder.set_data_field::(2, value); + } + #[inline] + pub fn get_nested_nodes( + self, + ) -> crate::Result< + crate::struct_list::Builder<'a, crate::schema_capnp::node::nested_node::Owned>, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_nested_nodes( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::node::nested_node::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_nested_nodes( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::node::nested_node::Owned> + { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_nested_nodes(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_annotations( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::annotation::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(2), + value, + false, + ) + } + #[inline] + pub fn init_annotations( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::annotation::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), size) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.builder.is_pointer_field_null(2) + } + #[inline] + pub fn set_file(&mut self, _value: ()) { + self.builder.set_data_field::(6, 0); + } + #[inline] + pub fn init_struct(mut self) -> crate::schema_capnp::node::struct_::Builder<'a> { + self.builder.set_data_field::(6, 1); + self.builder.set_data_field::(7, 0u16); + self.builder.set_data_field::(12, 0u16); + self.builder.set_data_field::(13, 0u16); + self.builder.set_bool_field(224, false); + self.builder.set_data_field::(15, 0u16); + self.builder.set_data_field::(8, 0u32); + self.builder.reborrow().get_pointer_field(3).clear(); + self.builder.into() + } + #[inline] + pub fn init_enum(mut self) -> crate::schema_capnp::node::enum_::Builder<'a> { + self.builder.set_data_field::(6, 2); + self.builder.reborrow().get_pointer_field(3).clear(); + self.builder.into() + } + #[inline] + pub fn init_interface(mut self) -> crate::schema_capnp::node::interface::Builder<'a> { + self.builder.set_data_field::(6, 3); + self.builder.reborrow().get_pointer_field(3).clear(); + self.builder.reborrow().get_pointer_field(4).clear(); + self.builder.into() + } + #[inline] + pub fn init_const(mut self) -> crate::schema_capnp::node::const_::Builder<'a> { + self.builder.set_data_field::(6, 4); + self.builder.reborrow().get_pointer_field(3).clear(); + self.builder.reborrow().get_pointer_field(4).clear(); + self.builder.into() + } + #[inline] + pub fn init_annotation(mut self) -> crate::schema_capnp::node::annotation::Builder<'a> { + self.builder.set_data_field::(6, 5); + self.builder.reborrow().get_pointer_field(3).clear(); + self.builder.set_bool_field(112, false); + self.builder.set_bool_field(113, false); + self.builder.set_bool_field(114, false); + self.builder.set_bool_field(115, false); + self.builder.set_bool_field(116, false); + self.builder.set_bool_field(117, false); + self.builder.set_bool_field(118, false); + self.builder.set_bool_field(119, false); + self.builder.set_bool_field(120, false); + self.builder.set_bool_field(121, false); + self.builder.set_bool_field(122, false); + self.builder.set_bool_field(123, false); + self.builder.into() + } + #[inline] + pub fn get_parameters( + self, + ) -> crate::Result< + crate::struct_list::Builder<'a, crate::schema_capnp::node::parameter::Owned>, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(5), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_parameters( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::node::parameter::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(5), + value, + false, + ) + } + #[inline] + pub fn init_parameters( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::node::parameter::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(5), size) + } + #[inline] + pub fn has_parameters(&self) -> bool { + !self.builder.is_pointer_field_null(5) + } + #[inline] + pub fn get_is_generic(self) -> bool { + self.builder.get_bool_field(288) + } + #[inline] + pub fn set_is_generic(&mut self, value: bool) { + self.builder.set_bool_field(288, value); + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(6) { + 0 => ::core::result::Result::Ok(File(())), + 1 => ::core::result::Result::Ok(Struct(self.builder.into())), + 2 => ::core::result::Result::Ok(Enum(self.builder.into())), + 3 => ::core::result::Result::Ok(Interface(self.builder.into())), + 4 => ::core::result::Result::Ok(Const(self.builder.into())), + 5 => ::core::result::Result::Ok(Annotation(self.builder.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 225] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(13, 0, 0, 0, 1, 0, 5, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(6, 0, 7, 0, 0, 0, 6, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 146, 0, 0, 0), + crate::word(29, 0, 0, 0, 55, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 23, 3, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 1, 0, 1, 0), + crate::word(177, 163, 15, 241, 204, 27, 82, 185), + crate::word(17, 0, 0, 0, 82, 0, 0, 0), + crate::word(66, 194, 15, 250, 187, 85, 191, 222), + crate::word(17, 0, 0, 0, 90, 0, 0, 0), + crate::word(174, 87, 19, 4, 227, 29, 142, 243), + crate::word(17, 0, 0, 0, 90, 0, 0, 0), + crate::word(80, 97, 114, 97, 109, 101, 116, 101), + crate::word(114, 0, 0, 0, 0, 0, 0, 0), + crate::word(78, 101, 115, 116, 101, 100, 78, 111), + crate::word(100, 101, 0, 0, 0, 0, 0, 0), + crate::word(83, 111, 117, 114, 99, 101, 73, 110), + crate::word(102, 111, 0, 0, 0, 0, 0, 0), + crate::word(56, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(121, 1, 0, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 1, 0, 0, 3, 0, 1, 0), + crate::word(128, 1, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(125, 1, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(124, 1, 0, 0, 3, 0, 1, 0), + crate::word(136, 1, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(133, 1, 0, 0, 194, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(136, 1, 0, 0, 3, 0, 1, 0), + crate::word(148, 1, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 3, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(145, 1, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(140, 1, 0, 0, 3, 0, 1, 0), + crate::word(152, 1, 0, 0, 2, 0, 1, 0), + crate::word(6, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 4, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(149, 1, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(148, 1, 0, 0, 3, 0, 1, 0), + crate::word(176, 1, 0, 0, 2, 0, 1, 0), + crate::word(7, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 5, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(173, 1, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(172, 1, 0, 0, 3, 0, 1, 0), + crate::word(200, 1, 0, 0, 2, 0, 1, 0), + crate::word(8, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 6, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(197, 1, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(192, 1, 0, 0, 3, 0, 1, 0), + crate::word(204, 1, 0, 0, 2, 0, 1, 0), + crate::word(9, 0, 254, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(53, 68, 251, 55, 155, 177, 160, 158), + crate::word(201, 1, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(10, 0, 253, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(152, 245, 51, 67, 54, 179, 74, 181), + crate::word(177, 1, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(11, 0, 252, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(143, 33, 194, 240, 207, 83, 39, 232), + crate::word(153, 1, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 251, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(32, 148, 13, 122, 172, 165, 138, 177), + crate::word(133, 1, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 250, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(144, 2, 10, 64, 212, 25, 22, 236), + crate::word(109, 1, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 5, 0, 0, 0), + crate::word(0, 0, 1, 0, 32, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(89, 1, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(88, 1, 0, 0, 3, 0, 1, 0), + crate::word(116, 1, 0, 0, 2, 0, 1, 0), + crate::word(5, 0, 0, 0, 32, 1, 0, 0), + crate::word(0, 0, 1, 0, 33, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(113, 1, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 1, 0, 0, 3, 0, 1, 0), + crate::word(124, 1, 0, 0, 2, 0, 1, 0), + crate::word(105, 100, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 105, 115, 112, 108, 97, 121, 78), + crate::word(97, 109, 101, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 105, 115, 112, 108, 97, 121, 78), + crate::word(97, 109, 101, 80, 114, 101, 102, 105), + crate::word(120, 76, 101, 110, 103, 116, 104, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 111, 112, 101, 73, 100, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(110, 101, 115, 116, 101, 100, 78, 111), + crate::word(100, 101, 115, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(66, 194, 15, 250, 187, 85, 191, 222), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 110, 110, 111, 116, 97, 116, 105), + crate::word(111, 110, 115, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(66, 117, 37, 171, 13, 149, 200, 241), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 105, 108, 101, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 116, 114, 117, 99, 116, 0, 0), + crate::word(101, 110, 117, 109, 0, 0, 0, 0), + crate::word(105, 110, 116, 101, 114, 102, 97, 99), + crate::word(101, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 111, 110, 115, 116, 0, 0, 0), + crate::word(97, 110, 110, 111, 116, 97, 116, 105), + crate::word(111, 110, 0, 0, 0, 0, 0, 0), + crate::word(112, 97, 114, 97, 109, 101, 116, 101), + crate::word(114, 115, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(177, 163, 15, 241, 204, 27, 82, 185), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 115, 71, 101, 110, 101, 114, 105), + crate::word(99, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => as crate::introspect::Introspect>::introspect(), + 5 => as crate::introspect::Introspect>::introspect(), + 6 => <() as crate::introspect::Introspect>::introspect(), + 7 => ::introspect(), + 8 => ::introspect(), + 9 => ::introspect(), + 10 => ::introspect(), + 11 => ::introspect(), + 12 => as crate::introspect::Introspect>::introspect(), + 13 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3, 4, 5, 12, 13]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[6, 7, 8, 9, 10, 11]; + pub const TYPE_ID: u64 = 0xe682_ab4c_f923_a417; + } + pub enum Which { + File(()), + Struct(A0), + Enum(A1), + Interface(A2), + Const(A3), + Annotation(A4), + } + pub type WhichReader<'a> = Which< + crate::schema_capnp::node::struct_::Reader<'a>, + crate::schema_capnp::node::enum_::Reader<'a>, + crate::schema_capnp::node::interface::Reader<'a>, + crate::schema_capnp::node::const_::Reader<'a>, + crate::schema_capnp::node::annotation::Reader<'a>, + >; + pub type WhichBuilder<'a> = Which< + crate::schema_capnp::node::struct_::Builder<'a>, + crate::schema_capnp::node::enum_::Builder<'a>, + crate::schema_capnp::node::interface::Builder<'a>, + crate::schema_capnp::node::const_::Builder<'a>, + crate::schema_capnp::node::annotation::Builder<'a>, + >; + + pub mod parameter { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 0, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 33] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(177, 163, 15, 241, 204, 27, 82, 185), + crate::word(18, 0, 0, 0, 1, 0, 0, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(1, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 226, 0, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 80, 97, 114, 97, 109, 101), + crate::word(116, 101, 114, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 1, 0), + crate::word(20, 0, 0, 0, 2, 0, 1, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xb952_1bcc_f10f_a3b1; + } + } + + pub mod nested_node { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_id(self) -> u64 { + self.reader.get_data_field::(0) + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 48] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(66, 194, 15, 250, 187, 85, 191, 222), + crate::word(18, 0, 0, 0, 1, 0, 1, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(1, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 234, 0, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 78, 101, 115, 116, 101, 100), + crate::word(78, 111, 100, 101, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 100, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xdebf_55bb_fa0f_c242; + } + } + + pub mod source_info { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_doc_comment(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_doc_comment(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_members( + self, + ) -> crate::Result< + crate::struct_list::Reader< + 'a, + crate::schema_capnp::node::source_info::member::Owned, + >, + > { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_members(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 2, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_doc_comment(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_doc_comment(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_doc_comment(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_doc_comment(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_members( + self, + ) -> crate::Result< + crate::struct_list::Builder< + 'a, + crate::schema_capnp::node::source_info::member::Owned, + >, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_members( + &mut self, + value: crate::struct_list::Reader< + 'a, + crate::schema_capnp::node::source_info::member::Owned, + >, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_members( + self, + size: u32, + ) -> crate::struct_list::Builder< + 'a, + crate::schema_capnp::node::source_info::member::Owned, + > { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(1), + size, + ) + } + #[inline] + pub fn has_members(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 71] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(174, 87, 19, 4, 227, 29, 142, 243), + crate::word(18, 0, 0, 0, 1, 0, 1, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(2, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 234, 0, 0, 0), + crate::word(33, 0, 0, 0, 23, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 175, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 83, 111, 117, 114, 99, 101), + crate::word(73, 110, 102, 111, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 1, 0, 1, 0), + crate::word(162, 31, 142, 137, 56, 144, 186, 194), + crate::word(1, 0, 0, 0, 58, 0, 0, 0), + crate::word(77, 101, 109, 98, 101, 114, 0, 0), + crate::word(12, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(69, 0, 0, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(64, 0, 0, 0, 3, 0, 1, 0), + crate::word(76, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(72, 0, 0, 0, 3, 0, 1, 0), + crate::word(84, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(81, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(76, 0, 0, 0, 3, 0, 1, 0), + crate::word(104, 0, 0, 0, 2, 0, 1, 0), + crate::word(105, 100, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 111, 99, 67, 111, 109, 109, 101), + crate::word(110, 116, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(109, 101, 109, 98, 101, 114, 115, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(162, 31, 142, 137, 56, 144, 186, 194), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xf38e_1de3_0413_57ae; + } + + pub mod member { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_doc_comment(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_doc_comment(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 0, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_doc_comment(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_doc_comment(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_doc_comment(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_doc_comment(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 35] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(162, 31, 142, 137, 56, 144, 186, 194), + crate::word(29, 0, 0, 0, 1, 0, 0, 0), + crate::word(174, 87, 19, 4, 227, 29, 142, 243), + crate::word(1, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 34, 1, 0, 0), + crate::word(37, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(33, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 83, 111, 117, 114, 99, 101), + crate::word(73, 110, 102, 111, 46, 77, 101, 109), + crate::word(98, 101, 114, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 3, 0, 1, 0), + crate::word(24, 0, 0, 0, 2, 0, 1, 0), + crate::word(100, 111, 99, 67, 111, 109, 109, 101), + crate::word(110, 116, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xc2ba_9038_898e_1fa2; + } + } + } + + pub mod struct_ { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_data_word_count(self) -> u16 { + self.reader.get_data_field::(7) + } + #[inline] + pub fn get_pointer_count(self) -> u16 { + self.reader.get_data_field::(12) + } + #[inline] + pub fn get_preferred_list_encoding( + self, + ) -> ::core::result::Result + { + ::core::convert::TryInto::try_into(self.reader.get_data_field::(13)) + } + #[inline] + pub fn get_is_group(self) -> bool { + self.reader.get_bool_field(224) + } + #[inline] + pub fn get_discriminant_count(self) -> u16 { + self.reader.get_data_field::(15) + } + #[inline] + pub fn get_discriminant_offset(self) -> u32 { + self.reader.get_data_field::(8) + } + #[inline] + pub fn get_fields( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_fields(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 5, + pointers: 6, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_data_word_count(self) -> u16 { + self.builder.get_data_field::(7) + } + #[inline] + pub fn set_data_word_count(&mut self, value: u16) { + self.builder.set_data_field::(7, value); + } + #[inline] + pub fn get_pointer_count(self) -> u16 { + self.builder.get_data_field::(12) + } + #[inline] + pub fn set_pointer_count(&mut self, value: u16) { + self.builder.set_data_field::(12, value); + } + #[inline] + pub fn get_preferred_list_encoding( + self, + ) -> ::core::result::Result + { + ::core::convert::TryInto::try_into(self.builder.get_data_field::(13)) + } + #[inline] + pub fn set_preferred_list_encoding(&mut self, value: crate::schema_capnp::ElementSize) { + self.builder.set_data_field::(13, value as u16); + } + #[inline] + pub fn get_is_group(self) -> bool { + self.builder.get_bool_field(224) + } + #[inline] + pub fn set_is_group(&mut self, value: bool) { + self.builder.set_bool_field(224, value); + } + #[inline] + pub fn get_discriminant_count(self) -> u16 { + self.builder.get_data_field::(15) + } + #[inline] + pub fn set_discriminant_count(&mut self, value: u16) { + self.builder.set_data_field::(15, value); + } + #[inline] + pub fn get_discriminant_offset(self) -> u32 { + self.builder.get_data_field::(8) + } + #[inline] + pub fn set_discriminant_offset(&mut self, value: u32) { + self.builder.set_data_field::(8, value); + } + #[inline] + pub fn get_fields( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_fields( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::field::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_fields( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::field::Owned> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(3), + size, + ) + } + #[inline] + pub fn has_fields(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 134] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(53, 68, 251, 55, 155, 177, 160, 158), + crate::word(18, 0, 0, 0, 1, 0, 5, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(6, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 202, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 143, 1, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 115, 116, 114, 117, 99, 116), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(28, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 1, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(181, 0, 0, 0, 114, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(180, 0, 0, 0, 3, 0, 1, 0), + crate::word(192, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 12, 0, 0, 0), + crate::word(0, 0, 1, 0, 8, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(189, 0, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(188, 0, 0, 0, 3, 0, 1, 0), + crate::word(200, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 13, 0, 0, 0), + crate::word(0, 0, 1, 0, 9, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(197, 0, 0, 0, 178, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(200, 0, 0, 0, 3, 0, 1, 0), + crate::word(212, 0, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 0, 0, 224, 0, 0, 0), + crate::word(0, 0, 1, 0, 10, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(209, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(204, 0, 0, 0, 3, 0, 1, 0), + crate::word(216, 0, 0, 0, 2, 0, 1, 0), + crate::word(4, 0, 0, 0, 15, 0, 0, 0), + crate::word(0, 0, 1, 0, 11, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(213, 0, 0, 0, 146, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(216, 0, 0, 0, 3, 0, 1, 0), + crate::word(228, 0, 0, 0, 2, 0, 1, 0), + crate::word(5, 0, 0, 0, 8, 0, 0, 0), + crate::word(0, 0, 1, 0, 12, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(225, 0, 0, 0, 154, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(228, 0, 0, 0, 3, 0, 1, 0), + crate::word(240, 0, 0, 0, 2, 0, 1, 0), + crate::word(6, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 13, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(237, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(232, 0, 0, 0, 3, 0, 1, 0), + crate::word(4, 1, 0, 0, 2, 0, 1, 0), + crate::word(100, 97, 116, 97, 87, 111, 114, 100), + crate::word(67, 111, 117, 110, 116, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 111, 105, 110, 116, 101, 114, 67), + crate::word(111, 117, 110, 116, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 114, 101, 102, 101, 114, 114, 101), + crate::word(100, 76, 105, 115, 116, 69, 110, 99), + crate::word(111, 100, 105, 110, 103, 0, 0, 0), + crate::word(15, 0, 0, 0, 0, 0, 0, 0), + crate::word(38, 25, 82, 186, 125, 143, 149, 209), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(15, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 115, 71, 114, 111, 117, 112, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 105, 115, 99, 114, 105, 109, 105), + crate::word(110, 97, 110, 116, 67, 111, 117, 110), + crate::word(116, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 105, 115, 99, 114, 105, 109, 105), + crate::word(110, 97, 110, 116, 79, 102, 102, 115), + crate::word(101, 116, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 105, 101, 108, 100, 115, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(95, 244, 74, 31, 164, 80, 173, 154), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => ::introspect(), + 5 => ::introspect(), + 6 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3, 4, 5, 6]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x9ea0_b19b_37fb_4435; + } + } + + pub mod enum_ { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_enumerants( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_enumerants(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 5, + pointers: 6, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_enumerants( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_enumerants( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::enumerant::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_enumerants( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::enumerant::Owned> + { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(3), + size, + ) + } + #[inline] + pub fn has_enumerants(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 36] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(152, 245, 51, 67, 54, 179, 74, 181), + crate::word(18, 0, 0, 0, 1, 0, 5, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(6, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 186, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 101, 110, 117, 109, 0, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 14, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 3, 0, 1, 0), + crate::word(40, 0, 0, 0, 2, 0, 1, 0), + crate::word(101, 110, 117, 109, 101, 114, 97, 110), + crate::word(116, 115, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(77, 154, 84, 220, 235, 124, 138, 151), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xb54a_b336_4333_f598; + } + } + + pub mod interface { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_methods( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_methods(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + #[inline] + pub fn get_superclasses( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(4), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_superclasses(&self) -> bool { + !self.reader.get_pointer_field(4).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 5, + pointers: 6, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_methods( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_methods( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::method::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_methods( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::method::Owned> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(3), + size, + ) + } + #[inline] + pub fn has_methods(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + #[inline] + pub fn get_superclasses( + self, + ) -> crate::Result< + crate::struct_list::Builder<'a, crate::schema_capnp::superclass::Owned>, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(4), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_superclasses( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::superclass::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(4), + value, + false, + ) + } + #[inline] + pub fn init_superclasses( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::superclass::Owned> + { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(4), + size, + ) + } + #[inline] + pub fn has_superclasses(&self) -> bool { + !self.builder.is_pointer_field_null(4) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 56] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(143, 33, 194, 240, 207, 83, 39, 232), + crate::word(18, 0, 0, 0, 1, 0, 5, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(6, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 226, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 105, 110, 116, 101, 114, 102), + crate::word(97, 99, 101, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 15, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(64, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 4, 0, 0, 0), + crate::word(0, 0, 1, 0, 31, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(61, 0, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(60, 0, 0, 0, 3, 0, 1, 0), + crate::word(88, 0, 0, 0, 2, 0, 1, 0), + crate::word(109, 101, 116, 104, 111, 100, 115, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(128, 77, 51, 59, 226, 204, 0, 149), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 117, 112, 101, 114, 99, 108, 97), + crate::word(115, 115, 101, 115, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(248, 215, 164, 208, 158, 42, 150, 169), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => as crate::introspect::Introspect>::introspect(), + 1 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xe827_53cf_f0c2_218f; + } + } + + pub mod const_ { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_type(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_type(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + #[inline] + pub fn get_value(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(4), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(4).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 5, + pointers: 6, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_type(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_type( + &mut self, + value: crate::schema_capnp::type_::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_type(self) -> crate::schema_capnp::type_::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(3), + 0, + ) + } + #[inline] + pub fn has_type(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + #[inline] + pub fn get_value(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(4), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_value( + &mut self, + value: crate::schema_capnp::value::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(4), + value, + false, + ) + } + #[inline] + pub fn init_value(self) -> crate::schema_capnp::value::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(4), + 0, + ) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(4) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_type(&self) -> crate::schema_capnp::type_::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(3)) + } + pub fn get_value(&self) -> crate::schema_capnp::value::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(4)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 46] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(32, 148, 13, 122, 172, 165, 138, 177), + crate::word(18, 0, 0, 0, 1, 0, 5, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(6, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 194, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 99, 111, 110, 115, 116, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 16, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 4, 0, 0, 0), + crate::word(0, 0, 1, 0, 17, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(116, 121, 112, 101, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(118, 97, 108, 117, 101, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(155, 12, 176, 215, 210, 220, 35, 206), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xb18a_a5ac_7a0d_9420; + } + } + + pub mod annotation { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_type(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_type(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + #[inline] + pub fn get_targets_file(self) -> bool { + self.reader.get_bool_field(112) + } + #[inline] + pub fn get_targets_const(self) -> bool { + self.reader.get_bool_field(113) + } + #[inline] + pub fn get_targets_enum(self) -> bool { + self.reader.get_bool_field(114) + } + #[inline] + pub fn get_targets_enumerant(self) -> bool { + self.reader.get_bool_field(115) + } + #[inline] + pub fn get_targets_struct(self) -> bool { + self.reader.get_bool_field(116) + } + #[inline] + pub fn get_targets_field(self) -> bool { + self.reader.get_bool_field(117) + } + #[inline] + pub fn get_targets_union(self) -> bool { + self.reader.get_bool_field(118) + } + #[inline] + pub fn get_targets_group(self) -> bool { + self.reader.get_bool_field(119) + } + #[inline] + pub fn get_targets_interface(self) -> bool { + self.reader.get_bool_field(120) + } + #[inline] + pub fn get_targets_method(self) -> bool { + self.reader.get_bool_field(121) + } + #[inline] + pub fn get_targets_param(self) -> bool { + self.reader.get_bool_field(122) + } + #[inline] + pub fn get_targets_annotation(self) -> bool { + self.reader.get_bool_field(123) + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 5, + pointers: 6, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_type(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_type( + &mut self, + value: crate::schema_capnp::type_::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_type(self) -> crate::schema_capnp::type_::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(3), + 0, + ) + } + #[inline] + pub fn has_type(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + #[inline] + pub fn get_targets_file(self) -> bool { + self.builder.get_bool_field(112) + } + #[inline] + pub fn set_targets_file(&mut self, value: bool) { + self.builder.set_bool_field(112, value); + } + #[inline] + pub fn get_targets_const(self) -> bool { + self.builder.get_bool_field(113) + } + #[inline] + pub fn set_targets_const(&mut self, value: bool) { + self.builder.set_bool_field(113, value); + } + #[inline] + pub fn get_targets_enum(self) -> bool { + self.builder.get_bool_field(114) + } + #[inline] + pub fn set_targets_enum(&mut self, value: bool) { + self.builder.set_bool_field(114, value); + } + #[inline] + pub fn get_targets_enumerant(self) -> bool { + self.builder.get_bool_field(115) + } + #[inline] + pub fn set_targets_enumerant(&mut self, value: bool) { + self.builder.set_bool_field(115, value); + } + #[inline] + pub fn get_targets_struct(self) -> bool { + self.builder.get_bool_field(116) + } + #[inline] + pub fn set_targets_struct(&mut self, value: bool) { + self.builder.set_bool_field(116, value); + } + #[inline] + pub fn get_targets_field(self) -> bool { + self.builder.get_bool_field(117) + } + #[inline] + pub fn set_targets_field(&mut self, value: bool) { + self.builder.set_bool_field(117, value); + } + #[inline] + pub fn get_targets_union(self) -> bool { + self.builder.get_bool_field(118) + } + #[inline] + pub fn set_targets_union(&mut self, value: bool) { + self.builder.set_bool_field(118, value); + } + #[inline] + pub fn get_targets_group(self) -> bool { + self.builder.get_bool_field(119) + } + #[inline] + pub fn set_targets_group(&mut self, value: bool) { + self.builder.set_bool_field(119, value); + } + #[inline] + pub fn get_targets_interface(self) -> bool { + self.builder.get_bool_field(120) + } + #[inline] + pub fn set_targets_interface(&mut self, value: bool) { + self.builder.set_bool_field(120, value); + } + #[inline] + pub fn get_targets_method(self) -> bool { + self.builder.get_bool_field(121) + } + #[inline] + pub fn set_targets_method(&mut self, value: bool) { + self.builder.set_bool_field(121, value); + } + #[inline] + pub fn get_targets_param(self) -> bool { + self.builder.get_bool_field(122) + } + #[inline] + pub fn set_targets_param(&mut self, value: bool) { + self.builder.set_bool_field(122, value); + } + #[inline] + pub fn get_targets_annotation(self) -> bool { + self.builder.get_bool_field(123) + } + #[inline] + pub fn set_targets_annotation(&mut self, value: bool) { + self.builder.set_bool_field(123, value); + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_type(&self) -> crate::schema_capnp::type_::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(3)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 227] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(144, 2, 10, 64, 212, 25, 22, 236), + crate::word(18, 0, 0, 0, 1, 0, 5, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(6, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 234, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 223, 2, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 78, 111, 100), + crate::word(101, 46, 97, 110, 110, 111, 116, 97), + crate::word(116, 105, 111, 110, 0, 0, 0, 0), + crate::word(52, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 18, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(93, 1, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(88, 1, 0, 0, 3, 0, 1, 0), + crate::word(100, 1, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 112, 0, 0, 0), + crate::word(0, 0, 1, 0, 19, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 1, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 1, 0, 0, 3, 0, 1, 0), + crate::word(108, 1, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 113, 0, 0, 0), + crate::word(0, 0, 1, 0, 20, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 1, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(104, 1, 0, 0, 3, 0, 1, 0), + crate::word(116, 1, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 0, 0, 114, 0, 0, 0), + crate::word(0, 0, 1, 0, 21, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(113, 1, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 1, 0, 0, 3, 0, 1, 0), + crate::word(124, 1, 0, 0, 2, 0, 1, 0), + crate::word(4, 0, 0, 0, 115, 0, 0, 0), + crate::word(0, 0, 1, 0, 22, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(121, 1, 0, 0, 138, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(124, 1, 0, 0, 3, 0, 1, 0), + crate::word(136, 1, 0, 0, 2, 0, 1, 0), + crate::word(5, 0, 0, 0, 116, 0, 0, 0), + crate::word(0, 0, 1, 0, 23, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(133, 1, 0, 0, 114, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(132, 1, 0, 0, 3, 0, 1, 0), + crate::word(144, 1, 0, 0, 2, 0, 1, 0), + crate::word(6, 0, 0, 0, 117, 0, 0, 0), + crate::word(0, 0, 1, 0, 24, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(141, 1, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(140, 1, 0, 0, 3, 0, 1, 0), + crate::word(152, 1, 0, 0, 2, 0, 1, 0), + crate::word(7, 0, 0, 0, 118, 0, 0, 0), + crate::word(0, 0, 1, 0, 25, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(149, 1, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(148, 1, 0, 0, 3, 0, 1, 0), + crate::word(160, 1, 0, 0, 2, 0, 1, 0), + crate::word(8, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 1, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(157, 1, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(156, 1, 0, 0, 3, 0, 1, 0), + crate::word(168, 1, 0, 0, 2, 0, 1, 0), + crate::word(9, 0, 0, 0, 120, 0, 0, 0), + crate::word(0, 0, 1, 0, 27, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(165, 1, 0, 0, 138, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(168, 1, 0, 0, 3, 0, 1, 0), + crate::word(180, 1, 0, 0, 2, 0, 1, 0), + crate::word(10, 0, 0, 0, 121, 0, 0, 0), + crate::word(0, 0, 1, 0, 28, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(177, 1, 0, 0, 114, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(176, 1, 0, 0, 3, 0, 1, 0), + crate::word(188, 1, 0, 0, 2, 0, 1, 0), + crate::word(11, 0, 0, 0, 122, 0, 0, 0), + crate::word(0, 0, 1, 0, 29, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(185, 1, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(184, 1, 0, 0, 3, 0, 1, 0), + crate::word(196, 1, 0, 0, 2, 0, 1, 0), + crate::word(12, 0, 0, 0, 123, 0, 0, 0), + crate::word(0, 0, 1, 0, 30, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(193, 1, 0, 0, 146, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(196, 1, 0, 0, 3, 0, 1, 0), + crate::word(208, 1, 0, 0, 2, 0, 1, 0), + crate::word(116, 121, 112, 101, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 70), + crate::word(105, 108, 101, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 67), + crate::word(111, 110, 115, 116, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 69), + crate::word(110, 117, 109, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 69), + crate::word(110, 117, 109, 101, 114, 97, 110, 116), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 83), + crate::word(116, 114, 117, 99, 116, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 70), + crate::word(105, 101, 108, 100, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 85), + crate::word(110, 105, 111, 110, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 71), + crate::word(114, 111, 117, 112, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 73), + crate::word(110, 116, 101, 114, 102, 97, 99, 101), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 77), + crate::word(101, 116, 104, 111, 100, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 80), + crate::word(97, 114, 97, 109, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 97, 114, 103, 101, 116, 115, 65), + crate::word(110, 110, 111, 116, 97, 116, 105, 111), + crate::word(110, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => ::introspect(), + 5 => ::introspect(), + 6 => ::introspect(), + 7 => ::introspect(), + 8 => ::introspect(), + 9 => ::introspect(), + 10 => ::introspect(), + 11 => ::introspect(), + 12 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xec16_19d4_400a_0290; + } + } +} + +pub mod field { + pub use self::Which::{Group, Slot}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_code_order(self) -> u16 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_discriminant_value(self) -> u16 { + self.reader.get_data_field_mask::(1, 65535) + } + #[inline] + pub fn get_ordinal(self) -> crate::schema_capnp::field::ordinal::Reader<'a> { + self.reader.into() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Slot(self.reader.into())), + 1 => ::core::result::Result::Ok(Group(self.reader.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 4, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_code_order(self) -> u16 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_code_order(&mut self, value: u16) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_annotations( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::annotation::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_annotations( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::annotation::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + #[inline] + pub fn get_discriminant_value(self) -> u16 { + self.builder.get_data_field_mask::(1, 65535) + } + #[inline] + pub fn set_discriminant_value(&mut self, value: u16) { + self.builder.set_data_field_mask::(1, value, 65535); + } + #[inline] + pub fn init_slot(mut self) -> crate::schema_capnp::field::slot::Builder<'a> { + self.builder.set_data_field::(4, 0); + self.builder.set_data_field::(1, 0u32); + self.builder.reborrow().get_pointer_field(2).clear(); + self.builder.reborrow().get_pointer_field(3).clear(); + self.builder.set_bool_field(128, false); + self.builder.into() + } + #[inline] + pub fn init_group(self) -> crate::schema_capnp::field::group::Builder<'a> { + self.builder.set_data_field::(4, 1); + self.builder.set_data_field::(2, 0u64); + self.builder.into() + } + #[inline] + pub fn get_ordinal(self) -> crate::schema_capnp::field::ordinal::Builder<'a> { + self.builder.into() + } + #[inline] + pub fn init_ordinal(self) -> crate::schema_capnp::field::ordinal::Builder<'a> { + self.builder.set_data_field::(5, 0); + self.builder.set_data_field::(6, 0u16); + self.builder.into() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Slot(self.builder.into())), + 1 => ::core::result::Result::Ok(Group(self.builder.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_ordinal(&self) -> crate::schema_capnp::field::ordinal::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.noop()) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 113] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(95, 244, 74, 31, 164, 80, 173, 154), + crate::word(13, 0, 0, 0, 1, 0, 3, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(4, 0, 7, 0, 0, 0, 2, 0), + crate::word(4, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 154, 0, 0, 0), + crate::word(29, 0, 0, 0, 23, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 143, 1, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 70, 105, 101), + crate::word(108, 100, 0, 0, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 1, 0, 1, 0), + crate::word(18, 199, 254, 124, 190, 76, 177, 151), + crate::word(1, 0, 0, 0, 122, 0, 0, 0), + crate::word(110, 111, 68, 105, 115, 99, 114, 105), + crate::word(109, 105, 110, 97, 110, 116, 0, 0), + crate::word(28, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(181, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(176, 0, 0, 0, 3, 0, 1, 0), + crate::word(188, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(185, 0, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(184, 0, 0, 0, 3, 0, 1, 0), + crate::word(196, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(193, 0, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(192, 0, 0, 0, 3, 0, 1, 0), + crate::word(220, 0, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 3, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(217, 0, 0, 0, 146, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(220, 0, 0, 0, 3, 0, 1, 0), + crate::word(232, 0, 0, 0, 2, 0, 1, 0), + crate::word(4, 0, 255, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(111, 116, 180, 107, 71, 5, 35, 196), + crate::word(229, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(5, 0, 254, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(17, 29, 219, 104, 219, 205, 252, 202), + crate::word(205, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(230, 11, 135, 135, 194, 213, 144, 187), + crate::word(181, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 111, 100, 101, 79, 114, 100, 101), + crate::word(114, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 110, 110, 111, 116, 97, 116, 105), + crate::word(111, 110, 115, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(66, 117, 37, 171, 13, 149, 200, 241), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 105, 115, 99, 114, 105, 109, 105), + crate::word(110, 97, 110, 116, 86, 97, 108, 117), + crate::word(101, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 108, 111, 116, 0, 0, 0, 0), + crate::word(103, 114, 111, 117, 112, 0, 0, 0), + crate::word(111, 114, 100, 105, 110, 97, 108, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => as crate::introspect::Introspect>::introspect(), + 3 => ::introspect(), + 4 => ::introspect(), + 5 => ::introspect(), + 6 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3, 6]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[4, 5]; + pub const TYPE_ID: u64 = 0x9aad_50a4_1f4a_f45f; + } + pub enum Which { + Slot(A0), + Group(A1), + } + pub type WhichReader<'a> = Which< + crate::schema_capnp::field::slot::Reader<'a>, + crate::schema_capnp::field::group::Reader<'a>, + >; + pub type WhichBuilder<'a> = Which< + crate::schema_capnp::field::slot::Builder<'a>, + crate::schema_capnp::field::group::Builder<'a>, + >; + pub const NO_DISCRIMINANT: u16 = 65535; + + pub mod slot { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_offset(self) -> u32 { + self.reader.get_data_field::(1) + } + #[inline] + pub fn get_type(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_type(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + #[inline] + pub fn get_default_value( + self, + ) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_default_value(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + #[inline] + pub fn get_had_explicit_default(self) -> bool { + self.reader.get_bool_field(128) + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 4, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_offset(self) -> u32 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_offset(&mut self, value: u32) { + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn get_type(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_type( + &mut self, + value: crate::schema_capnp::type_::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(2), + value, + false, + ) + } + #[inline] + pub fn init_type(self) -> crate::schema_capnp::type_::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(2), + 0, + ) + } + #[inline] + pub fn has_type(&self) -> bool { + !self.builder.is_pointer_field_null(2) + } + #[inline] + pub fn get_default_value( + self, + ) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_default_value( + &mut self, + value: crate::schema_capnp::value::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_default_value(self) -> crate::schema_capnp::value::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(3), + 0, + ) + } + #[inline] + pub fn has_default_value(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + #[inline] + pub fn get_had_explicit_default(self) -> bool { + self.builder.get_bool_field(128) + } + #[inline] + pub fn set_had_explicit_default(&mut self, value: bool) { + self.builder.set_bool_field(128, value); + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_type(&self) -> crate::schema_capnp::type_::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2)) + } + pub fn get_default_value(&self) -> crate::schema_capnp::value::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(3)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 79] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(111, 116, 180, 107, 71, 5, 35, 196), + crate::word(19, 0, 0, 0, 1, 0, 3, 0), + crate::word(95, 244, 74, 31, 164, 80, 173, 154), + crate::word(4, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 194, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 231, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 70, 105, 101), + crate::word(108, 100, 46, 115, 108, 111, 116, 0), + crate::word(16, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 4, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(92, 0, 0, 0, 3, 0, 1, 0), + crate::word(104, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 5, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(101, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 0, 0, 0, 3, 0, 1, 0), + crate::word(108, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 6, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 0, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(104, 0, 0, 0, 3, 0, 1, 0), + crate::word(116, 0, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 0, 0, 128, 0, 0, 0), + crate::word(0, 0, 1, 0, 10, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(113, 0, 0, 0, 154, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 0, 0, 0, 3, 0, 1, 0), + crate::word(128, 0, 0, 0, 2, 0, 1, 0), + crate::word(111, 102, 102, 115, 101, 116, 0, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 121, 112, 101, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 101, 102, 97, 117, 108, 116, 86), + crate::word(97, 108, 117, 101, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(155, 12, 176, 215, 210, 220, 35, 206), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(104, 97, 100, 69, 120, 112, 108, 105), + crate::word(99, 105, 116, 68, 101, 102, 97, 117), + crate::word(108, 116, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xc423_0547_6bb4_746f; + } + } + + pub mod group { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.reader.get_data_field::(2) + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 4, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.builder.get_data_field::(2) + } + #[inline] + pub fn set_type_id(&mut self, value: u64) { + self.builder.set_data_field::(2, value); + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 32] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(17, 29, 219, 104, 219, 205, 252, 202), + crate::word(19, 0, 0, 0, 1, 0, 3, 0), + crate::word(95, 244, 74, 31, 164, 80, 173, 154), + crate::word(4, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 202, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 70, 105, 101), + crate::word(108, 100, 46, 103, 114, 111, 117, 112), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 1, 0), + crate::word(20, 0, 0, 0, 2, 0, 1, 0), + crate::word(116, 121, 112, 101, 73, 100, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xcafc_cddb_68db_1d11; + } + } + + pub mod ordinal { + pub use self::Which::{Explicit, Implicit}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn which(self) -> ::core::result::Result { + match self.reader.get_data_field::(5) { + 0 => ::core::result::Result::Ok(Implicit(())), + 1 => ::core::result::Result::Ok(Explicit(self.reader.get_data_field::(6))), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 4, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_implicit(&mut self, _value: ()) { + self.builder.set_data_field::(5, 0); + } + #[inline] + pub fn set_explicit(&mut self, value: u16) { + self.builder.set_data_field::(5, 1); + self.builder.set_data_field::(6, value); + } + #[inline] + pub fn which(self) -> ::core::result::Result { + match self.builder.get_data_field::(5) { + 0 => ::core::result::Result::Ok(Implicit(())), + 1 => { + ::core::result::Result::Ok(Explicit(self.builder.get_data_field::(6))) + } + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 49] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(230, 11, 135, 135, 194, 213, 144, 187), + crate::word(19, 0, 0, 0, 1, 0, 3, 0), + crate::word(95, 244, 74, 31, 164, 80, 173, 154), + crate::word(4, 0, 7, 0, 1, 0, 2, 0), + crate::word(5, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 218, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 70, 105, 101), + crate::word(108, 100, 46, 111, 114, 100, 105, 110), + crate::word(97, 108, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 8, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 74, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 254, 255, 6, 0, 0, 0), + crate::word(0, 0, 1, 0, 9, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 0, 0, 0, 74, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(48, 0, 0, 0, 3, 0, 1, 0), + crate::word(60, 0, 0, 0, 2, 0, 1, 0), + crate::word(105, 109, 112, 108, 105, 99, 105, 116), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(101, 120, 112, 108, 105, 99, 105, 116), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => <() as crate::introspect::Introspect>::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[0, 1]; + pub const TYPE_ID: u64 = 0xbb90_d5c2_8787_0be6; + } + pub enum Which { + Implicit(()), + Explicit(u16), + } + pub type WhichReader = Which; + pub type WhichBuilder = Which; + } +} + +pub mod enumerant { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_code_order(self) -> u16 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 2, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_code_order(self) -> u16 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_code_order(&mut self, value: u16) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_annotations( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::annotation::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_annotations( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::annotation::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 68] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(77, 154, 84, 220, 235, 124, 138, 151), + crate::word(13, 0, 0, 0, 1, 0, 1, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(2, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 186, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 175, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 69, 110, 117), + crate::word(109, 101, 114, 97, 110, 116, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(12, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(69, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(64, 0, 0, 0, 3, 0, 1, 0), + crate::word(76, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(72, 0, 0, 0, 3, 0, 1, 0), + crate::word(84, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(81, 0, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(80, 0, 0, 0, 3, 0, 1, 0), + crate::word(108, 0, 0, 0, 2, 0, 1, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 111, 100, 101, 79, 114, 100, 101), + crate::word(114, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 110, 110, 111, 116, 97, 116, 105), + crate::word(111, 110, 115, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(66, 117, 37, 171, 13, 149, 200, 241), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x978a_7ceb_dc54_9a4d; + } +} + +pub mod superclass { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_brand( + &mut self, + value: crate::schema_capnp::brand::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_brand(self) -> crate::schema_capnp::brand::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_brand(&self) -> crate::schema_capnp::brand::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 47] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(248, 215, 164, 208, 158, 42, 150, 169), + crate::word(13, 0, 0, 0, 1, 0, 1, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(1, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 194, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 83, 117, 112), + crate::word(101, 114, 99, 108, 97, 115, 115, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(105, 100, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 114, 97, 110, 100, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => { + ::introspect( + ) + } + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xa996_2a9e_d0a4_d7f8; + } +} + +pub mod method { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_code_order(self) -> u16 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_param_struct_type(self) -> u64 { + self.reader.get_data_field::(1) + } + #[inline] + pub fn get_result_struct_type(self) -> u64 { + self.reader.get_data_field::(2) + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_param_brand(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_param_brand(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + #[inline] + pub fn get_result_brand(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_result_brand(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + #[inline] + pub fn get_implicit_parameters( + self, + ) -> crate::Result< + crate::struct_list::Reader<'a, crate::schema_capnp::node::parameter::Owned>, + > { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(4), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_implicit_parameters(&self) -> bool { + !self.reader.get_pointer_field(4).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 5, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_code_order(self) -> u16 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_code_order(&mut self, value: u16) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_param_struct_type(self) -> u64 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_param_struct_type(&mut self, value: u64) { + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn get_result_struct_type(self) -> u64 { + self.builder.get_data_field::(2) + } + #[inline] + pub fn set_result_struct_type(&mut self, value: u64) { + self.builder.set_data_field::(2, value); + } + #[inline] + pub fn get_annotations( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_annotations( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::annotation::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_annotations( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::annotation::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_annotations(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + #[inline] + pub fn get_param_brand(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_param_brand( + &mut self, + value: crate::schema_capnp::brand::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(2), + value, + false, + ) + } + #[inline] + pub fn init_param_brand(self) -> crate::schema_capnp::brand::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), 0) + } + #[inline] + pub fn has_param_brand(&self) -> bool { + !self.builder.is_pointer_field_null(2) + } + #[inline] + pub fn get_result_brand(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_result_brand( + &mut self, + value: crate::schema_capnp::brand::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_result_brand(self) -> crate::schema_capnp::brand::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(3), 0) + } + #[inline] + pub fn has_result_brand(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + #[inline] + pub fn get_implicit_parameters( + self, + ) -> crate::Result< + crate::struct_list::Builder<'a, crate::schema_capnp::node::parameter::Owned>, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(4), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_implicit_parameters( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::node::parameter::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(4), + value, + false, + ) + } + #[inline] + pub fn init_implicit_parameters( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::node::parameter::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(4), size) + } + #[inline] + pub fn has_implicit_parameters(&self) -> bool { + !self.builder.is_pointer_field_null(4) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_param_brand(&self) -> crate::schema_capnp::brand::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2)) + } + pub fn get_result_brand(&self) -> crate::schema_capnp::brand::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(3)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 154] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(128, 77, 51, 59, 226, 204, 0, 149), + crate::word(13, 0, 0, 0, 1, 0, 3, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(5, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 162, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 199, 1, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 77, 101, 116), + crate::word(104, 111, 100, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(32, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(209, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(204, 0, 0, 0, 3, 0, 1, 0), + crate::word(216, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(213, 0, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(212, 0, 0, 0, 3, 0, 1, 0), + crate::word(224, 0, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(221, 0, 0, 0, 130, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(220, 0, 0, 0, 3, 0, 1, 0), + crate::word(232, 0, 0, 0, 2, 0, 1, 0), + crate::word(5, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 3, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(229, 0, 0, 0, 138, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(232, 0, 0, 0, 3, 0, 1, 0), + crate::word(244, 0, 0, 0, 2, 0, 1, 0), + crate::word(7, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 4, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(241, 0, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(240, 0, 0, 0, 3, 0, 1, 0), + crate::word(12, 1, 0, 0, 2, 0, 1, 0), + crate::word(4, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 5, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 1, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 1, 0, 0, 3, 0, 1, 0), + crate::word(20, 1, 0, 0, 2, 0, 1, 0), + crate::word(6, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 6, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(17, 1, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 1, 0, 0, 3, 0, 1, 0), + crate::word(28, 1, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 4, 0, 0, 0), + crate::word(0, 0, 1, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 1, 0, 0, 154, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(28, 1, 0, 0, 3, 0, 1, 0), + crate::word(56, 1, 0, 0, 2, 0, 1, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 111, 100, 101, 79, 114, 100, 101), + crate::word(114, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 97, 114, 97, 109, 83, 116, 114), + crate::word(117, 99, 116, 84, 121, 112, 101, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(114, 101, 115, 117, 108, 116, 83, 116), + crate::word(114, 117, 99, 116, 84, 121, 112, 101), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 110, 110, 111, 116, 97, 116, 105), + crate::word(111, 110, 115, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(66, 117, 37, 171, 13, 149, 200, 241), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 97, 114, 97, 109, 66, 114, 97), + crate::word(110, 100, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(114, 101, 115, 117, 108, 116, 66, 114), + crate::word(97, 110, 100, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 109, 112, 108, 105, 99, 105, 116), + crate::word(80, 97, 114, 97, 109, 101, 116, 101), + crate::word(114, 115, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(177, 163, 15, 241, 204, 27, 82, 185), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => as crate::introspect::Introspect>::introspect(), + 5 => ::introspect(), + 6 => ::introspect(), + 7 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3, 4, 5, 6, 7]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x9500_cce2_3b33_4d80; + } +} + +pub mod type_ { + pub use self::Which::{ + AnyPointer, Bool, Data, Enum, Float32, Float64, Int16, Int32, Int64, Int8, Interface, List, + Struct, Text, Uint16, Uint32, Uint64, Uint8, Void, + }; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Void(())), + 1 => ::core::result::Result::Ok(Bool(())), + 2 => ::core::result::Result::Ok(Int8(())), + 3 => ::core::result::Result::Ok(Int16(())), + 4 => ::core::result::Result::Ok(Int32(())), + 5 => ::core::result::Result::Ok(Int64(())), + 6 => ::core::result::Result::Ok(Uint8(())), + 7 => ::core::result::Result::Ok(Uint16(())), + 8 => ::core::result::Result::Ok(Uint32(())), + 9 => ::core::result::Result::Ok(Uint64(())), + 10 => ::core::result::Result::Ok(Float32(())), + 11 => ::core::result::Result::Ok(Float64(())), + 12 => ::core::result::Result::Ok(Text(())), + 13 => ::core::result::Result::Ok(Data(())), + 14 => ::core::result::Result::Ok(List(self.reader.into())), + 15 => ::core::result::Result::Ok(Enum(self.reader.into())), + 16 => ::core::result::Result::Ok(Struct(self.reader.into())), + 17 => ::core::result::Result::Ok(Interface(self.reader.into())), + 18 => ::core::result::Result::Ok(AnyPointer(self.reader.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_void(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_bool(&mut self, _value: ()) { + self.builder.set_data_field::(0, 1); + } + #[inline] + pub fn set_int8(&mut self, _value: ()) { + self.builder.set_data_field::(0, 2); + } + #[inline] + pub fn set_int16(&mut self, _value: ()) { + self.builder.set_data_field::(0, 3); + } + #[inline] + pub fn set_int32(&mut self, _value: ()) { + self.builder.set_data_field::(0, 4); + } + #[inline] + pub fn set_int64(&mut self, _value: ()) { + self.builder.set_data_field::(0, 5); + } + #[inline] + pub fn set_uint8(&mut self, _value: ()) { + self.builder.set_data_field::(0, 6); + } + #[inline] + pub fn set_uint16(&mut self, _value: ()) { + self.builder.set_data_field::(0, 7); + } + #[inline] + pub fn set_uint32(&mut self, _value: ()) { + self.builder.set_data_field::(0, 8); + } + #[inline] + pub fn set_uint64(&mut self, _value: ()) { + self.builder.set_data_field::(0, 9); + } + #[inline] + pub fn set_float32(&mut self, _value: ()) { + self.builder.set_data_field::(0, 10); + } + #[inline] + pub fn set_float64(&mut self, _value: ()) { + self.builder.set_data_field::(0, 11); + } + #[inline] + pub fn set_text(&mut self, _value: ()) { + self.builder.set_data_field::(0, 12); + } + #[inline] + pub fn set_data(&mut self, _value: ()) { + self.builder.set_data_field::(0, 13); + } + #[inline] + pub fn init_list(mut self) -> crate::schema_capnp::type_::list::Builder<'a> { + self.builder.set_data_field::(0, 14); + self.builder.reborrow().get_pointer_field(0).clear(); + self.builder.into() + } + #[inline] + pub fn init_enum(mut self) -> crate::schema_capnp::type_::enum_::Builder<'a> { + self.builder.set_data_field::(0, 15); + self.builder.set_data_field::(1, 0u64); + self.builder.reborrow().get_pointer_field(0).clear(); + self.builder.into() + } + #[inline] + pub fn init_struct(mut self) -> crate::schema_capnp::type_::struct_::Builder<'a> { + self.builder.set_data_field::(0, 16); + self.builder.set_data_field::(1, 0u64); + self.builder.reborrow().get_pointer_field(0).clear(); + self.builder.into() + } + #[inline] + pub fn init_interface(mut self) -> crate::schema_capnp::type_::interface::Builder<'a> { + self.builder.set_data_field::(0, 17); + self.builder.set_data_field::(1, 0u64); + self.builder.reborrow().get_pointer_field(0).clear(); + self.builder.into() + } + #[inline] + pub fn init_any_pointer(self) -> crate::schema_capnp::type_::any_pointer::Builder<'a> { + self.builder.set_data_field::(0, 18); + self.builder.set_data_field::(4, 0); + self.builder.set_data_field::(5, 0); + self.builder.set_data_field::(2, 0u64); + self.builder.set_data_field::(5, 0u16); + self.builder.set_data_field::(5, 0u16); + self.builder.into() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Void(())), + 1 => ::core::result::Result::Ok(Bool(())), + 2 => ::core::result::Result::Ok(Int8(())), + 3 => ::core::result::Result::Ok(Int16(())), + 4 => ::core::result::Result::Ok(Int32(())), + 5 => ::core::result::Result::Ok(Int64(())), + 6 => ::core::result::Result::Ok(Uint8(())), + 7 => ::core::result::Result::Ok(Uint16(())), + 8 => ::core::result::Result::Ok(Uint32(())), + 9 => ::core::result::Result::Ok(Uint64(())), + 10 => ::core::result::Result::Ok(Float32(())), + 11 => ::core::result::Result::Ok(Float64(())), + 12 => ::core::result::Result::Ok(Text(())), + 13 => ::core::result::Result::Ok(Data(())), + 14 => ::core::result::Result::Ok(List(self.builder.into())), + 15 => ::core::result::Result::Ok(Enum(self.builder.into())), + 16 => ::core::result::Result::Ok(Struct(self.builder.into())), + 17 => ::core::result::Result::Ok(Interface(self.builder.into())), + 18 => ::core::result::Result::Ok(AnyPointer(self.builder.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 269] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(13, 0, 0, 0, 1, 0, 3, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(1, 0, 7, 0, 0, 0, 19, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 146, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 47, 4, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(76, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(5, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 2, 0, 0, 3, 0, 1, 0), + crate::word(12, 2, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 254, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 2, 0, 0, 3, 0, 1, 0), + crate::word(16, 2, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 253, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 2, 0, 0, 3, 0, 1, 0), + crate::word(20, 2, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 252, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 3, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(17, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 2, 0, 0, 3, 0, 1, 0), + crate::word(24, 2, 0, 0, 2, 0, 1, 0), + crate::word(4, 0, 251, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 4, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 2, 0, 0, 3, 0, 1, 0), + crate::word(28, 2, 0, 0, 2, 0, 1, 0), + crate::word(5, 0, 250, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 5, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(20, 2, 0, 0, 3, 0, 1, 0), + crate::word(32, 2, 0, 0, 2, 0, 1, 0), + crate::word(6, 0, 249, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 6, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(24, 2, 0, 0, 3, 0, 1, 0), + crate::word(36, 2, 0, 0, 2, 0, 1, 0), + crate::word(7, 0, 248, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(33, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(28, 2, 0, 0, 3, 0, 1, 0), + crate::word(40, 2, 0, 0, 2, 0, 1, 0), + crate::word(8, 0, 247, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 8, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(37, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(32, 2, 0, 0, 3, 0, 1, 0), + crate::word(44, 2, 0, 0, 2, 0, 1, 0), + crate::word(9, 0, 246, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 9, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 2, 0, 0, 3, 0, 1, 0), + crate::word(48, 2, 0, 0, 2, 0, 1, 0), + crate::word(10, 0, 245, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 10, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 2, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 2, 0, 0, 3, 0, 1, 0), + crate::word(52, 2, 0, 0, 2, 0, 1, 0), + crate::word(11, 0, 244, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 11, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 2, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(44, 2, 0, 0, 3, 0, 1, 0), + crate::word(56, 2, 0, 0, 2, 0, 1, 0), + crate::word(12, 0, 243, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 12, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(53, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(48, 2, 0, 0, 3, 0, 1, 0), + crate::word(60, 2, 0, 0, 2, 0, 1, 0), + crate::word(13, 0, 242, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 13, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(57, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(52, 2, 0, 0, 3, 0, 1, 0), + crate::word(64, 2, 0, 0, 2, 0, 1, 0), + crate::word(14, 0, 241, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(151, 234, 96, 10, 37, 57, 231, 135), + crate::word(61, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(15, 0, 240, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(169, 135, 127, 26, 113, 120, 14, 158), + crate::word(37, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 239, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(211, 198, 76, 239, 96, 111, 58, 172), + crate::word(13, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(17, 0, 238, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(191, 12, 251, 247, 105, 202, 139, 237), + crate::word(245, 1, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(18, 0, 237, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(241, 73, 62, 162, 232, 63, 87, 194), + crate::word(225, 1, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(118, 111, 105, 100, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 111, 111, 108, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 56, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 49, 54, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 51, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 54, 52, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 56, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 49, 54, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 51, 50, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 54, 52, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 108, 111, 97, 116, 51, 50, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 108, 111, 97, 116, 54, 52, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 101, 120, 116, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 97, 116, 97, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(108, 105, 115, 116, 0, 0, 0, 0), + crate::word(101, 110, 117, 109, 0, 0, 0, 0), + crate::word(115, 116, 114, 117, 99, 116, 0, 0), + crate::word(105, 110, 116, 101, 114, 102, 97, 99), + crate::word(101, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 110, 121, 80, 111, 105, 110, 116), + crate::word(101, 114, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => <() as crate::introspect::Introspect>::introspect(), + 1 => <() as crate::introspect::Introspect>::introspect(), + 2 => <() as crate::introspect::Introspect>::introspect(), + 3 => <() as crate::introspect::Introspect>::introspect(), + 4 => <() as crate::introspect::Introspect>::introspect(), + 5 => <() as crate::introspect::Introspect>::introspect(), + 6 => <() as crate::introspect::Introspect>::introspect(), + 7 => <() as crate::introspect::Introspect>::introspect(), + 8 => <() as crate::introspect::Introspect>::introspect(), + 9 => <() as crate::introspect::Introspect>::introspect(), + 10 => <() as crate::introspect::Introspect>::introspect(), + 11 => <() as crate::introspect::Introspect>::introspect(), + 12 => <() as crate::introspect::Introspect>::introspect(), + 13 => <() as crate::introspect::Introspect>::introspect(), + 14 => ::introspect(), + 15 => ::introspect(), + 16 => ::introspect(), + 17 => ::introspect(), + 18 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + ]; + pub const TYPE_ID: u64 = 0xd073_78ed_e1f9_cc60; + } + pub enum Which { + Void(()), + Bool(()), + Int8(()), + Int16(()), + Int32(()), + Int64(()), + Uint8(()), + Uint16(()), + Uint32(()), + Uint64(()), + Float32(()), + Float64(()), + Text(()), + Data(()), + List(A0), + Enum(A1), + Struct(A2), + Interface(A3), + AnyPointer(A4), + } + pub type WhichReader<'a> = Which< + crate::schema_capnp::type_::list::Reader<'a>, + crate::schema_capnp::type_::enum_::Reader<'a>, + crate::schema_capnp::type_::struct_::Reader<'a>, + crate::schema_capnp::type_::interface::Reader<'a>, + crate::schema_capnp::type_::any_pointer::Reader<'a>, + >; + pub type WhichBuilder<'a> = Which< + crate::schema_capnp::type_::list::Builder<'a>, + crate::schema_capnp::type_::enum_::Builder<'a>, + crate::schema_capnp::type_::struct_::Builder<'a>, + crate::schema_capnp::type_::interface::Builder<'a>, + crate::schema_capnp::type_::any_pointer::Builder<'a>, + >; + + pub mod list { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_element_type(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_element_type(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_element_type( + self, + ) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_element_type( + &mut self, + value: crate::schema_capnp::type_::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_element_type(self) -> crate::schema_capnp::type_::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_element_type(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_element_type(&self) -> crate::schema_capnp::type_::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 32] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(151, 234, 96, 10, 37, 57, 231, 135), + crate::word(18, 0, 0, 0, 1, 0, 3, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(1, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 186, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 108, 105, 115, 116, 0, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 14, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 98, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 3, 0, 1, 0), + crate::word(24, 0, 0, 0, 2, 0, 1, 0), + crate::word(101, 108, 101, 109, 101, 110, 116, 84), + crate::word(121, 112, 101, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x87e7_3925_0a60_ea97; + } + } + + pub mod enum_ { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.reader.get_data_field::(1) + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_type_id(&mut self, value: u64) { + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_brand( + &mut self, + value: crate::schema_capnp::brand::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_brand(self) -> crate::schema_capnp::brand::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_brand(&self) -> crate::schema_capnp::brand::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 46] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(169, 135, 127, 26, 113, 120, 14, 158), + crate::word(18, 0, 0, 0, 1, 0, 3, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(1, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 186, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 101, 110, 117, 109, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 15, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 21, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(116, 121, 112, 101, 73, 100, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 114, 97, 110, 100, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x9e0e_7871_1a7f_87a9; + } + } + + pub mod struct_ { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.reader.get_data_field::(1) + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_type_id(&mut self, value: u64) { + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_brand( + &mut self, + value: crate::schema_capnp::brand::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_brand(self) -> crate::schema_capnp::brand::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_brand(&self) -> crate::schema_capnp::brand::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 47] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(211, 198, 76, 239, 96, 111, 58, 172), + crate::word(18, 0, 0, 0, 1, 0, 3, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(1, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 202, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 115, 116, 114, 117, 99, 116), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 16, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 22, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(116, 121, 112, 101, 73, 100, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 114, 97, 110, 100, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xac3a_6f60_ef4c_c6d3; + } + } + + pub mod interface { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.reader.get_data_field::(1) + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_type_id(self) -> u64 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_type_id(&mut self, value: u64) { + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_brand( + &mut self, + value: crate::schema_capnp::brand::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_brand(self) -> crate::schema_capnp::brand::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_brand(&self) -> crate::schema_capnp::brand::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 47] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(191, 12, 251, 247, 105, 202, 139, 237), + crate::word(18, 0, 0, 0, 1, 0, 3, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(1, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 226, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 105, 110, 116, 101, 114, 102), + crate::word(97, 99, 101, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 17, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 23, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(116, 121, 112, 101, 73, 100, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 114, 97, 110, 100, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xed8b_ca69_f7fb_0cbf; + } + } + + pub mod any_pointer { + pub use self::Which::{ImplicitMethodParameter, Parameter, Unconstrained}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Unconstrained(self.reader.into())), + 1 => ::core::result::Result::Ok(Parameter(self.reader.into())), + 2 => ::core::result::Result::Ok(ImplicitMethodParameter(self.reader.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn init_unconstrained( + self, + ) -> crate::schema_capnp::type_::any_pointer::unconstrained::Builder<'a> { + self.builder.set_data_field::(4, 0); + self.builder.set_data_field::(5, 0); + self.builder.into() + } + #[inline] + pub fn init_parameter( + self, + ) -> crate::schema_capnp::type_::any_pointer::parameter::Builder<'a> { + self.builder.set_data_field::(4, 1); + self.builder.set_data_field::(2, 0u64); + self.builder.set_data_field::(5, 0u16); + self.builder.into() + } + #[inline] + pub fn init_implicit_method_parameter( + self, + ) -> crate::schema_capnp::type_::any_pointer::implicit_method_parameter::Builder<'a> + { + self.builder.set_data_field::(4, 2); + self.builder.set_data_field::(5, 0u16); + self.builder.into() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Unconstrained(self.builder.into())), + 1 => ::core::result::Result::Ok(Parameter(self.builder.into())), + 2 => ::core::result::Result::Ok(ImplicitMethodParameter(self.builder.into())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 45] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(241, 73, 62, 162, 232, 63, 87, 194), + crate::word(18, 0, 0, 0, 1, 0, 3, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(1, 0, 7, 0, 1, 0, 3, 0), + crate::word(4, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 234, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 175, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 97, 110, 121, 80, 111, 105), + crate::word(110, 116, 101, 114, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 255, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(86, 54, 89, 254, 121, 95, 59, 142), + crate::word(69, 0, 0, 0, 114, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 254, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(133, 74, 97, 244, 36, 247, 209, 157), + crate::word(49, 0, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(2, 0, 253, 255, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 226, 86, 12, 18, 201, 239, 186), + crate::word(29, 0, 0, 0, 194, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 110, 99, 111, 110, 115, 116, 114), + crate::word(97, 105, 110, 101, 100, 0, 0, 0), + crate::word(112, 97, 114, 97, 109, 101, 116, 101), + crate::word(114, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 109, 112, 108, 105, 99, 105, 116), + crate::word(77, 101, 116, 104, 111, 100, 80, 97), + crate::word(114, 97, 109, 101, 116, 101, 114, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[0, 1, 2]; + pub const TYPE_ID: u64 = 0xc257_3fe8_a23e_49f1; + } + pub enum Which { + Unconstrained(A0), + Parameter(A1), + ImplicitMethodParameter(A2), + } + pub type WhichReader<'a> = Which< + crate::schema_capnp::type_::any_pointer::unconstrained::Reader<'a>, + crate::schema_capnp::type_::any_pointer::parameter::Reader<'a>, + crate::schema_capnp::type_::any_pointer::implicit_method_parameter::Reader<'a>, + >; + pub type WhichBuilder<'a> = Which< + crate::schema_capnp::type_::any_pointer::unconstrained::Builder<'a>, + crate::schema_capnp::type_::any_pointer::parameter::Builder<'a>, + crate::schema_capnp::type_::any_pointer::implicit_method_parameter::Builder<'a>, + >; + + pub mod unconstrained { + pub use self::Which::{AnyKind, Capability, List, Struct}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn which(self) -> ::core::result::Result { + match self.reader.get_data_field::(5) { + 0 => ::core::result::Result::Ok(AnyKind(())), + 1 => ::core::result::Result::Ok(Struct(())), + 2 => ::core::result::Result::Ok(List(())), + 3 => ::core::result::Result::Ok(Capability(())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_any_kind(&mut self, _value: ()) { + self.builder.set_data_field::(5, 0); + } + #[inline] + pub fn set_struct(&mut self, _value: ()) { + self.builder.set_data_field::(5, 1); + } + #[inline] + pub fn set_list(&mut self, _value: ()) { + self.builder.set_data_field::(5, 2); + } + #[inline] + pub fn set_capability(&mut self, _value: ()) { + self.builder.set_data_field::(5, 3); + } + #[inline] + pub fn which(self) -> ::core::result::Result { + match self.builder.get_data_field::(5) { + 0 => ::core::result::Result::Ok(AnyKind(())), + 1 => ::core::result::Result::Ok(Struct(())), + 2 => ::core::result::Result::Ok(List(())), + 3 => ::core::result::Result::Ok(Capability(())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 80] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(86, 54, 89, 254, 121, 95, 59, 142), + crate::word(29, 0, 0, 0, 1, 0, 3, 0), + crate::word(241, 73, 62, 162, 232, 63, 87, 194), + crate::word(1, 0, 7, 0, 1, 0, 4, 0), + crate::word(5, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 90, 1, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(33, 0, 0, 0, 231, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 97, 110, 121, 80, 111, 105), + crate::word(110, 116, 101, 114, 46, 117, 110, 99), + crate::word(111, 110, 115, 116, 114, 97, 105, 110), + crate::word(101, 100, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 18, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(92, 0, 0, 0, 3, 0, 1, 0), + crate::word(104, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 254, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 25, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(101, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 0, 0, 0, 3, 0, 1, 0), + crate::word(108, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 253, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 0, 0, 0, 3, 0, 1, 0), + crate::word(112, 0, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 252, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 27, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(109, 0, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(108, 0, 0, 0, 3, 0, 1, 0), + crate::word(120, 0, 0, 0, 2, 0, 1, 0), + crate::word(97, 110, 121, 75, 105, 110, 100, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 116, 114, 117, 99, 116, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(108, 105, 115, 116, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 97, 112, 97, 98, 105, 108, 105), + crate::word(116, 121, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => <() as crate::introspect::Introspect>::introspect(), + 1 => <() as crate::introspect::Introspect>::introspect(), + 2 => <() as crate::introspect::Introspect>::introspect(), + 3 => <() as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[0, 1, 2, 3]; + pub const TYPE_ID: u64 = 0x8e3b_5f79_fe59_3656; + } + pub enum Which { + AnyKind(()), + Struct(()), + List(()), + Capability(()), + } + pub type WhichReader = Which; + pub type WhichBuilder = Which; + } + + pub mod parameter { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_scope_id(self) -> u64 { + self.reader.get_data_field::(2) + } + #[inline] + pub fn get_parameter_index(self) -> u16 { + self.reader.get_data_field::(5) + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_scope_id(self) -> u64 { + self.builder.get_data_field::(2) + } + #[inline] + pub fn set_scope_id(&mut self, value: u64) { + self.builder.set_data_field::(2, value); + } + #[inline] + pub fn get_parameter_index(self) -> u16 { + self.builder.get_data_field::(5) + } + #[inline] + pub fn set_parameter_index(&mut self, value: u16) { + self.builder.set_data_field::(5, value); + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 49] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(133, 74, 97, 244, 36, 247, 209, 157), + crate::word(29, 0, 0, 0, 1, 0, 3, 0), + crate::word(241, 73, 62, 162, 232, 63, 87, 194), + crate::word(1, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 58, 1, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 97, 110, 121, 80, 111, 105), + crate::word(110, 116, 101, 114, 46, 112, 97, 114), + crate::word(97, 109, 101, 116, 101, 114, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 19, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 5, 0, 0, 0), + crate::word(0, 0, 1, 0, 20, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 122, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(44, 0, 0, 0, 3, 0, 1, 0), + crate::word(56, 0, 0, 0, 2, 0, 1, 0), + crate::word(115, 99, 111, 112, 101, 73, 100, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 97, 114, 97, 109, 101, 116, 101), + crate::word(114, 73, 110, 100, 101, 120, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x9dd1_f724_f461_4a85; + } + } + + pub mod implicit_method_parameter { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_parameter_index(self) -> u16 { + self.reader.get_data_field::(5) + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 3, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_parameter_index(self) -> u16 { + self.builder.get_data_field::(5) + } + #[inline] + pub fn set_parameter_index(&mut self, value: u16) { + self.builder.set_data_field::(5, value); + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 36] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(116, 226, 86, 12, 18, 201, 239, 186), + crate::word(29, 0, 0, 0, 1, 0, 3, 0), + crate::word(241, 73, 62, 162, 232, 63, 87, 194), + crate::word(1, 0, 7, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 170, 1, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(37, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 84, 121, 112), + crate::word(101, 46, 97, 110, 121, 80, 111, 105), + crate::word(110, 116, 101, 114, 46, 105, 109, 112), + crate::word(108, 105, 99, 105, 116, 77, 101, 116), + crate::word(104, 111, 100, 80, 97, 114, 97, 109), + crate::word(101, 116, 101, 114, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 5, 0, 0, 0), + crate::word(0, 0, 1, 0, 24, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 122, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 3, 0, 1, 0), + crate::word(24, 0, 0, 0, 2, 0, 1, 0), + crate::word(112, 97, 114, 97, 109, 101, 116, 101), + crate::word(114, 73, 110, 100, 101, 120, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xbaef_c912_0c56_e274; + } + } + } +} + +pub mod brand { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_scopes( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_scopes(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 0, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_scopes( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_scopes( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::brand::scope::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_scopes( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::brand::scope::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) + } + #[inline] + pub fn has_scopes(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 42] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(13, 0, 0, 0, 1, 0, 0, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(1, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 154, 0, 0, 0), + crate::word(29, 0, 0, 0, 39, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 66, 114, 97), + crate::word(110, 100, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 1, 0, 1, 0), + crate::word(201, 107, 99, 169, 133, 52, 215, 171), + crate::word(9, 0, 0, 0, 50, 0, 0, 0), + crate::word(252, 231, 158, 150, 22, 205, 99, 200), + crate::word(5, 0, 0, 0, 66, 0, 0, 0), + crate::word(83, 99, 111, 112, 101, 0, 0, 0), + crate::word(66, 105, 110, 100, 105, 110, 103, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 1, 0), + crate::word(36, 0, 0, 0, 2, 0, 1, 0), + crate::word(115, 99, 111, 112, 101, 115, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(201, 107, 99, 169, 133, 52, 215, 171), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x9034_55f0_6065_422b; + } + + pub mod scope { + pub use self::Which::{Bind, Inherit}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_scope_id(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn has_bind(&self) -> bool { + if self.reader.get_data_field::(4) != 0 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Bind( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 1 => ::core::result::Result::Ok(Inherit(())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 2, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_scope_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_scope_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn set_bind( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::brand::binding::Owned>, + ) -> crate::Result<()> { + self.builder.set_data_field::(4, 0); + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_bind( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::brand::binding::Owned> + { + self.builder.set_data_field::(4, 0); + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_bind(&self) -> bool { + if self.builder.get_data_field::(4) != 0 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_inherit(&mut self, _value: ()) { + self.builder.set_data_field::(4, 1); + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Bind( + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 1 => ::core::result::Result::Ok(Inherit(())), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 67] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(201, 107, 99, 169, 133, 52, 215, 171), + crate::word(19, 0, 0, 0, 1, 0, 2, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(1, 0, 7, 0, 0, 0, 2, 0), + crate::word(4, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 202, 0, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 175, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 66, 114, 97), + crate::word(110, 100, 46, 83, 99, 111, 112, 101), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(12, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(69, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(64, 0, 0, 0, 3, 0, 1, 0), + crate::word(76, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(68, 0, 0, 0, 3, 0, 1, 0), + crate::word(96, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 254, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(93, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(88, 0, 0, 0, 3, 0, 1, 0), + crate::word(100, 0, 0, 0, 2, 0, 1, 0), + crate::word(115, 99, 111, 112, 101, 73, 100, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 105, 110, 100, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(252, 231, 158, 150, 22, 205, 99, 200), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 104, 101, 114, 105, 116, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => as crate::introspect::Introspect>::introspect(), + 2 => <() as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[1, 2]; + pub const TYPE_ID: u64 = 0xabd7_3485_a963_6bc9; + } + pub enum Which { + Bind(A0), + Inherit(()), + } + pub type WhichReader<'a> = Which< + crate::Result< + crate::struct_list::Reader<'a, crate::schema_capnp::brand::binding::Owned>, + >, + >; + pub type WhichBuilder<'a> = Which< + crate::Result< + crate::struct_list::Builder<'a, crate::schema_capnp::brand::binding::Owned>, + >, + >; + } + + pub mod binding { + pub use self::Which::{Type, Unbound}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn has_type(&self) -> bool { + if self.reader.get_data_field::(0) != 1 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Unbound(())), + 1 => ::core::result::Result::Ok(Type( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_unbound(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_type( + &mut self, + value: crate::schema_capnp::type_::Reader<'_>, + ) -> crate::Result<()> { + self.builder.set_data_field::(0, 1); + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_type(self) -> crate::schema_capnp::type_::Builder<'a> { + self.builder.set_data_field::(0, 1); + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_type(&self) -> bool { + if self.builder.get_data_field::(0) != 1 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Unbound(())), + 1 => ::core::result::Result::Ok(Type( + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 48] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(252, 231, 158, 150, 22, 205, 99, 200), + crate::word(19, 0, 0, 0, 1, 0, 1, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(1, 0, 7, 0, 0, 0, 2, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 218, 0, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 66, 114, 97), + crate::word(110, 100, 46, 66, 105, 110, 100, 105), + crate::word(110, 103, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 254, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(117, 110, 98, 111, 117, 110, 100, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 121, 112, 101, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(96, 204, 249, 225, 237, 120, 115, 208), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => <() as crate::introspect::Introspect>::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[0, 1]; + pub const TYPE_ID: u64 = 0xc863_cd16_969e_e7fc; + } + pub enum Which { + Unbound(()), + Type(A0), + } + pub type WhichReader<'a> = Which>>; + pub type WhichBuilder<'a> = Which>>; + } +} + +pub mod value { + pub use self::Which::{ + AnyPointer, Bool, Data, Enum, Float32, Float64, Int16, Int32, Int64, Int8, Interface, List, + Struct, Text, Uint16, Uint32, Uint64, Uint8, Void, + }; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn has_text(&self) -> bool { + if self.reader.get_data_field::(0) != 12 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_data(&self) -> bool { + if self.reader.get_data_field::(0) != 13 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_list(&self) -> bool { + if self.reader.get_data_field::(0) != 14 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_struct(&self) -> bool { + if self.reader.get_data_field::(0) != 16 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_any_pointer(&self) -> bool { + if self.reader.get_data_field::(0) != 18 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Void(())), + 1 => ::core::result::Result::Ok(Bool(self.reader.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Int8(self.reader.get_data_field::(2))), + 3 => ::core::result::Result::Ok(Int16(self.reader.get_data_field::(1))), + 4 => ::core::result::Result::Ok(Int32(self.reader.get_data_field::(1))), + 5 => ::core::result::Result::Ok(Int64(self.reader.get_data_field::(1))), + 6 => ::core::result::Result::Ok(Uint8(self.reader.get_data_field::(2))), + 7 => ::core::result::Result::Ok(Uint16(self.reader.get_data_field::(1))), + 8 => ::core::result::Result::Ok(Uint32(self.reader.get_data_field::(1))), + 9 => ::core::result::Result::Ok(Uint64(self.reader.get_data_field::(1))), + 10 => ::core::result::Result::Ok(Float32(self.reader.get_data_field::(1))), + 11 => ::core::result::Result::Ok(Float64(self.reader.get_data_field::(1))), + 12 => ::core::result::Result::Ok(Text( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 13 => ::core::result::Result::Ok(Data( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 14 => ::core::result::Result::Ok(List(crate::any_pointer::Reader::new( + self.reader.get_pointer_field(0), + ))), + 15 => ::core::result::Result::Ok(Enum(self.reader.get_data_field::(1))), + 16 => ::core::result::Result::Ok(Struct(crate::any_pointer::Reader::new( + self.reader.get_pointer_field(0), + ))), + 17 => ::core::result::Result::Ok(Interface(())), + 18 => ::core::result::Result::Ok(AnyPointer(crate::any_pointer::Reader::new( + self.reader.get_pointer_field(0), + ))), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 2, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_void(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_bool(&mut self, value: bool) { + self.builder.set_data_field::(0, 1); + self.builder.set_bool_field(16, value); + } + #[inline] + pub fn set_int8(&mut self, value: i8) { + self.builder.set_data_field::(0, 2); + self.builder.set_data_field::(2, value); + } + #[inline] + pub fn set_int16(&mut self, value: i16) { + self.builder.set_data_field::(0, 3); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_int32(&mut self, value: i32) { + self.builder.set_data_field::(0, 4); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_int64(&mut self, value: i64) { + self.builder.set_data_field::(0, 5); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_uint8(&mut self, value: u8) { + self.builder.set_data_field::(0, 6); + self.builder.set_data_field::(2, value); + } + #[inline] + pub fn set_uint16(&mut self, value: u16) { + self.builder.set_data_field::(0, 7); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_uint32(&mut self, value: u32) { + self.builder.set_data_field::(0, 8); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_uint64(&mut self, value: u64) { + self.builder.set_data_field::(0, 9); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_float32(&mut self, value: f32) { + self.builder.set_data_field::(0, 10); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_float64(&mut self, value: f64) { + self.builder.set_data_field::(0, 11); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_text(&mut self, value: crate::text::Reader<'_>) { + self.builder.set_data_field::(0, 12); + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_text(self, size: u32) -> crate::text::Builder<'a> { + self.builder.set_data_field::(0, 12); + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_text(&self) -> bool { + if self.builder.get_data_field::(0) != 12 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_data(&mut self, value: crate::data::Reader<'_>) { + self.builder.set_data_field::(0, 13); + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_data(self, size: u32) -> crate::data::Builder<'a> { + self.builder.set_data_field::(0, 13); + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_data(&self) -> bool { + if self.builder.get_data_field::(0) != 13 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn init_list(self) -> crate::any_pointer::Builder<'a> { + self.builder.set_data_field::(0, 14); + let mut result = crate::any_pointer::Builder::new(self.builder.get_pointer_field(0)); + result.clear(); + result + } + #[inline] + pub fn has_list(&self) -> bool { + if self.builder.get_data_field::(0) != 14 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_enum(&mut self, value: u16) { + self.builder.set_data_field::(0, 15); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn init_struct(self) -> crate::any_pointer::Builder<'a> { + self.builder.set_data_field::(0, 16); + let mut result = crate::any_pointer::Builder::new(self.builder.get_pointer_field(0)); + result.clear(); + result + } + #[inline] + pub fn has_struct(&self) -> bool { + if self.builder.get_data_field::(0) != 16 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_interface(&mut self, _value: ()) { + self.builder.set_data_field::(0, 17); + } + #[inline] + pub fn init_any_pointer(self) -> crate::any_pointer::Builder<'a> { + self.builder.set_data_field::(0, 18); + let mut result = crate::any_pointer::Builder::new(self.builder.get_pointer_field(0)); + result.clear(); + result + } + #[inline] + pub fn has_any_pointer(&self) -> bool { + if self.builder.get_data_field::(0) != 18 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Void(())), + 1 => ::core::result::Result::Ok(Bool(self.builder.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Int8(self.builder.get_data_field::(2))), + 3 => ::core::result::Result::Ok(Int16(self.builder.get_data_field::(1))), + 4 => ::core::result::Result::Ok(Int32(self.builder.get_data_field::(1))), + 5 => ::core::result::Result::Ok(Int64(self.builder.get_data_field::(1))), + 6 => ::core::result::Result::Ok(Uint8(self.builder.get_data_field::(2))), + 7 => ::core::result::Result::Ok(Uint16(self.builder.get_data_field::(1))), + 8 => ::core::result::Result::Ok(Uint32(self.builder.get_data_field::(1))), + 9 => ::core::result::Result::Ok(Uint64(self.builder.get_data_field::(1))), + 10 => ::core::result::Result::Ok(Float32(self.builder.get_data_field::(1))), + 11 => ::core::result::Result::Ok(Float64(self.builder.get_data_field::(1))), + 12 => ::core::result::Result::Ok(Text( + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 13 => ::core::result::Result::Ok(Data( + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 14 => ::core::result::Result::Ok(List(crate::any_pointer::Builder::new( + self.builder.get_pointer_field(0), + ))), + 15 => ::core::result::Result::Ok(Enum(self.builder.get_data_field::(1))), + 16 => ::core::result::Result::Ok(Struct(crate::any_pointer::Builder::new( + self.builder.get_pointer_field(0), + ))), + 17 => ::core::result::Result::Ok(Interface(())), + 18 => ::core::result::Result::Ok(AnyPointer(crate::any_pointer::Builder::new( + self.builder.get_pointer_field(0), + ))), + x => ::core::result::Result::Err(crate::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 304] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(155, 12, 176, 215, 210, 220, 35, 206), + crate::word(13, 0, 0, 0, 1, 0, 2, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(1, 0, 7, 0, 0, 0, 19, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 154, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 47, 4, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 86, 97, 108), + crate::word(117, 101, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(76, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(5, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 2, 0, 0, 3, 0, 1, 0), + crate::word(12, 2, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 254, 255, 16, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 2, 0, 0, 3, 0, 1, 0), + crate::word(16, 2, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 253, 255, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 2, 0, 0, 3, 0, 1, 0), + crate::word(20, 2, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 252, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 3, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(17, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 2, 0, 0, 3, 0, 1, 0), + crate::word(24, 2, 0, 0, 2, 0, 1, 0), + crate::word(4, 0, 251, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 4, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 2, 0, 0, 3, 0, 1, 0), + crate::word(28, 2, 0, 0, 2, 0, 1, 0), + crate::word(5, 0, 250, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 5, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(20, 2, 0, 0, 3, 0, 1, 0), + crate::word(32, 2, 0, 0, 2, 0, 1, 0), + crate::word(6, 0, 249, 255, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 6, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 2, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(24, 2, 0, 0, 3, 0, 1, 0), + crate::word(36, 2, 0, 0, 2, 0, 1, 0), + crate::word(7, 0, 248, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(33, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(28, 2, 0, 0, 3, 0, 1, 0), + crate::word(40, 2, 0, 0, 2, 0, 1, 0), + crate::word(8, 0, 247, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 8, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(37, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(32, 2, 0, 0, 3, 0, 1, 0), + crate::word(44, 2, 0, 0, 2, 0, 1, 0), + crate::word(9, 0, 246, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 9, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 2, 0, 0, 3, 0, 1, 0), + crate::word(48, 2, 0, 0, 2, 0, 1, 0), + crate::word(10, 0, 245, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 10, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 2, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 2, 0, 0, 3, 0, 1, 0), + crate::word(52, 2, 0, 0, 2, 0, 1, 0), + crate::word(11, 0, 244, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 11, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 2, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(44, 2, 0, 0, 3, 0, 1, 0), + crate::word(56, 2, 0, 0, 2, 0, 1, 0), + crate::word(12, 0, 243, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 12, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(53, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(48, 2, 0, 0, 3, 0, 1, 0), + crate::word(60, 2, 0, 0, 2, 0, 1, 0), + crate::word(13, 0, 242, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 13, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(57, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(52, 2, 0, 0, 3, 0, 1, 0), + crate::word(64, 2, 0, 0, 2, 0, 1, 0), + crate::word(14, 0, 241, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 14, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(61, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(56, 2, 0, 0, 3, 0, 1, 0), + crate::word(68, 2, 0, 0, 2, 0, 1, 0), + crate::word(15, 0, 240, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 15, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(65, 2, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(60, 2, 0, 0, 3, 0, 1, 0), + crate::word(72, 2, 0, 0, 2, 0, 1, 0), + crate::word(16, 0, 239, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 16, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(69, 2, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(64, 2, 0, 0, 3, 0, 1, 0), + crate::word(76, 2, 0, 0, 2, 0, 1, 0), + crate::word(17, 0, 238, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 17, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 2, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(72, 2, 0, 0, 3, 0, 1, 0), + crate::word(84, 2, 0, 0, 2, 0, 1, 0), + crate::word(18, 0, 237, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 18, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(81, 2, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(80, 2, 0, 0, 3, 0, 1, 0), + crate::word(92, 2, 0, 0, 2, 0, 1, 0), + crate::word(118, 111, 105, 100, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 111, 111, 108, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 56, 0, 0, 0, 0), + crate::word(2, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(2, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 49, 54, 0, 0, 0), + crate::word(3, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(3, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 51, 50, 0, 0, 0), + crate::word(4, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 54, 52, 0, 0, 0), + crate::word(5, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(5, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 56, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 49, 54, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 51, 50, 0, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 105, 110, 116, 54, 52, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 108, 111, 97, 116, 51, 50, 0), + crate::word(10, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(10, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 108, 111, 97, 116, 54, 52, 0), + crate::word(11, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(11, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 101, 120, 116, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(100, 97, 116, 97, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(108, 105, 115, 116, 0, 0, 0, 0), + crate::word(18, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(18, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(101, 110, 117, 109, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 116, 114, 117, 99, 116, 0, 0), + crate::word(18, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(18, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 110, 116, 101, 114, 102, 97, 99), + crate::word(101, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 110, 121, 80, 111, 105, 110, 116), + crate::word(101, 114, 0, 0, 0, 0, 0, 0), + crate::word(18, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(18, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => <() as crate::introspect::Introspect>::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => ::introspect(), + 5 => ::introspect(), + 6 => ::introspect(), + 7 => ::introspect(), + 8 => ::introspect(), + 9 => ::introspect(), + 10 => ::introspect(), + 11 => ::introspect(), + 12 => ::introspect(), + 13 => ::introspect(), + 14 => ::introspect(), + 15 => ::introspect(), + 16 => ::introspect(), + 17 => <() as crate::introspect::Introspect>::introspect(), + 18 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + ]; + pub const TYPE_ID: u64 = 0xce23_dcd2_d7b0_0c9b; + } + pub enum Which { + Void(()), + Bool(bool), + Int8(i8), + Int16(i16), + Int32(i32), + Int64(i64), + Uint8(u8), + Uint16(u16), + Uint32(u32), + Uint64(u64), + Float32(f32), + Float64(f64), + Text(A0), + Data(A1), + List(A2), + Enum(u16), + Struct(A3), + Interface(()), + AnyPointer(A4), + } + pub type WhichReader<'a> = Which< + crate::Result>, + crate::Result>, + crate::any_pointer::Reader<'a>, + crate::any_pointer::Reader<'a>, + crate::any_pointer::Reader<'a>, + >; + pub type WhichBuilder<'a> = Which< + crate::Result>, + crate::Result>, + crate::any_pointer::Builder<'a>, + crate::any_pointer::Builder<'a>, + crate::any_pointer::Builder<'a>, + >; +} + +pub mod annotation { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_value(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 2, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_value(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_value( + &mut self, + value: crate::schema_capnp::value::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_value(self) -> crate::schema_capnp::value::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_brand(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_brand( + &mut self, + value: crate::schema_capnp::brand::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_brand(self) -> crate::schema_capnp::brand::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) + } + #[inline] + pub fn has_brand(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_value(&self) -> crate::schema_capnp::value::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + pub fn get_brand(&self) -> crate::schema_capnp::brand::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 62] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(66, 117, 37, 171, 13, 149, 200, 241), + crate::word(13, 0, 0, 0, 1, 0, 1, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(2, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 194, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 175, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 65, 110, 110), + crate::word(111, 116, 97, 116, 105, 111, 110, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(12, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(69, 0, 0, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(64, 0, 0, 0, 3, 0, 1, 0), + crate::word(76, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(68, 0, 0, 0, 3, 0, 1, 0), + crate::word(80, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(77, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(72, 0, 0, 0, 3, 0, 1, 0), + crate::word(84, 0, 0, 0, 2, 0, 1, 0), + crate::word(105, 100, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(118, 97, 108, 117, 101, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(155, 12, 176, 215, 210, 220, 35, 206), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 114, 97, 110, 100, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(43, 66, 101, 96, 240, 85, 52, 144), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => { + ::introspect( + ) + } + 2 => { + ::introspect( + ) + } + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xf1c8_950d_ab25_7542; + } +} + +#[repr(u16)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ElementSize { + Empty = 0, + Bit = 1, + Byte = 2, + TwoBytes = 3, + FourBytes = 4, + EightBytes = 5, + Pointer = 6, + InlineComposite = 7, +} + +impl crate::introspect::Introspect for ElementSize { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Enum(crate::introspect::RawEnumSchema { + encoded_node: &element_size::ENCODED_NODE, + annotation_types: element_size::get_annotation_types, + }) + .into() + } +} +impl<'a> ::core::convert::From for crate::dynamic_value::Reader<'a> { + fn from(e: ElementSize) -> Self { + crate::dynamic_value::Enum::new( + e.into(), + crate::introspect::RawEnumSchema { + encoded_node: &element_size::ENCODED_NODE, + annotation_types: element_size::get_annotation_types, + } + .into(), + ) + .into() + } +} +impl ::core::convert::TryFrom for ElementSize { + type Error = crate::NotInSchema; + fn try_from( + value: u16, + ) -> ::core::result::Result>::Error> { + match value { + 0 => ::core::result::Result::Ok(Self::Empty), + 1 => ::core::result::Result::Ok(Self::Bit), + 2 => ::core::result::Result::Ok(Self::Byte), + 3 => ::core::result::Result::Ok(Self::TwoBytes), + 4 => ::core::result::Result::Ok(Self::FourBytes), + 5 => ::core::result::Result::Ok(Self::EightBytes), + 6 => ::core::result::Result::Ok(Self::Pointer), + 7 => ::core::result::Result::Ok(Self::InlineComposite), + n => ::core::result::Result::Err(crate::NotInSchema(n)), + } + } +} +impl From for u16 { + #[inline] + fn from(x: ElementSize) -> u16 { + x as u16 + } +} +impl crate::traits::HasTypeId for ElementSize { + const TYPE_ID: u64 = 0xd195_8f7d_ba52_1926u64; +} +mod element_size { + pub static ENCODED_NODE: [crate::Word; 54] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(38, 25, 82, 186, 125, 143, 149, 209), + crate::word(13, 0, 0, 0, 2, 0, 0, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 202, 0, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 199, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 69, 108, 101), + crate::word(109, 101, 110, 116, 83, 105, 122, 101), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(32, 0, 0, 0, 1, 0, 2, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(89, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(81, 0, 0, 0, 34, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(2, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(3, 0, 0, 0, 0, 0, 0, 0), + crate::word(65, 0, 0, 0, 74, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 0, 0, 0, 0), + crate::word(61, 0, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(5, 0, 0, 0, 0, 0, 0, 0), + crate::word(57, 0, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(53, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 130, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(101, 109, 112, 116, 121, 0, 0, 0), + crate::word(98, 105, 116, 0, 0, 0, 0, 0), + crate::word(98, 121, 116, 101, 0, 0, 0, 0), + crate::word(116, 119, 111, 66, 121, 116, 101, 115), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 111, 117, 114, 66, 121, 116, 101), + crate::word(115, 0, 0, 0, 0, 0, 0, 0), + crate::word(101, 105, 103, 104, 116, 66, 121, 116), + crate::word(101, 115, 0, 0, 0, 0, 0, 0), + crate::word(112, 111, 105, 110, 116, 101, 114, 0), + crate::word(105, 110, 108, 105, 110, 101, 67, 111), + crate::word(109, 112, 111, 115, 105, 116, 101, 0), + ]; + pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } +} + +pub mod capnp_version { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_major(self) -> u16 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_minor(self) -> u8 { + self.reader.get_data_field::(2) + } + #[inline] + pub fn get_micro(self) -> u8 { + self.reader.get_data_field::(3) + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 0, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_major(self) -> u16 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_major(&mut self, value: u16) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_minor(self) -> u8 { + self.builder.get_data_field::(2) + } + #[inline] + pub fn set_minor(&mut self, value: u8) { + self.builder.set_data_field::(2, value); + } + #[inline] + pub fn get_micro(self) -> u8 { + self.builder.get_data_field::(3) + } + #[inline] + pub fn set_micro(&mut self, value: u8) { + self.builder.set_data_field::(3, value); + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 63] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(99, 153, 131, 125, 91, 48, 93, 216), + crate::word(13, 0, 0, 0, 1, 0, 1, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(0, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 210, 0, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 175, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 67, 97, 112), + crate::word(110, 112, 86, 101, 114, 115, 105, 111), + crate::word(110, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(12, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(69, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(64, 0, 0, 0, 3, 0, 1, 0), + crate::word(76, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(68, 0, 0, 0, 3, 0, 1, 0), + crate::word(80, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(77, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(72, 0, 0, 0, 3, 0, 1, 0), + crate::word(84, 0, 0, 0, 2, 0, 1, 0), + crate::word(109, 97, 106, 111, 114, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(7, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(109, 105, 110, 111, 114, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(109, 105, 99, 114, 111, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(6, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xd85d_305b_7d83_9963; + } +} + +pub mod code_generator_request { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_nodes( + self, + ) -> crate::Result> + { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_nodes(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_requested_files( + self, + ) -> crate::Result< + crate::struct_list::Reader< + 'a, + crate::schema_capnp::code_generator_request::requested_file::Owned, + >, + > { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_requested_files(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_capnp_version( + self, + ) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_capnp_version(&self) -> bool { + !self.reader.get_pointer_field(2).is_null() + } + #[inline] + pub fn get_source_info( + self, + ) -> crate::Result< + crate::struct_list::Reader<'a, crate::schema_capnp::node::source_info::Owned>, + > { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_source_info(&self) -> bool { + !self.reader.get_pointer_field(3).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 0, + pointers: 4, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_nodes( + self, + ) -> crate::Result> + { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_nodes( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::node::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_nodes( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::node::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) + } + #[inline] + pub fn has_nodes(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_requested_files( + self, + ) -> crate::Result< + crate::struct_list::Builder< + 'a, + crate::schema_capnp::code_generator_request::requested_file::Owned, + >, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_requested_files( + &mut self, + value: crate::struct_list::Reader< + 'a, + crate::schema_capnp::code_generator_request::requested_file::Owned, + >, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_requested_files( + self, + size: u32, + ) -> crate::struct_list::Builder< + 'a, + crate::schema_capnp::code_generator_request::requested_file::Owned, + > { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_requested_files(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + #[inline] + pub fn get_capnp_version( + self, + ) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(2), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_capnp_version( + &mut self, + value: crate::schema_capnp::capnp_version::Reader<'_>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(2), + value, + false, + ) + } + #[inline] + pub fn init_capnp_version(self) -> crate::schema_capnp::capnp_version::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), 0) + } + #[inline] + pub fn has_capnp_version(&self) -> bool { + !self.builder.is_pointer_field_null(2) + } + #[inline] + pub fn get_source_info( + self, + ) -> crate::Result< + crate::struct_list::Builder<'a, crate::schema_capnp::node::source_info::Owned>, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(3), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_source_info( + &mut self, + value: crate::struct_list::Reader<'a, crate::schema_capnp::node::source_info::Owned>, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(3), + value, + false, + ) + } + #[inline] + pub fn init_source_info( + self, + size: u32, + ) -> crate::struct_list::Builder<'a, crate::schema_capnp::node::source_info::Owned> + { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(3), size) + } + #[inline] + pub fn has_source_info(&self) -> bool { + !self.builder.is_pointer_field_null(3) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_capnp_version(&self) -> crate::schema_capnp::capnp_version::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 98] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(206, 215, 10, 33, 246, 70, 197, 191), + crate::word(13, 0, 0, 0, 1, 0, 0, 0), + crate::word(217, 114, 76, 98, 9, 197, 63, 169), + crate::word(4, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 18, 1, 0, 0), + crate::word(37, 0, 0, 0, 23, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 0, 0, 0, 231, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 67, 111, 100), + crate::word(101, 71, 101, 110, 101, 114, 97, 116), + crate::word(111, 114, 82, 101, 113, 117, 101, 115), + crate::word(116, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 0, 0, 0, 1, 0, 1, 0), + crate::word(98, 0, 129, 46, 176, 14, 234, 207), + crate::word(1, 0, 0, 0, 114, 0, 0, 0), + crate::word(82, 101, 113, 117, 101, 115, 116, 101), + crate::word(100, 70, 105, 108, 101, 0, 0, 0), + crate::word(16, 0, 0, 0, 3, 0, 4, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(92, 0, 0, 0, 3, 0, 1, 0), + crate::word(120, 0, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(117, 0, 0, 0, 122, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(116, 0, 0, 0, 3, 0, 1, 0), + crate::word(144, 0, 0, 0, 2, 0, 1, 0), + crate::word(0, 0, 0, 0, 2, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(141, 0, 0, 0, 106, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(140, 0, 0, 0, 3, 0, 1, 0), + crate::word(152, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 3, 0, 0, 0), + crate::word(0, 0, 1, 0, 3, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(149, 0, 0, 0, 90, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(148, 0, 0, 0, 3, 0, 1, 0), + crate::word(176, 0, 0, 0, 2, 0, 1, 0), + crate::word(110, 111, 100, 101, 115, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(23, 164, 35, 249, 76, 171, 130, 230), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(114, 101, 113, 117, 101, 115, 116, 101), + crate::word(100, 70, 105, 108, 101, 115, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 0, 129, 46, 176, 14, 234, 207), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 97, 112, 110, 112, 86, 101, 114), + crate::word(115, 105, 111, 110, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 153, 131, 125, 91, 48, 93, 216), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 111, 117, 114, 99, 101, 73, 110), + crate::word(102, 111, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(174, 87, 19, 4, 227, 29, 142, 243), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => as crate::introspect::Introspect>::introspect(), + 1 => as crate::introspect::Introspect>::introspect(), + 2 => ::introspect(), + 3 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xbfc5_46f6_210a_d7ce; + } + + pub mod requested_file { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_filename(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_filename(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_imports( + self, + ) -> crate::Result< + crate::struct_list::Reader< + 'a, + crate::schema_capnp::code_generator_request::requested_file::import::Owned, + >, + > { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_imports(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 2, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct(::STRUCT_SIZE, default)? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_filename(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_filename(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_filename(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_filename(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_imports( + self, + ) -> crate::Result< + crate::struct_list::Builder< + 'a, + crate::schema_capnp::code_generator_request::requested_file::import::Owned, + >, + > { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_imports( + &mut self, + value: crate::struct_list::Reader< + 'a, + crate::schema_capnp::code_generator_request::requested_file::import::Owned, + >, + ) -> crate::Result<()> { + crate::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_imports( + self, + size: u32, + ) -> crate::struct_list::Builder< + 'a, + crate::schema_capnp::code_generator_request::requested_file::import::Owned, + > { + crate::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(1), + size, + ) + } + #[inline] + pub fn has_imports(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 73] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(98, 0, 129, 46, 176, 14, 234, 207), + crate::word(34, 0, 0, 0, 1, 0, 1, 0), + crate::word(206, 215, 10, 33, 246, 70, 197, 191), + crate::word(2, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 130, 1, 0, 0), + crate::word(41, 0, 0, 0, 23, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 0, 0, 0, 175, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 67, 111, 100), + crate::word(101, 71, 101, 110, 101, 114, 97, 116), + crate::word(111, 114, 82, 101, 113, 117, 101, 115), + crate::word(116, 46, 82, 101, 113, 117, 101, 115), + crate::word(116, 101, 100, 70, 105, 108, 101, 0), + crate::word(4, 0, 0, 0, 1, 0, 1, 0), + crate::word(229, 87, 35, 18, 147, 65, 80, 174), + crate::word(1, 0, 0, 0, 58, 0, 0, 0), + crate::word(73, 109, 112, 111, 114, 116, 0, 0), + crate::word(12, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(69, 0, 0, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(64, 0, 0, 0, 3, 0, 1, 0), + crate::word(76, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(73, 0, 0, 0, 74, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(72, 0, 0, 0, 3, 0, 1, 0), + crate::word(84, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(81, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(76, 0, 0, 0, 3, 0, 1, 0), + crate::word(104, 0, 0, 0, 2, 0, 1, 0), + crate::word(105, 100, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(102, 105, 108, 101, 110, 97, 109, 101), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(105, 109, 112, 111, 114, 116, 115, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(229, 87, 35, 18, 147, 65, 80, 174), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => as crate::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xcfea_0eb0_2e81_0062; + } + + pub mod import { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Struct( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl crate::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: crate::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> crate::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Reader<'a> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new( + reader.reader, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::>::into(*self), + f, + ) + } + } + + impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> crate::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> crate::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader + .imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: crate::private::layout::StructBuilder<'a>, + } + impl<'a> crate::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: crate::private::layout::StructSize = + crate::private::layout::StructSize { + data: 1, + pointers: 1, + }; + } + impl<'a> crate::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From> for Builder<'a> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new( + builder.builder, + crate::schema::StructSchema::new( + crate::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder + .imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [crate::Word]>, + ) -> crate::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: crate::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> crate::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_id(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_id(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: crate::text::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_text(value); + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: crate::any_pointer::Pipeline, + } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [crate::Word; 51] = [ + crate::word(0, 0, 0, 0, 5, 0, 6, 0), + crate::word(229, 87, 35, 18, 147, 65, 80, 174), + crate::word(48, 0, 0, 0, 1, 0, 1, 0), + crate::word(98, 0, 129, 46, 176, 14, 234, 207), + crate::word(1, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(21, 0, 0, 0, 186, 1, 0, 0), + crate::word(45, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 99, 104, 101, 109, 97, 46, 99), + crate::word(97, 112, 110, 112, 58, 67, 111, 100), + crate::word(101, 71, 101, 110, 101, 114, 97, 116), + crate::word(111, 114, 82, 101, 113, 117, 101, 115), + crate::word(116, 46, 82, 101, 113, 117, 101, 115), + crate::word(116, 101, 100, 70, 105, 108, 101, 46), + crate::word(73, 109, 112, 111, 114, 116, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 26, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(105, 100, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> crate::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = + crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xae50_4193_1223_57e5; + } + } + } +} diff --git a/rust/capnp/serialize.rs b/rust/capnp/serialize.rs new file mode 100644 index 000000000000..ad9e130e5ed7 --- /dev/null +++ b/rust/capnp/serialize.rs @@ -0,0 +1,961 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Reading and writing of messages using the +//! [standard stream framing](https://capnproto.org/encoding.html#serialization-over-a-stream), +//! where each message is preceded by a segment table indicating the size of its segments. + +mod no_alloc_buffer_segments; +pub use no_alloc_buffer_segments::{NoAllocBufferSegments, NoAllocSliceSegments}; + +#[cfg(feature = "alloc")] +use crate::io::{Read, Write}; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +#[cfg(feature = "alloc")] +use core::convert::TryInto; +#[cfg(feature = "alloc")] +use core::ops::Deref; + +use crate::message; +#[cfg(feature = "alloc")] +use crate::private::units::BYTES_PER_WORD; +use crate::Result; +#[cfg(feature = "alloc")] +use crate::{Error, ErrorKind}; + +pub const SEGMENTS_COUNT_LIMIT: usize = 512; + +/// Segments read from a single flat slice of words. +#[cfg(feature = "alloc")] +type SliceSegments<'a> = BufferSegments<&'a [u8]>; + +/// Reads a serialized message (including a segment table) from a flat slice of bytes, without copying. +/// The slice is allowed to extend beyond the end of the message. On success, updates `slice` to point +/// to the remaining bytes beyond the end of the message. +/// +/// ALIGNMENT: If the "unaligned" feature is enabled, then there are no alignment requirements on `slice`. +/// Otherwise, `slice` must be 8-byte aligned (attempts to read the message will trigger errors). +#[cfg(feature = "alloc")] +pub fn read_message_from_flat_slice<'a>( + slice: &mut &'a [u8], + options: message::ReaderOptions, +) -> Result>> { + let all_bytes = *slice; + let mut bytes = *slice; + let orig_bytes_len = bytes.len(); + let Some(segment_lengths_builder) = read_segment_table(&mut bytes, options)? else { + return Err(Error::from_kind(ErrorKind::EmptySlice)); + }; + let segment_table_bytes_len = orig_bytes_len - bytes.len(); + assert_eq!(segment_table_bytes_len % BYTES_PER_WORD, 0); + let num_words = segment_lengths_builder.total_words(); + let body_bytes = &all_bytes[segment_table_bytes_len..]; + if num_words > (body_bytes.len() / BYTES_PER_WORD) { + Err(Error::from_kind(ErrorKind::MessageEndsPrematurely( + num_words, + body_bytes.len() / BYTES_PER_WORD, + ))) + } else { + *slice = &body_bytes[(num_words * BYTES_PER_WORD)..]; + Ok(message::Reader::new( + segment_lengths_builder.into_slice_segments(all_bytes, segment_table_bytes_len), + options, + )) + } +} + +/// Reads a serialized message (including a segment table) from a flat slice of bytes, without copying. +/// The slice is allowed to extend beyond the end of the message. On success, updates `slice` to point +/// to the remaining bytes beyond the end of the message. +/// +/// Unlike read_message_from_flat_slice_no_alloc it does not do heap allocation +/// +/// ALIGNMENT: If the "unaligned" feature is enabled, then there are no alignment requirements on `slice`. +/// Otherwise, `slice` must be 8-byte aligned (attempts to read the message will trigger errors). +pub fn read_message_from_flat_slice_no_alloc<'a>( + slice: &mut &'a [u8], + options: message::ReaderOptions, +) -> Result>> { + let segments = NoAllocSliceSegments::from_slice(slice, options)?; + + Ok(message::Reader::new(segments, options)) +} + +/// Segments read from a buffer, useful for when you have the message in a buffer and don't want the extra +/// copy of `read_message`. +#[cfg(feature = "alloc")] +pub struct BufferSegments { + buffer: T, + + // Number of bytes in the segment table. + segment_table_bytes_len: usize, + + // Each pair represents a segment inside of `buffer`: + // (starting index (in words), ending index (in words)), + // where the indices are relative to the end of the segment table. + segment_indices: Vec<(usize, usize)>, +} + +#[cfg(feature = "alloc")] +impl> BufferSegments { + /// Reads a serialized message (including a segment table) from a buffer and takes ownership, without copying. + /// The buffer is allowed to be longer than the message. Provide this to `Reader::new` with options that make + /// sense for your use case. Very long lived mmaps may need unlimited traversal limit. + /// + /// ALIGNMENT: If the "unaligned" feature is enabled, then there are no alignment requirements on `buffer`. + /// Otherwise, `buffer` must be 8-byte aligned (attempts to read the message will trigger errors). + pub fn new(buffer: T, options: message::ReaderOptions) -> Result { + let mut segment_bytes = &*buffer; + + let Some(segment_table) = read_segment_table(&mut segment_bytes, options)? else { + return Err(Error::from_kind(ErrorKind::EmptyBuffer)); + }; + let segment_table_bytes_len = buffer.len() - segment_bytes.len(); + + assert!(segment_table.total_words() * 8 <= buffer.len()); + let segment_indices = segment_table.to_segment_indices(); + Ok(Self { + buffer, + segment_table_bytes_len, + segment_indices, + }) + } + + pub fn into_buffer(self) -> T { + self.buffer + } +} + +#[cfg(feature = "alloc")] +impl> message::ReaderSegments for BufferSegments { + fn get_segment(&self, id: u32) -> Option<&[u8]> { + if id < self.segment_indices.len() as u32 { + let (a, b) = self.segment_indices[id as usize]; + Some( + &self.buffer[(self.segment_table_bytes_len + a * BYTES_PER_WORD) + ..(self.segment_table_bytes_len + b * BYTES_PER_WORD)], + ) + } else { + None + } + } + + fn len(&self) -> usize { + self.segment_indices.len() + } +} + +/// Owned memory containing a message's segments sequentialized in a single contiguous buffer. +/// The segments are guaranteed to be 8-byte aligned. +#[cfg(feature = "alloc")] +pub struct OwnedSegments { + // Each pair represents a segment inside of `owned_space`. + // (starting index (in words), ending index (in words)) + segment_indices: Vec<(usize, usize)>, + + owned_space: Vec, +} + +#[cfg(feature = "alloc")] +impl core::ops::Deref for OwnedSegments { + type Target = [u8]; + fn deref(&self) -> &[u8] { + crate::Word::words_to_bytes(&self.owned_space[..]) + } +} + +#[cfg(feature = "alloc")] +impl core::ops::DerefMut for OwnedSegments { + fn deref_mut(&mut self) -> &mut [u8] { + crate::Word::words_to_bytes_mut(&mut self.owned_space[..]) + } +} + +#[cfg(feature = "alloc")] +impl crate::message::ReaderSegments for OwnedSegments { + fn get_segment(&self, id: u32) -> Option<&[u8]> { + if id < self.segment_indices.len() as u32 { + let (a, b) = self.segment_indices[id as usize]; + Some(&self[(a * BYTES_PER_WORD)..(b * BYTES_PER_WORD)]) + } else { + None + } + } + + fn len(&self) -> usize { + self.segment_indices.len() + } +} + +#[cfg(feature = "alloc")] +/// Helper object for constructing an `OwnedSegments` or a `SliceSegments`. +pub struct SegmentLengthsBuilder { + segment_indices: Vec<(usize, usize)>, + total_words: usize, +} + +#[cfg(feature = "alloc")] +impl SegmentLengthsBuilder { + /// Creates a new `SegmentsLengthsBuilder`, initializing the segment_indices vector with + /// `Vec::with_capacitiy(capacity)`. `capacity` should equal the number of times that `push_segment()` + /// is expected to be called. + pub fn with_capacity(capacity: usize) -> Self { + Self { + segment_indices: Vec::with_capacity(capacity), + total_words: 0, + } + } + + /// Pushes a new segment length. The `n`th time (starting at 0) this is called specifies the length of + /// the segment with ID `n`. + pub fn push_segment(&mut self, length_in_words: usize) { + self.segment_indices + .push((self.total_words, self.total_words + length_in_words)); + self.total_words += length_in_words; + } + + /// Constructs an `OwnedSegments`, allocating a single buffer of 8-byte aligned memory to hold + /// all segments. + pub fn into_owned_segments(self) -> OwnedSegments { + let owned_space = crate::Word::allocate_zeroed_vec(self.total_words); + OwnedSegments { + segment_indices: self.segment_indices, + owned_space, + } + } + + /// Constructs a `SliceSegments`. + /// `slice` contains the full message (including the segment header). + pub fn into_slice_segments( + self, + slice: &[u8], + segment_table_bytes_len: usize, + ) -> SliceSegments { + assert!(self.total_words * BYTES_PER_WORD <= slice.len()); + BufferSegments { + buffer: slice, + segment_table_bytes_len, + segment_indices: self.segment_indices, + } + } + + /// Returns the sum of the lengths of the segments pushed so far. + pub fn total_words(&self) -> usize { + self.total_words + } + + /// Returns the vector of segment indices. Each entry is a pair (start_word_index, end_word_index). + /// This method primarily exists to enable testing. + pub fn to_segment_indices(self) -> Vec<(usize, usize)> { + self.segment_indices + } +} + +/// Reads a serialized message from a stream with the provided options. +/// +/// For optimal performance, `read` should be a buffered reader type. +#[cfg(feature = "alloc")] +pub fn read_message( + mut read: R, + options: message::ReaderOptions, +) -> Result> +where + R: Read, +{ + let Some(owned_segments_builder) = read_segment_table(&mut read, options)? else { + return Err(Error::from_kind(ErrorKind::PrematureEndOfFile)); + }; + read_segments( + &mut read, + owned_segments_builder.into_owned_segments(), + options, + ) +} + +/// Like `read_message()`, but returns None instead of an error if there are zero bytes left in +/// `read`. This is useful for reading a stream containing an unknown number of messages -- you +/// call this function until it returns None. +#[cfg(feature = "alloc")] +pub fn try_read_message( + mut read: R, + options: message::ReaderOptions, +) -> Result>> +where + R: Read, +{ + let Some(owned_segments_builder) = read_segment_table(&mut read, options)? else { + return Ok(None); + }; + Ok(Some(read_segments( + &mut read, + owned_segments_builder.into_owned_segments(), + options, + )?)) +} + +/// Reads a segment table from `read` and returns the total number of words across all +/// segments, as well as the segment offsets. +/// +/// The segment table format for streams is defined in the Cap'n Proto +/// [encoding spec](https://capnproto.org/encoding.html) +#[cfg(feature = "alloc")] +fn read_segment_table( + read: &mut R, + options: message::ReaderOptions, +) -> Result> +where + R: Read, +{ + // read the first Word, which contains segment_count and the 1st segment length + let mut buf: [u8; 8] = [0; 8]; + { + let n = read.read(&mut buf[..])?; + if n == 0 { + // Clean EOF on message boundary + return Ok(None); + } else if n < 8 { + read.read_exact(&mut buf[n..])?; + } + } + + let segment_count = u32::from_le_bytes(buf[0..4].try_into().unwrap()).wrapping_add(1) as usize; + + if segment_count >= SEGMENTS_COUNT_LIMIT || segment_count == 0 { + return Err(Error::from_kind(ErrorKind::InvalidNumberOfSegments( + segment_count, + ))); + } + + let mut segment_lengths_builder = SegmentLengthsBuilder::with_capacity(segment_count); + segment_lengths_builder + .push_segment(u32::from_le_bytes(buf[4..8].try_into().unwrap()) as usize); + if segment_count > 1 { + if segment_count < 4 { + read.read_exact(&mut buf)?; + for idx in 0..(segment_count - 1) { + let segment_len = + u32::from_le_bytes(buf[(idx * 4)..(idx + 1) * 4].try_into().unwrap()) as usize; + segment_lengths_builder.push_segment(segment_len); + } + } else { + let mut segment_sizes = vec![0u8; (segment_count & !1) * 4]; + read.read_exact(&mut segment_sizes[..])?; + for idx in 0..(segment_count - 1) { + let segment_len = + u32::from_le_bytes(segment_sizes[(idx * 4)..(idx + 1) * 4].try_into().unwrap()) + as usize; + segment_lengths_builder.push_segment(segment_len); + } + } + } + + // Don't accept a message which the receiver couldn't possibly traverse without hitting the + // traversal limit. Without this check, a malicious client could transmit a very large segment + // size to make the receiver allocate excessive space and possibly crash. + if let Some(limit) = options.traversal_limit_in_words { + if segment_lengths_builder.total_words() > limit { + return Err(Error::from_kind(ErrorKind::MessageTooLarge( + segment_lengths_builder.total_words(), + ))); + } + } + + Ok(Some(segment_lengths_builder)) +} + +#[cfg(feature = "alloc")] +/// Reads segments from `read`. +fn read_segments( + read: &mut R, + mut owned_segments: OwnedSegments, + options: message::ReaderOptions, +) -> Result> +where + R: Read, +{ + read.read_exact(&mut owned_segments[..])?; + Ok(crate::message::Reader::new(owned_segments, options)) +} + +/// Constructs a flat vector containing the entire message, including a segment header. +#[cfg(feature = "alloc")] +pub fn write_message_to_words(message: &message::Builder) -> Vec +where + A: message::Allocator, +{ + flatten_segments(&*message.get_segments_for_output()) +} + +/// Like `write_message_to_words()`, but takes a `ReaderSegments`, allowing it to be +/// used on `message::Reader` objects (via `into_segments()`). +#[cfg(feature = "alloc")] +pub fn write_message_segments_to_words(message: &R) -> Vec +where + R: message::ReaderSegments, +{ + flatten_segments(message) +} + +#[cfg(feature = "alloc")] +fn flatten_segments(segments: &R) -> Vec { + let word_count = compute_serialized_size(segments); + let segment_count = segments.len(); + let table_size = segment_count / 2 + 1; + let mut result = Vec::with_capacity(word_count); + result.resize(table_size * BYTES_PER_WORD, 0); + { + let mut bytes = &mut result[..]; + write_segment_table_internal(&mut bytes, segments).expect("Failed to write segment table."); + } + for i in 0..segment_count { + let segment = segments.get_segment(i as u32).unwrap(); + result.extend(segment); + } + result +} + +/// Writes the provided message to `write`. +/// +/// For optimal performance, `write` should be a buffered writer. `flush()` will not be called on +/// the writer. +/// +/// The only source of errors from this function are `write.write_all()` calls. If you pass in +/// a writer that never returns an error, then this function will never return an error. +#[cfg(feature = "alloc")] +pub fn write_message(mut write: W, message: &message::Builder) -> Result<()> +where + W: Write, + A: message::Allocator, +{ + let segments = message.get_segments_for_output(); + write_segment_table(&mut write, &segments)?; + write_segments(&mut write, &segments) +} + +/// Like `write_message()`, but takes a `ReaderSegments`, allowing it to be +/// used on `message::Reader` objects (via `into_segments()`). +#[cfg(feature = "alloc")] +pub fn write_message_segments(mut write: W, segments: &R) -> Result<()> +where + W: Write, + R: message::ReaderSegments, +{ + write_segment_table_internal(&mut write, segments)?; + write_segments(&mut write, segments) +} + +#[cfg(feature = "alloc")] +fn write_segment_table(write: &mut W, segments: &[&[u8]]) -> Result<()> +where + W: Write, +{ + write_segment_table_internal(write, segments) +} + +/// Writes a segment table to `write`. +/// +/// `segments` must contain at least one segment. +#[cfg(feature = "alloc")] +fn write_segment_table_internal(write: &mut W, segments: &R) -> Result<()> +where + W: Write, + R: message::ReaderSegments + ?Sized, +{ + let mut buf: [u8; 8] = [0; 8]; + let segment_count = segments.len(); + + // write the first Word, which contains segment_count and the 1st segment length + buf[0..4].copy_from_slice(&(segment_count as u32 - 1).to_le_bytes()); + buf[4..8].copy_from_slice( + &((segments.get_segment(0).unwrap().len() / BYTES_PER_WORD) as u32).to_le_bytes(), + ); + write.write_all(&buf)?; + + if segment_count > 1 { + if segment_count < 4 { + for idx in 1..segment_count { + buf[(idx - 1) * 4..idx * 4].copy_from_slice( + &((segments.get_segment(idx as u32).unwrap().len() / BYTES_PER_WORD) as u32) + .to_le_bytes(), + ); + } + if segment_count == 2 { + for b in &mut buf[4..8] { + *b = 0 + } + } + write.write_all(&buf)?; + } else { + let mut buf = vec![0; (segment_count & !1) * 4]; + for idx in 1..segment_count { + buf[(idx - 1) * 4..idx * 4].copy_from_slice( + &((segments.get_segment(idx as u32).unwrap().len() / BYTES_PER_WORD) as u32) + .to_le_bytes(), + ); + } + if segment_count % 2 == 0 { + let start_idx = buf.len() - 4; + for b in &mut buf[start_idx..] { + *b = 0 + } + } + write.write_all(&buf)?; + } + } + Ok(()) +} + +/// Writes segments to `write`. +#[cfg(feature = "alloc")] +fn write_segments(write: &mut W, segments: &R) -> Result<()> +where + W: Write, +{ + for i in 0.. { + if let Some(segment) = segments.get_segment(i) { + write.write_all(segment)?; + } else { + break; + } + } + Ok(()) +} + +#[cfg(feature = "alloc")] +fn compute_serialized_size(segments: &R) -> usize { + // Table size + let len = segments.len(); + let mut size = (len / 2) + 1; + for i in 0..len { + let segment = segments.get_segment(i as u32).unwrap(); + size += segment.len() / BYTES_PER_WORD; + } + size +} + +/// Returns the number of (8-byte) words required to serialize the message (including the +/// segment table). +/// +/// Multiply this by 8 (or `std::mem::size_of::()`) to get the number of bytes +/// that [`write_message()`](fn.write_message.html) will write. +#[cfg(feature = "alloc")] +pub fn compute_serialized_size_in_words(message: &crate::message::Builder) -> usize +where + A: crate::message::Allocator, +{ + compute_serialized_size(&message.get_segments_for_output()) +} + +#[cfg(feature = "alloc")] +#[cfg(test)] +pub mod test { + use alloc::vec::Vec; + + use crate::io::{Read, Write}; + + use quickcheck::{quickcheck, TestResult}; + + use super::{ + flatten_segments, read_message, read_message_from_flat_slice, read_segment_table, + try_read_message, write_segment_table, write_segments, + }; + use crate::message; + use crate::message::ReaderSegments; + + /// Writes segments as if they were a Capnproto message. + pub fn write_message_segments(write: &mut W, segments: &[Vec]) + where + W: Write, + { + let borrowed_segments: &[&[u8]] = &segments + .iter() + .map(|segment| crate::Word::words_to_bytes(&segment[..])) + .collect::>()[..]; + write_segment_table(write, borrowed_segments).unwrap(); + write_segments(write, borrowed_segments).unwrap(); + } + + #[test] + fn try_read_empty() { + let mut buf: &[u8] = &[]; + assert!(try_read_message(&mut buf, message::ReaderOptions::new()) + .unwrap() + .is_none()); + } + + #[test] + fn test_read_segment_table() { + let mut buf = vec![]; + + buf.extend( + [ + 0, 0, 0, 0, // 1 segments + 0, 0, 0, 0, + ], // 0 length + ); + let segment_lengths_builder = + read_segment_table(&mut &buf[..], message::ReaderOptions::new()) + .unwrap() + .unwrap(); + assert_eq!(0, segment_lengths_builder.total_words()); + assert_eq!(vec![(0, 0)], segment_lengths_builder.to_segment_indices()); + buf.clear(); + + buf.extend( + [ + 0, 0, 0, 0, // 1 segments + 1, 0, 0, 0, + ], // 1 length + ); + let segment_lengths_builder = + read_segment_table(&mut &buf[..], message::ReaderOptions::new()) + .unwrap() + .unwrap(); + assert_eq!(1, segment_lengths_builder.total_words()); + assert_eq!(vec![(0, 1)], segment_lengths_builder.to_segment_indices()); + buf.clear(); + + buf.extend( + [ + 1, 0, 0, 0, // 2 segments + 1, 0, 0, 0, // 1 length + 1, 0, 0, 0, // 1 length + 0, 0, 0, 0, + ], // padding + ); + let segment_lengths_builder = + read_segment_table(&mut &buf[..], message::ReaderOptions::new()) + .unwrap() + .unwrap(); + assert_eq!(2, segment_lengths_builder.total_words()); + assert_eq!( + vec![(0, 1), (1, 2)], + segment_lengths_builder.to_segment_indices() + ); + buf.clear(); + + buf.extend( + [ + 2, 0, 0, 0, // 3 segments + 1, 0, 0, 0, // 1 length + 1, 0, 0, 0, // 1 length + 0, 1, 0, 0, + ], // 256 length + ); + let segment_lengths_builder = + read_segment_table(&mut &buf[..], message::ReaderOptions::new()) + .unwrap() + .unwrap(); + assert_eq!(258, segment_lengths_builder.total_words()); + assert_eq!( + vec![(0, 1), (1, 2), (2, 258)], + segment_lengths_builder.to_segment_indices() + ); + buf.clear(); + + buf.extend( + [ + 3, 0, 0, 0, // 4 segments + 77, 0, 0, 0, // 77 length + 23, 0, 0, 0, // 23 length + 1, 0, 0, 0, // 1 length + 99, 0, 0, 0, // 99 length + 0, 0, 0, 0, + ], // padding + ); + let segment_lengths_builder = + read_segment_table(&mut &buf[..], message::ReaderOptions::new()) + .unwrap() + .unwrap(); + assert_eq!(200, segment_lengths_builder.total_words()); + assert_eq!( + vec![(0, 77), (77, 100), (100, 101), (101, 200)], + segment_lengths_builder.to_segment_indices() + ); + buf.clear(); + } + + struct MaxRead + where + R: Read, + { + inner: R, + max: usize, + } + + impl Read for MaxRead + where + R: Read, + { + fn read(&mut self, buf: &mut [u8]) -> crate::Result { + if buf.len() <= self.max { + self.inner.read(buf) + } else { + self.inner.read(&mut buf[0..self.max]) + } + } + } + + #[test] + fn test_read_segment_table_max_read() { + // Make sure things still work well when we read less than a word at a time. + let mut buf: Vec = vec![]; + buf.extend( + [ + 0, 0, 0, 0, // 1 segments + 1, 0, 0, 0, + ], // 1 length + ); + let segment_lengths_builder = read_segment_table( + &mut MaxRead { + inner: &buf[..], + max: 2, + }, + message::ReaderOptions::new(), + ) + .unwrap() + .unwrap(); + assert_eq!(1, segment_lengths_builder.total_words()); + assert_eq!(vec![(0, 1)], segment_lengths_builder.to_segment_indices()); + } + + #[test] + fn test_read_invalid_segment_table() { + let mut buf = vec![]; + + buf.extend([0, 2, 0, 0]); // 513 segments + buf.extend([0; 513 * 4]); + assert!(read_segment_table(&mut &buf[..], message::ReaderOptions::new()).is_err()); + buf.clear(); + + buf.extend([0, 0, 0, 0]); // 1 segments + assert!(read_segment_table(&mut &buf[..], message::ReaderOptions::new()).is_err()); + buf.clear(); + + buf.extend([0, 0, 0, 0]); // 1 segments + buf.extend([0; 3]); + assert!(read_segment_table(&mut &buf[..], message::ReaderOptions::new()).is_err()); + buf.clear(); + + buf.extend([255, 255, 255, 255]); // 0 segments + assert!(read_segment_table(&mut &buf[..], message::ReaderOptions::new()).is_err()); + buf.clear(); + } + + #[test] + fn test_write_segment_table() { + let mut buf = vec![]; + + let segment_0 = [0u8; 0]; + let segment_1 = [1u8, 1, 1, 1, 1, 1, 1, 1]; + let segment_199 = [201u8; 199 * 8]; + + write_segment_table(&mut buf, &[&segment_0]).unwrap(); + assert_eq!( + &[ + 0, 0, 0, 0, // 1 segments + 0, 0, 0, 0 + ], // 0 length + &buf[..] + ); + buf.clear(); + + write_segment_table(&mut buf, &[&segment_1]).unwrap(); + assert_eq!( + &[ + 0, 0, 0, 0, // 1 segments + 1, 0, 0, 0 + ], // 1 length + &buf[..] + ); + buf.clear(); + + write_segment_table(&mut buf, &[&segment_199]).unwrap(); + assert_eq!( + &[ + 0, 0, 0, 0, // 1 segments + 199, 0, 0, 0 + ], // 199 length + &buf[..] + ); + buf.clear(); + + write_segment_table(&mut buf, &[&segment_0, &segment_1]).unwrap(); + assert_eq!( + &[ + 1, 0, 0, 0, // 2 segments + 0, 0, 0, 0, // 0 length + 1, 0, 0, 0, // 1 length + 0, 0, 0, 0 + ], // padding + &buf[..] + ); + buf.clear(); + + write_segment_table( + &mut buf, + &[&segment_199, &segment_1, &segment_199, &segment_0], + ) + .unwrap(); + assert_eq!( + &[ + 3, 0, 0, 0, // 4 segments + 199, 0, 0, 0, // 199 length + 1, 0, 0, 0, // 1 length + 199, 0, 0, 0, // 199 length + 0, 0, 0, 0, // 0 length + 0, 0, 0, 0 + ], // padding + &buf[..] + ); + buf.clear(); + + write_segment_table( + &mut buf, + &[ + &segment_199, + &segment_1, + &segment_199, + &segment_0, + &segment_1, + ], + ) + .unwrap(); + assert_eq!( + &[ + 4, 0, 0, 0, // 5 segments + 199, 0, 0, 0, // 199 length + 1, 0, 0, 0, // 1 length + 199, 0, 0, 0, // 199 length + 0, 0, 0, 0, // 0 length + 1, 0, 0, 0 + ], // 1 length + &buf[..] + ); + buf.clear(); + } + + quickcheck! { + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_round_trip(segments: Vec>) -> TestResult { + if segments.is_empty() { return TestResult::discard(); } + let mut buf: Vec = Vec::new(); + + write_message_segments(&mut buf, &segments); + let message = read_message(&mut &buf[..], message::ReaderOptions::new()).unwrap(); + let result_segments = message.into_segments(); + + TestResult::from_bool(segments.iter().enumerate().all(|(i, segment)| { + crate::Word::words_to_bytes(&segment[..]) == result_segments.get_segment(i as u32).unwrap() + })) + } + + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_round_trip_slice_segments(segments: Vec>) -> TestResult { + if segments.is_empty() { return TestResult::discard(); } + let borrowed_segments: &[&[u8]] = &segments.iter() + .map(|segment| crate::Word::words_to_bytes(&segment[..])) + .collect::>()[..]; + let words = flatten_segments(borrowed_segments); + let mut word_slice = &words[..]; + let message = read_message_from_flat_slice(&mut word_slice, message::ReaderOptions::new()).unwrap(); + assert!(word_slice.is_empty()); // no remaining words + let result_segments = message.into_segments(); + + TestResult::from_bool(segments.iter().enumerate().all(|(i, segment)| { + crate::Word::words_to_bytes(&segment[..]) == result_segments.get_segment(i as u32).unwrap() + })) + } + } + + #[test] + fn read_message_from_flat_slice_with_remainder() { + let segments = vec![ + vec![123, 0, 0, 0, 0, 0, 0, 0], + vec![4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0], + ]; + + let borrowed_segments: &[&[u8]] = &segments + .iter() + .map(|segment| &segment[..]) + .collect::>()[..]; + + let mut bytes = flatten_segments(borrowed_segments); + let extra_bytes: &[u8] = &[9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + for &b in extra_bytes { + bytes.push(b); + } + let mut byte_slice = &bytes[..]; + let message = + read_message_from_flat_slice(&mut byte_slice, message::ReaderOptions::new()).unwrap(); + assert_eq!(byte_slice, extra_bytes); + let result_segments = message.into_segments(); + for (idx, segment) in segments.iter().enumerate() { + assert_eq!( + *segment, + result_segments + .get_segment(idx as u32) + .expect("segment should exist") + ); + } + } + + #[test] + fn read_message_from_flat_slice_too_short() { + let segments = vec![ + vec![1, 0, 0, 0, 0, 0, 0, 0], + vec![2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0], + ]; + + let borrowed_segments: &[&[u8]] = &segments + .iter() + .map(|segment| &segment[..]) + .collect::>()[..]; + + let mut bytes = flatten_segments(borrowed_segments); + while !bytes.is_empty() { + bytes.pop(); + assert!( + read_message_from_flat_slice(&mut &bytes[..], message::ReaderOptions::new()) + .is_err() + ); + } + } + + #[test] + fn compute_serialized_size() { + const LIST_LENGTH_IN_WORDS: u32 = 5; + let mut m = message::Builder::new_default(); + { + let root: crate::any_pointer::Builder = m.init_root(); + let _list_builder: crate::primitive_list::Builder = + root.initn_as(LIST_LENGTH_IN_WORDS); + } + + // The message body has a list pointer (one word) and the list (LIST_LENGTH_IN_WORDS words). + // The message has one segment, so the header is one word. + assert_eq!( + super::compute_serialized_size_in_words(&m) as u32, + 1 + 1 + LIST_LENGTH_IN_WORDS + ) + } +} diff --git a/rust/capnp/serialize/no_alloc_buffer_segments.rs b/rust/capnp/serialize/no_alloc_buffer_segments.rs new file mode 100644 index 000000000000..d3837738d702 --- /dev/null +++ b/rust/capnp/serialize/no_alloc_buffer_segments.rs @@ -0,0 +1,627 @@ +use core::convert::TryInto; + +use crate::message::ReaderOptions; +use crate::message::ReaderSegments; +use crate::private::units::BYTES_PER_WORD; +use crate::{Error, ErrorKind, Result}; +use core::ops::Deref; + +use super::SEGMENTS_COUNT_LIMIT; + +const U32_LEN_IN_BYTES: usize = core::mem::size_of::(); + +struct ReadSegmentTableResult { + segments_count: usize, + segment_table_length_bytes: usize, + total_segments_length_bytes: usize, +} + +fn read_segment_table(slice: &[u8], options: ReaderOptions) -> Result { + let mut remaining = slice; + + verify_alignment(remaining.as_ptr())?; + + let segments_count = u32_to_segments_count(read_u32_le(&mut remaining)?)?; + + if segments_count >= SEGMENTS_COUNT_LIMIT { + return Err(Error::from_kind(ErrorKind::InvalidNumberOfSegments( + segments_count, + ))); + } + + let mut total_segments_length_bytes = 0_usize; + + for _ in 0..segments_count { + let segment_length_in_bytes = u32_to_segment_length_bytes(read_u32_le(&mut remaining)?)?; + + total_segments_length_bytes = total_segments_length_bytes + .checked_add(segment_length_in_bytes) + .ok_or_else(|| Error::from_kind(ErrorKind::MessageSizeOverflow))?; + } + + // Don't accept a message which the receiver couldn't possibly traverse without hitting the + // traversal limit. Without this check, a malicious client could transmit a very large segment + // size to make the receiver allocate excessive space and possibly crash. + if let Some(limit) = options.traversal_limit_in_words { + let total_segments_length_words = total_segments_length_bytes / 8; + if total_segments_length_words > limit { + return Err(Error::from_kind(ErrorKind::MessageTooLarge( + total_segments_length_words, + ))); + } + } + + // If number of segments is even, header length will not be aligned by 8, we need to consume + // padding from the remainder of the message + if segments_count % 2 == 0 { + let _padding = read_u32_le(&mut remaining)?; + } + + let expected_data_offset = calculate_data_offset(segments_count) + .ok_or_else(|| Error::from_kind(ErrorKind::MessageSizeOverflow))?; + + let consumed_bytes = slice.len() - remaining.len(); + + assert_eq!( + expected_data_offset, consumed_bytes, + "Expected header size and actual header size must match, otherwise we have a bug in this code" + ); + + // If data section of the message is smaller than calculated total segments length, the message + // is malformed. It looks like it's ok to have extra bytes in the end, according to + // of `SliceSegments` implementation. + if remaining.len() < total_segments_length_bytes { + return Err(Error::from_kind(ErrorKind::MessageEndsPrematurely( + total_segments_length_bytes / BYTES_PER_WORD, + remaining.len() / BYTES_PER_WORD, + ))); + } + + Ok(ReadSegmentTableResult { + segments_count, + segment_table_length_bytes: expected_data_offset, + total_segments_length_bytes, + }) +} + +/// Alias for the common case where the buffer in `NoAllocBufferSegments` is a u8 slice. +pub type NoAllocSliceSegments<'b> = NoAllocBufferSegments<&'b [u8]>; + +enum NoAllocBufferSegmentType { + SingleSegment(usize, usize), + MultipleSegments, +} + +/// `NoAllocBufferSegments` is similar to [`crate::serialize::BufferSegments`] but optimized for +/// low memory embedded environment. It does not do heap allocations. +/// +/// # Performance considerations +/// +/// Due to lack of heap allocations, `NoAllocBufferSegments` does not cache segments offset and +/// length and has to parse message header every time `NoAllocBufferSegments::get_segment` is called. +/// The parsing has O(N) complexity where N is total number of segments in the message. +/// `NoAllocBufferSegments` has optimization for single segment messages: if message has only one +/// segment, it will be parsed only once during creation and no parsing will be required on `get_segment` calls +pub struct NoAllocBufferSegments { + buffer: T, + segment_type: NoAllocBufferSegmentType, +} + +impl<'b> NoAllocBufferSegments<&'b [u8]> { + /// Reads a serialized message (including a segment table) from a buffer and takes ownership, without copying. + /// The buffer is allowed to extend beyond the end of the message. On success, updates `slice` to point + /// to the remaining bytes beyond the end of the message. + /// + /// ALIGNMENT: If the "unaligned" feature is enabled, then there are no alignment requirements on `buffer`. + /// Otherwise, `buffer` must be 8-byte aligned (attempts to read the message will trigger errors). + pub fn from_slice(slice: &mut &'b [u8], options: ReaderOptions) -> Result { + let segment_table_info = read_segment_table(slice, options)?; + + let message_length = segment_table_info.segment_table_length_bytes + + segment_table_info.total_segments_length_bytes; + + let message = &slice[..message_length]; + *slice = &slice[message_length..]; + + if segment_table_info.segments_count == 1 { + Ok(Self { + buffer: message, + segment_type: NoAllocBufferSegmentType::SingleSegment( + segment_table_info.segment_table_length_bytes, + message_length, + ), + }) + } else { + Ok(Self { + buffer: message, + segment_type: NoAllocBufferSegmentType::MultipleSegments, + }) + } + } +} + +impl> NoAllocBufferSegments { + /// Reads a serialized message (including a segment table) from a buffer and takes ownership, without copying. + /// The buffer is allowed to extend beyond the end of the message. + /// + /// ALIGNMENT: If the "unaligned" feature is enabled, then there are no alignment requirements on `buffer`. + /// Otherwise, `buffer` must be 8-byte aligned (attempts to read the message will trigger errors). + pub fn from_buffer(buffer: T, options: ReaderOptions) -> Result { + let segment_table_info = read_segment_table(&buffer, options)?; + let message_length = segment_table_info.segment_table_length_bytes + + segment_table_info.total_segments_length_bytes; + + if segment_table_info.segments_count == 1 { + Ok(Self { + buffer, + segment_type: NoAllocBufferSegmentType::SingleSegment( + segment_table_info.segment_table_length_bytes, + message_length, + ), + }) + } else { + Ok(Self { + buffer, + segment_type: NoAllocBufferSegmentType::MultipleSegments, + }) + } + } +} + +impl> ReaderSegments for NoAllocBufferSegments { + fn get_segment(&self, idx: u32) -> Option<&[u8]> { + // panic safety: we are doing a lot of `unwrap` here. We assume that underlying message slice + // holds valid capnp message - we already verified slice in read_segment_table(), + // so these unwraps are not expected to panic unless we have bug in the code. + + let idx: usize = idx.try_into().unwrap(); + + match self.segment_type { + NoAllocBufferSegmentType::SingleSegment(start, end) => { + if idx == 0 { + Some(&self.buffer[start..end]) + } else { + None + } + } + NoAllocBufferSegmentType::MultipleSegments => { + let mut buf = &*self.buffer; + + let segments_count = u32_to_segments_count(read_u32_le(&mut buf).unwrap()).unwrap(); + + if idx >= segments_count { + return None; + } + + let mut segment_offset = calculate_data_offset(segments_count).unwrap(); + + for _ in 0..idx { + segment_offset = segment_offset + .checked_add( + u32_to_segment_length_bytes(read_u32_le(&mut buf).unwrap()).unwrap(), + ) + .unwrap(); + } + + let segment_length = + u32_to_segment_length_bytes(read_u32_le(&mut buf).unwrap()).unwrap(); + + Some(&self.buffer[segment_offset..(segment_offset + segment_length)]) + } + } + } + + fn len(&self) -> usize { + // panic safety: we are doing a lot of `unwrap` here. We assume that underlying message slice + // holds valid capnp message - we already verified slice in read_segment_table(), + + match self.segment_type { + NoAllocBufferSegmentType::SingleSegment { .. } => 1, + NoAllocBufferSegmentType::MultipleSegments => { + u32_to_segments_count(read_u32_le(&mut &*self.buffer).unwrap()).unwrap() + } + } + } +} + +/// Verifies whether pointer meets alignment requirements +/// +/// If crate is compiled with "unaligned" feature, then this function does nothing since +/// there are no alignment requirements in this mode. +/// +/// If crate was not compiled with "unaligned" feature, it will verify that pointer is aligned +/// by WORD boundary. +fn verify_alignment(ptr: *const u8) -> Result<()> { + if cfg!(feature = "unaligned") { + return Ok(()); + } + + if ptr.align_offset(BYTES_PER_WORD) == 0 { + Ok(()) + } else { + Err(Error::from_kind( + ErrorKind::MessageNotAlignedBy8BytesBoundary, + )) + } +} + +/// Reads u32 little endian value from the front of the slice and truncates processed bytes +/// Returns Error if there are not enough bytes to read u32 +fn read_u32_le(slice: &mut &[u8]) -> Result { + if slice.len() < U32_LEN_IN_BYTES { + return Err(Error::from_kind(ErrorKind::MessageEndsPrematurely( + U32_LEN_IN_BYTES, + slice.len(), + ))); + } + + // Panic safety: we just confirmed that `slice` has at least `U32_LEN_IN_BYTES` so nothing + // here should panic + let u32_buf: [u8; U32_LEN_IN_BYTES] = slice[..U32_LEN_IN_BYTES].try_into().unwrap(); + *slice = &slice[U32_LEN_IN_BYTES..]; + + Ok(u32::from_le_bytes(u32_buf)) +} + +/// Converts 32 bit value which represents encoded segments count in header to usize segment count +fn u32_to_segments_count(val: u32) -> Result { + // This conversion can fail on 8 or 16 bit machines. + let result: Option = val.try_into().ok(); + + // According to encoding schema, segments count is encoded as (count - 1), where 0 means one + // segment, 1 - two segments and so on, so we need to add +1 to value read from the stream. + // We need to do +1 to value read from the stream. + let result = result.and_then(|v: usize| v.checked_add(1)); + + result.ok_or_else(|| Error::from_kind(ErrorKind::FourByteLengthTooBigForUSize)) +} + +/// Converts 32 bit vlaue which represents encoded segment length to usize segment length in bytes +fn u32_to_segment_length_bytes(val: u32) -> Result { + // This convertion can fail on 8 or 16 bit machines. + let length_in_words: Option = val.try_into().ok(); + + let length_in_bytes = length_in_words.and_then(|l| l.checked_mul(BYTES_PER_WORD)); + + length_in_bytes.ok_or_else(|| Error::from_kind(ErrorKind::FourByteSegmentLengthTooBigForUSize)) +} + +/// Calculates expected offset of the message data (beginning of first segment) +/// in the capnp message. +/// Message data comes right after message header and potential padding +/// +/// Returns None if it's impossible to calculate offset without arithmentic overflow of usize or +/// if segments count is invalid +fn calculate_data_offset(segments_count: usize) -> Option { + // Message data goes right after message header. + // Message header has following format: + // + // Segment count (u32) + // Segments length (u32 per each segment) + // Padding to align header size by 8 bytes (it will be either 0 bytes or 4 bytes) + + // It should be impossible to have properly encoded message with 0 segments + if segments_count == 0 { + return None; + } + + let mut data_offset = 0_usize; + + { + // 4 bytes encoded segments count + let segments_count_len = U32_LEN_IN_BYTES; + data_offset = data_offset.checked_add(segments_count_len)?; + } + + { + // 4 bytes per each segment + let segments_lengt_len = segments_count.checked_mul(U32_LEN_IN_BYTES)?; + data_offset = data_offset.checked_add(segments_lengt_len)?; + } + + // Message data must be aligned by 8 bytes. If there was even number of segments, then + // header size will not be aligned by 8, in this case we have to add 4 byte padding to make + // data offset aligned by 8. + let padding_len = match data_offset % BYTES_PER_WORD { + 0 => 0, + 4 => 4, + _ => unreachable!( + "Mis-alignment by anything other than 4 should be impossible, this is a bug" + ), + }; + + data_offset = data_offset.checked_add(padding_len)?; + + // It's a sanity check to ensure that message offset has correct alignment + assert_eq!( + data_offset % BYTES_PER_WORD, + 0, + "data_offset after adding panic must be aligned by 8. \ + If it's not, it's a bug" + ); + + Some(data_offset) +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "alloc")] + use quickcheck::{quickcheck, TestResult}; + + use super::calculate_data_offset; + #[cfg(feature = "alloc")] + use crate::{ + message::{ReaderOptions, ReaderSegments}, + serialize, word, Word, + }; + + #[cfg(feature = "alloc")] + use crate::OutputSegments; + + use super::{ + read_u32_le, u32_to_segment_length_bytes, u32_to_segments_count, verify_alignment, + }; + #[cfg(feature = "alloc")] + use super::{NoAllocBufferSegmentType, NoAllocBufferSegments, NoAllocSliceSegments}; + + #[cfg(feature = "alloc")] + use alloc::vec::Vec; + + #[repr(align(8))] + struct Aligned([u8; 8]); + + #[cfg(feature = "unaligned")] + #[test] + fn test_verify_alignment_unaligned_mode() { + // To run this test do + // `% cargo test --features unaligned` + + // make sure there is no padding + assert_eq!(core::mem::size_of::(), 8); + + let aligned = Aligned([0; 8]); + + // no alignment requirements in "unaligned" mode + for idx in 0..8 { + verify_alignment(unsafe { aligned.0.as_ptr().add(idx) }).unwrap(); + } + } + + #[cfg(not(feature = "unaligned"))] + #[test] + fn test_verify_alignment() { + // make sure there is no padding + assert_eq!(core::mem::size_of::(), 8); + + let aligned = Aligned([0; 8]); + + verify_alignment(aligned.0.as_ptr()).unwrap(); + for idx in 1..8 { + verify_alignment(unsafe { aligned.0.as_ptr().add(idx) }).unwrap_err(); + } + } + + #[test] + fn test_read_u32_le() { + let buffer = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; + let mut buffer_remaining = &buffer[..]; + + assert_eq!(read_u32_le(&mut buffer_remaining).unwrap(), 0x04030201); + assert_eq!(buffer_remaining, &buffer[4..]); + } + + #[test] + fn test_read_u32_le_truncated() { + let buffer = [0x01, 0x02, 0x03]; + let mut buffer_remaining = &buffer[..]; + + read_u32_le(&mut buffer_remaining).unwrap_err(); + assert_eq!(buffer_remaining, &buffer[..]); + } + + #[test] + fn test_u32_to_segments_count() { + assert_eq!(u32_to_segments_count(0).unwrap(), 1); + assert_eq!(u32_to_segments_count(10).unwrap(), 11); + // There is no way to reproduce "negative" case on 64 bit machine + } + + #[test] + fn test_u32_to_segment_length_bytes() { + assert_eq!(u32_to_segment_length_bytes(0).unwrap(), 0); + assert_eq!(u32_to_segment_length_bytes(123).unwrap(), 123 * 8); + } + + #[test] + fn test_calculate_data_offset_no_padding() { + assert_eq!(calculate_data_offset(0), None); + + assert_eq!(calculate_data_offset(1), Some(8)); + + assert_eq!(calculate_data_offset(2), Some(16)); + assert_eq!(calculate_data_offset(3), Some(16)); + + assert_eq!(calculate_data_offset(100), Some(408)); + assert_eq!(calculate_data_offset(101), Some(408)); + } + + #[cfg(feature = "alloc")] + quickcheck! { + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_no_alloc_buffer_segments_single_segment_optimization( + segment_0 : Vec) -> TestResult + { + let words = &segment_0[..]; + let bytes = Word::words_to_bytes(words); + let output_segments = OutputSegments::SingleSegment([bytes]); + let mut msg = vec![]; + + serialize::write_message_segments(&mut msg, &output_segments).unwrap(); + + let no_alloc_segments = + NoAllocSliceSegments::from_slice(&mut msg.as_slice(), ReaderOptions::new()).unwrap(); + + assert!(matches!( + no_alloc_segments, + NoAllocBufferSegments { buffer: _, + segment_type : NoAllocBufferSegmentType::SingleSegment { .. }, + } + )); + + assert_eq!(no_alloc_segments.len(), 1); + assert_eq!(no_alloc_segments.get_segment(0), Some(bytes)); + assert_eq!(no_alloc_segments.get_segment(1), None); + TestResult::from_bool(true) + } + + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_no_alloc_buffer_segments_multiple_segments(segments_vec: Vec>) -> TestResult { + if segments_vec.is_empty() { return TestResult::discard() }; + + let segments: Vec<_> = segments_vec.iter().map(|s| + Word::words_to_bytes(s.as_slice())).collect(); + + let output_segments = OutputSegments::MultiSegment(segments.clone()); + + let mut msg = vec![]; + + serialize::write_message_segments(&mut msg, &output_segments).unwrap(); + + let no_alloc_segments = + NoAllocSliceSegments::from_slice(&mut msg.as_slice(), ReaderOptions::new()).unwrap(); + + assert_eq!(no_alloc_segments.len(), segments.len()); + for (i, segment) in segments.iter().enumerate() { + assert_eq!(no_alloc_segments.get_segment(i as u32), Some(*segment)); + } + + assert_eq!( + no_alloc_segments.get_segment(no_alloc_segments.len() as u32), + None + ); + TestResult::from_bool(true) + } + } + + #[cfg(feature = "alloc")] + #[test] + fn test_no_alloc_buffer_segments_message_postfix() { + let output_segments = OutputSegments::SingleSegment([&[1, 2, 3, 4, 5, 6, 7, 8]]); + let mut buf = Word::allocate_zeroed_vec(2); + serialize::write_message_segments(Word::words_to_bytes_mut(&mut buf), &output_segments) + .unwrap(); + buf.push(word(11, 12, 13, 14, 15, 16, 0, 0)); + + let remaining = &mut Word::words_to_bytes(&buf); + NoAllocSliceSegments::from_slice(remaining, ReaderOptions::new()).unwrap(); + + // Confirm that slice pointer was advanced to data past first message + assert_eq!(*remaining, &[11, 12, 13, 14, 15, 16, 0, 0]); + } + + #[cfg(feature = "alloc")] + #[test] + fn test_no_alloc_buffer_segments_message_invalid() { + let mut buf = vec![]; + + buf.extend([0, 2, 0, 0]); // 513 segments + buf.extend([0; 513 * 8]); + assert!(NoAllocSliceSegments::from_slice(&mut &buf[..], ReaderOptions::new()).is_err()); + buf.clear(); + + buf.extend([0, 0, 0, 0]); // 1 segments + assert!(NoAllocSliceSegments::from_slice(&mut &buf[..], ReaderOptions::new()).is_err()); + buf.clear(); + + buf.extend([0, 0, 0, 0]); // 1 segments + buf.extend([0; 3]); + assert!(NoAllocSliceSegments::from_slice(&mut &buf[..], ReaderOptions::new()).is_err()); + buf.clear(); + + buf.extend([255, 255, 255, 255]); // 0 segments + assert!(NoAllocSliceSegments::from_slice(&mut &buf[..], ReaderOptions::new()).is_err()); + buf.clear(); + } + + #[cfg(feature = "alloc")] + quickcheck! { + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_no_alloc_buffer_segments_message_truncated(segments_vec: Vec>) -> TestResult { + if segments_vec.is_empty() { return TestResult::discard() } + + let segments: Vec<_> = segments_vec.iter() + .map(|s| Word::words_to_bytes(s.as_slice())).collect(); + + let output_segments = OutputSegments::MultiSegment(segments.clone()); + + let mut msg = vec![]; + + serialize::write_message_segments(&mut msg, &output_segments).unwrap(); + + // Lop off the final element. + msg.pop().unwrap(); + + let no_alloc_segments = + NoAllocSliceSegments::from_slice(&mut msg.as_slice(), ReaderOptions::new()); + + assert!(no_alloc_segments.is_err()); + TestResult::from_bool(true) + } + + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_no_alloc_buffer_segments_message_options_limit( + segments_vec: Vec>) -> TestResult + { + let mut word_count = 0; + let segments: Vec<_> = segments_vec.iter() + .map(|s| { + let ws = Word::words_to_bytes(s.as_slice()); + word_count += s.len(); + ws + }).collect(); + if word_count == 0 { return TestResult::discard() }; + + let output_segments = OutputSegments::MultiSegment(segments.clone()); + + let mut msg = vec![]; + + serialize::write_message_segments(&mut msg, &output_segments).unwrap(); + + let mut options = ReaderOptions::new(); + options.traversal_limit_in_words(Some(word_count)); + + let _no_alloc_segments = + NoAllocSliceSegments::from_slice(&mut msg.as_slice(), options).unwrap(); + + let mut options = ReaderOptions::new(); + options.traversal_limit_in_words(Some(word_count - 1)); + + let no_alloc_segments = NoAllocSliceSegments::from_slice(&mut msg.as_slice(), options); + + assert!(no_alloc_segments.is_err()); + TestResult::from_bool(true) + } + + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_no_alloc_buffer_segments_bad_alignment(segment_0: Vec) -> TestResult { + if segment_0.is_empty() { return TestResult::discard(); } + let output_segments = OutputSegments::SingleSegment([Word::words_to_bytes(&segment_0)]); + + let mut msg = vec![]; + + serialize::write_message_segments(&mut msg, &output_segments).unwrap(); + // mis-align buffer by 1 byte + msg.insert(0_usize, 0_u8); + + let no_alloc_segments = NoAllocSliceSegments::from_slice(&mut &msg[1..], ReaderOptions::new()); + + if cfg!(feature = "unaligned") { + // If we build with "unaligned" feature, alignment requirements should not be enforced + no_alloc_segments.unwrap(); + } else { + assert!(no_alloc_segments.is_err()); + } + TestResult::from_bool(true) + } + } +} diff --git a/rust/capnp/serialize_packed.rs b/rust/capnp/serialize_packed.rs new file mode 100644 index 000000000000..286a36950981 --- /dev/null +++ b/rust/capnp/serialize_packed.rs @@ -0,0 +1,618 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! Reading and writing of messages using the +//! [packed stream encoding](https://capnproto.org/encoding.html#packing). + +use crate::io::{BufRead, Read, Write}; +use core::{mem, ptr, slice}; + +#[cfg(feature = "alloc")] +use crate::message; +#[cfg(feature = "alloc")] +use crate::serialize; +use crate::{Error, ErrorKind, Result}; + +/// A `BufRead` wrapper that unpacks packed data. Returns an error on any `read()` +/// call that would end within an all-zero (tag 0x00) or uncompressed (tag 0xff) +/// run of words. Calls that come from `serialize_packed::read_message()` and +/// `serialize_packed::try_read_message()` always mirror `write()` calls from +/// `serialize_packed::write_message()`, so they always safely span such runs. +struct PackedRead +where + R: BufRead, +{ + inner: R, +} + +impl PackedRead +where + R: BufRead, +{ + fn get_read_buffer(&mut self) -> Result<(*const u8, *const u8)> { + let buf = self.inner.fill_buf()?; + Ok((buf.as_ptr(), buf.as_ptr().wrapping_add(buf.len()))) + } +} + +#[inline] +fn ptr_sub(p1: *const T, p2: *const T) -> usize { + (p1 as usize - p2 as usize) / mem::size_of::() +} + +macro_rules! refresh_buffer( + ($this:expr, $size:ident, $in_ptr:ident, $in_end:ident, $out:ident, + $outBuf:ident, $buffer_begin:ident) => ( + { + $this.inner.consume($size); + let (b, e) = $this.get_read_buffer()?; + $in_ptr = b; + $in_end = e; + $size = ptr_sub($in_end, $in_ptr); + $buffer_begin = b; + if $size == 0 { + return Err(Error::from_kind(ErrorKind::PrematureEndOfPackedInput)); + } + } + ); + ); + +impl Read for PackedRead +where + R: BufRead, +{ + fn read(&mut self, out_buf: &mut [u8]) -> Result { + let len = out_buf.len(); + if len == 0 { + return Ok(0); + } + + assert!(len % 8 == 0, "PackedRead reads must be word-aligned."); + + unsafe { + let out_buf_start = out_buf.as_mut_ptr(); + let mut out = out_buf_start; + let out_end: *mut u8 = out.wrapping_add(len); + + let (mut in_ptr, mut in_end) = self.get_read_buffer()?; + let mut buffer_begin = in_ptr; + let mut size = ptr_sub(in_end, in_ptr); + if size == 0 { + return Ok(0); + } + + loop { + let tag: u8; + + assert_eq!( + ptr_sub(out, out_buf_start) % 8, + 0, + "Output pointer should always be aligned here." + ); + + if ptr_sub(in_end, in_ptr) < 10 { + if ptr_sub(in_end, in_ptr) == 0 { + refresh_buffer!(self, size, in_ptr, in_end, out, out_buf, buffer_begin); + continue; + } + + //# We have at least 1, but not 10, bytes available. We need to read + //# slowly, doing a bounds check on each byte. + + tag = *in_ptr; + in_ptr = in_ptr.offset(1); + + for i in 0..8 { + if (tag & (1u8 << i)) != 0 { + if ptr_sub(in_end, in_ptr) == 0 { + refresh_buffer!( + self, + size, + in_ptr, + in_end, + out, + out_buf, + buffer_begin + ); + } + *out = *in_ptr; + out = out.offset(1); + in_ptr = in_ptr.offset(1); + } else { + *out = 0; + out = out.offset(1); + } + } + + if ptr_sub(in_end, in_ptr) == 0 && (tag == 0 || tag == 0xff) { + refresh_buffer!(self, size, in_ptr, in_end, out, out_buf, buffer_begin); + } + } else { + tag = *in_ptr; + in_ptr = in_ptr.offset(1); + + for n in 0..8 { + let is_nonzero = (tag & (1u8 << n)) != 0; + *out = (*in_ptr) & ((-i8::from(is_nonzero)) as u8); + out = out.offset(1); + in_ptr = in_ptr.offset(isize::from(is_nonzero)); + } + } + if tag == 0 { + assert!( + ptr_sub(in_end, in_ptr) > 0, + "Should always have non-empty buffer here." + ); + + let run_length: usize = (*in_ptr) as usize * 8; + in_ptr = in_ptr.offset(1); + + if run_length > ptr_sub(out_end, out) { + return Err(Error::from_kind( + ErrorKind::PackedInputDidNotEndCleanlyOnASegmentBoundary, + )); + } + + ptr::write_bytes(out, 0, run_length); + out = out.add(run_length); + } else if tag == 0xff { + assert!( + ptr_sub(in_end, in_ptr) > 0, + "Should always have non-empty buffer here" + ); + + let mut run_length: usize = (*in_ptr) as usize * 8; + in_ptr = in_ptr.offset(1); + + if run_length > ptr_sub(out_end, out) { + return Err(Error::from_kind( + ErrorKind::PackedInputDidNotEndCleanlyOnASegmentBoundary, + )); + } + + let in_remaining = ptr_sub(in_end, in_ptr); + if in_remaining >= run_length { + //# Fast path. + ptr::copy_nonoverlapping(in_ptr, out, run_length); + out = out.add(run_length); + in_ptr = in_ptr.add(run_length); + } else { + //# Copy over the first buffer, then do one big read for the rest. + ptr::copy_nonoverlapping(in_ptr, out, in_remaining); + out = out.add(in_remaining); + run_length -= in_remaining; + + self.inner.consume(size); + { + let buf = slice::from_raw_parts_mut::(out, run_length); + self.inner.read_exact(buf)?; + } + + out = out.add(run_length); + + if out == out_end { + return Ok(len); + } else { + let (b, e) = self.get_read_buffer()?; + in_ptr = b; + in_end = e; + size = ptr_sub(e, b); + buffer_begin = in_ptr; + continue; + } + } + } + + if out == out_end { + self.inner.consume(ptr_sub(in_ptr, buffer_begin)); + return Ok(len); + } + } + } + } +} + +/// Reads a packed message from a stream using the provided options. +#[cfg(feature = "alloc")] +pub fn read_message( + read: R, + options: message::ReaderOptions, +) -> Result> +where + R: BufRead, +{ + let packed_read = PackedRead { inner: read }; + serialize::read_message(packed_read, options) +} + +/// Like read_message(), but returns None instead of an error if there are zero bytes left in `read`. +#[cfg(feature = "alloc")] +pub fn try_read_message( + read: R, + options: message::ReaderOptions, +) -> Result>> +where + R: BufRead, +{ + let packed_read = PackedRead { inner: read }; + serialize::try_read_message(packed_read, options) +} + +struct PackedWrite +where + W: Write, +{ + inner: W, +} + +impl Write for PackedWrite +where + W: Write, +{ + fn write_all(&mut self, in_buf: &[u8]) -> Result<()> { + unsafe { + let mut buf_idx: usize = 0; + let mut buf: [u8; 64] = [0; 64]; + + let mut in_ptr: *const u8 = in_buf.as_ptr(); + let in_end: *const u8 = in_buf.as_ptr().wrapping_add(in_buf.len()); + + while in_ptr < in_end { + if buf_idx + 10 > buf.len() { + //# Oops, we're out of space. We need at least 10 + //# bytes for the fast path, since we don't + //# bounds-check on every byte. + self.inner.write_all(&buf[..buf_idx])?; + buf_idx = 0; + } + + let tag_pos = buf_idx; + buf_idx += 1; + + let bit0 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit0 as usize; + in_ptr = in_ptr.offset(1); + + let bit1 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit1 as usize; + in_ptr = in_ptr.offset(1); + + let bit2 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit2 as usize; + in_ptr = in_ptr.offset(1); + + let bit3 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit3 as usize; + in_ptr = in_ptr.offset(1); + + let bit4 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit4 as usize; + in_ptr = in_ptr.offset(1); + + let bit5 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit5 as usize; + in_ptr = in_ptr.offset(1); + + let bit6 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit6 as usize; + in_ptr = in_ptr.offset(1); + + let bit7 = u8::from(*in_ptr != 0); + *buf.get_unchecked_mut(buf_idx) = *in_ptr; + buf_idx += bit7 as usize; + in_ptr = in_ptr.offset(1); + + let tag: u8 = bit0 + | (bit1 << 1) + | (bit2 << 2) + | (bit3 << 3) + | (bit4 << 4) + | (bit5 << 5) + | (bit6 << 6) + | (bit7 << 7); + + *buf.get_unchecked_mut(tag_pos) = tag; + + if tag == 0 { + //# An all-zero word is followed by a count of + //# consecutive zero words (not including the first + //# one). + + let mut in_word: *const [u8; 8] = in_ptr as *const [u8; 8]; + let mut limit: *const [u8; 8] = in_end as *const [u8; 8]; + if ptr_sub(limit, in_word) > 255 { + limit = in_word.offset(255); + } + while in_word < limit && *in_word == [0; 8] { + in_word = in_word.offset(1); + } + + *buf.get_unchecked_mut(buf_idx) = + ptr_sub(in_word, in_ptr as *const [u8; 8]) as u8; + buf_idx += 1; + in_ptr = in_word as *const u8; + } else if tag == 0xff { + //# An all-nonzero word is followed by a count of + //# consecutive uncompressed words, followed by the + //# uncompressed words themselves. + + //# Count the number of consecutive words in the input + //# which have no more than a single zero-byte. We look + //# for at least two zeros because that's the point + //# where our compression scheme becomes a net win. + let run_start = in_ptr; + let mut limit = in_end; + if ptr_sub(limit, in_ptr) > 255 * 8 { + limit = in_ptr.offset(255 * 8); + } + + while in_ptr < limit { + let mut c = 0; + + for _ in 0..8 { + c += u8::from(*in_ptr == 0); + in_ptr = in_ptr.offset(1); + } + + if c >= 2 { + //# Un-read the word with multiple zeros, since + //# we'll want to compress that one. + in_ptr = in_ptr.offset(-8); + break; + } + } + + let count: usize = ptr_sub(in_ptr, run_start); + *buf.get_unchecked_mut(buf_idx) = (count / 8) as u8; + buf_idx += 1; + + self.inner.write_all(&buf[..buf_idx])?; + buf_idx = 0; + self.inner + .write_all(slice::from_raw_parts::(run_start, count))?; + } + } + + self.inner.write_all(&buf[..buf_idx])?; + Ok(()) + } + } +} + +/// Writes a packed message to a stream. +/// +/// The only source of errors from this function are `write.write_all()` calls. If you pass in +/// a writer that never returns an error, then this function will never return an error. +#[cfg(feature = "alloc")] +pub fn write_message(write: W, message: &crate::message::Builder) -> Result<()> +where + W: Write, + A: crate::message::Allocator, +{ + let packed_write = PackedWrite { inner: write }; + serialize::write_message(packed_write, message) +} + +#[cfg(feature = "alloc")] +#[cfg(test)] +mod tests { + use alloc::vec::Vec; + + use crate::io::{Read, Write}; + + use quickcheck::{quickcheck, TestResult}; + + use super::read_message; + use crate::message::ReaderOptions; + use crate::serialize::test::write_message_segments; + use crate::serialize_packed::{PackedRead, PackedWrite}; + use crate::ErrorKind; + + #[test] + pub fn premature_eof() { + let input_bytes: &[u8] = &[]; + let mut packed_read = PackedRead { inner: input_bytes }; + + let mut output_bytes: Vec = vec![0; 8]; + assert!(packed_read.read_exact(&mut output_bytes[..]).is_err()); + } + + pub fn check_unpacks_to(packed: &[u8], unpacked: &[u8]) { + let mut packed_read = PackedRead { inner: packed }; + + let mut bytes: Vec = vec![0; unpacked.len()]; + packed_read.read_exact(&mut bytes[..]).unwrap(); + + assert!(packed_read.inner.is_empty()); // nothing left to read + assert_eq!(bytes, unpacked); + } + + pub fn check_packing(unpacked: &[u8], packed: &[u8]) { + // -------- + // write + + let mut bytes: Vec = vec![0; packed.len()]; + { + let mut packed_write = PackedWrite { + inner: &mut bytes[..], + }; + packed_write.write_all(unpacked).unwrap(); + } + + assert_eq!(bytes, packed); + + // -------- + // read + check_unpacks_to(packed, unpacked); + } + + #[test] + pub fn simple_packing() { + check_packing(&[], &[]); + check_packing(&[0; 8], &[0, 0]); + check_packing(&[0, 0, 12, 0, 0, 34, 0, 0], &[0x24, 12, 34]); + check_packing( + &[1, 3, 2, 4, 5, 7, 6, 8], + &[0xff, 1, 3, 2, 4, 5, 7, 6, 8, 0], + ); + check_packing( + &[0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 4, 5, 7, 6, 8], + &[0, 0, 0xff, 1, 3, 2, 4, 5, 7, 6, 8, 0], + ); + check_packing( + &[0, 0, 12, 0, 0, 34, 0, 0, 1, 3, 2, 4, 5, 7, 6, 8], + &[0x24, 12, 34, 0xff, 1, 3, 2, 4, 5, 7, 6, 8, 0], + ); + check_packing( + &[1, 3, 2, 4, 5, 7, 6, 8, 8, 6, 7, 4, 5, 2, 3, 1], + &[0xff, 1, 3, 2, 4, 5, 7, 6, 8, 1, 8, 6, 7, 4, 5, 2, 3, 1], + ); + + check_packing( + &[ + 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, + 5, 6, 7, 8, 0, 2, 4, 0, 9, 0, 5, 1, + ], + &[ + 0xff, 1, 2, 3, 4, 5, 6, 7, 8, 3, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, + 2, 3, 4, 5, 6, 7, 8, 0xd6, 2, 4, 9, 5, 1, + ], + ); + check_packing( + &[ + 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 6, 2, 4, 3, 9, 0, 5, 1, 1, 2, 3, 4, + 5, 6, 7, 8, 0, 2, 4, 0, 9, 0, 5, 1, + ], + &[ + 0xff, 1, 2, 3, 4, 5, 6, 7, 8, 3, 1, 2, 3, 4, 5, 6, 7, 8, 6, 2, 4, 3, 9, 0, 5, 1, 1, + 2, 3, 4, 5, 6, 7, 8, 0xd6, 2, 4, 9, 5, 1, + ], + ); + + check_packing( + &[ + 8, 0, 100, 6, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 1, + ], + &[0xed, 8, 100, 6, 1, 1, 2, 0, 2, 0xd4, 1, 2, 3, 1], + ); + + check_packing(&[0; 16], &[0, 1]); + check_packing( + &[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + &[0, 2], + ); + } + + quickcheck! { + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_round_trip(segments: Vec>) -> TestResult { + use crate::message::ReaderSegments; + if segments.is_empty() { return TestResult::discard(); } + let mut buf: Vec = Vec::new(); + + write_message_segments(&mut PackedWrite { inner: &mut buf }, &segments); + let message = read_message(&mut &buf[..], ReaderOptions::new()).unwrap(); + let result_segments = message.into_segments(); + + TestResult::from_bool(segments.iter().enumerate().all(|(i, segment)| { + crate::Word::words_to_bytes(&segment[..]) == result_segments.get_segment(i as u32).unwrap() + })) + } + + #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck + fn test_unpack(packed: Vec) -> TestResult { + let len = packed.len(); + let mut packed_read = PackedRead { inner: &packed[..] }; + + let mut out_buffer: Vec = vec![0; len * 8]; + + let _ = packed_read.read_exact(&mut out_buffer); + TestResult::from_bool(true) + } + } + + #[test] + fn did_not_end_cleanly_on_a_segment_boundary() { + let packed = &[0xff, 1, 2, 3, 4, 5, 6, 7, 8, 37, 1, 2]; + let mut packed_read = PackedRead { inner: &packed[..] }; + + let mut bytes: Vec = vec![0; 200]; + match packed_read.read_exact(&mut bytes[..]) { + Ok(_) => panic!("should have been an error"), + Err(e) => { + assert_eq!( + e.kind, + ErrorKind::PackedInputDidNotEndCleanlyOnASegmentBoundary, + ); + } + } + } + + #[test] + fn premature_end_of_packed_input() { + fn helper(packed: &[u8]) { + let mut packed_read = PackedRead { inner: packed }; + + let mut bytes: Vec = vec![0; 200]; + match packed_read.read_exact(&mut bytes[..]) { + Ok(_) => panic!("should have been an error"), + Err(e) => { + assert_eq!(e.kind, ErrorKind::PrematureEndOfPackedInput); + } + } + } + + helper(&[0xf0, 1, 2]); + helper(&[0]); + helper(&[0xff, 1, 2, 3, 4, 5, 6, 7, 8]); + + // In this case, the error is only due to the fact that the unpacked data does not + // fill up the given output buffer. + helper(&[1, 1]); + } + + #[test] + fn packed_segment_table() { + let packed_buf = &[0x11, 4, 1, 0, 1, 0, 0]; + + check_unpacks_to( + packed_buf, + &[ + 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ], + ); + + // At one point, this failed due to serialize::read_message() + // reading the segment table only one word at a time. + read_message(&mut &packed_buf[..], Default::default()).unwrap(); + } +} diff --git a/rust/capnp/stringify.rs b/rust/capnp/stringify.rs new file mode 100644 index 000000000000..d11bfbeb7b14 --- /dev/null +++ b/rust/capnp/stringify.rs @@ -0,0 +1,181 @@ +use crate::dynamic_value; +use core::fmt::{self, Formatter}; + +#[derive(Clone, Copy, Debug, Default)] +pub(crate) struct Indent { + /// None means everything gets printed on a single line. + indent: Option, +} + +impl Indent { + fn no_indent() -> Self { + Self { indent: None } + } + + fn enabled() -> Self { + Self { indent: Some(0) } + } + + fn next(self) -> Self { + match self.indent { + None => self, + Some(x) => Self { + indent: Some(x + 1), + }, + } + } + + fn maybe_newline(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> { + match self.indent { + None => Ok(()), + Some(indent) => { + formatter.write_str("\n")?; + for _ in 0..indent { + formatter.write_str(" ")?; + } + Ok(()) + } + } + } + + fn comma(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> { + match self.indent { + None => formatter.write_str(", "), + Some(_) => formatter.write_str(","), + } + } +} + +fn cvt(r: core::result::Result) -> Result { + match r { + Ok(v) => Ok(v), + Err(_) => Err(fmt::Error), + } +} + +pub(crate) fn print( + value: dynamic_value::Reader, + formatter: &mut Formatter, + indent: Indent, +) -> Result<(), fmt::Error> { + match value { + dynamic_value::Reader::Void => formatter.write_str("()"), + dynamic_value::Reader::Bool(b) => formatter.write_fmt(format_args!("{b}")), + dynamic_value::Reader::Int8(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::Int16(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::Int32(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::Int64(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::UInt8(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::UInt16(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::UInt32(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::UInt64(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::Float32(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::Float64(x) => formatter.write_fmt(format_args!("{x}")), + dynamic_value::Reader::Enum(e) => match cvt(e.get_enumerant())? { + Some(enumerant) => { + formatter.write_str(cvt(cvt(enumerant.get_proto().get_name())?.to_str())?) + } + None => formatter.write_fmt(format_args!("{}", e.get_value())), + }, + dynamic_value::Reader::Text(t) => formatter.write_fmt(format_args!("{t:?}")), + dynamic_value::Reader::Data(d) => { + formatter.write_str("0x\"")?; + for b in d { + formatter.write_fmt(format_args!("{:02x}", *b))?; + } + formatter.write_str("\"") + } + dynamic_value::Reader::List(list) => { + if list.is_empty() { + formatter.write_str("[]") + } else { + formatter.write_str("[")?; + let indent2 = indent.next(); + for (idx, value) in list.iter().enumerate() { + indent2.maybe_newline(formatter)?; + print(cvt(value)?, formatter, indent2)?; + if idx + 1 < list.len() as usize { + indent2.comma(formatter)?; + } + } + indent.maybe_newline(formatter)?; + formatter.write_str("]") + } + } + dynamic_value::Reader::Struct(st) => { + let schema = st.get_schema(); + let union_fields = cvt(schema.get_union_fields())?; + let non_union_fields = cvt(schema.get_non_union_fields())?; + if union_fields.len() + non_union_fields.len() == 0 { + return formatter.write_str("()"); + } + formatter.write_str("(")?; + let indent2 = indent.next(); + let mut union_field = match cvt(st.which())? { + None => None, + Some(field) => { + // If it's not the default descriminant, then we always need to print it. + if field.get_proto().get_discriminant_value() != 0 || cvt(st.has(field))? { + Some(field) + } else { + None + } + } + }; + let mut first = true; + for field in non_union_fields { + if let Some(ff) = union_field { + if ff.get_index() < field.get_index() { + // It's time to print the union field. + if first { + first = false + } else { + indent2.comma(formatter)?; + } + indent2.maybe_newline(formatter)?; + formatter.write_str(cvt(cvt(ff.get_proto().get_name())?.to_str())?)?; + formatter.write_str(" = ")?; + print(cvt(st.get(ff))?, formatter, indent2)?; + union_field = None; + } + } + if cvt(st.has(field))? { + if first { + first = false + } else { + indent2.comma(formatter)?; + } + indent2.maybe_newline(formatter)?; + formatter.write_str(cvt(cvt(field.get_proto().get_name())?.to_str())?)?; + formatter.write_str(" = ")?; + print(cvt(st.get(field))?, formatter, indent2)?; + } + } + if let Some(ff) = union_field { + // Union field comes last. + if !first { + indent2.comma(formatter)?; + } + indent2.maybe_newline(formatter)?; + formatter.write_str(cvt(cvt(ff.get_proto().get_name())?.to_str())?)?; + formatter.write_str(" = ")?; + print(cvt(st.get(ff))?, formatter, indent2)?; + } + indent.maybe_newline(formatter)?; + formatter.write_str(")") + } + dynamic_value::Reader::AnyPointer(_) => formatter.write_str(""), + dynamic_value::Reader::Capability(_) => formatter.write_str(""), + } +} + +impl<'a> fmt::Debug for dynamic_value::Reader<'a> { + fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { + let indent = if f.alternate() { + Indent::enabled() + } else { + Indent::no_indent() + }; + print(*self, f, indent) + } +} diff --git a/rust/capnp/struct_list.rs b/rust/capnp/struct_list.rs new file mode 100644 index 000000000000..5c2775ddc1fd --- /dev/null +++ b/rust/capnp/struct_list.rs @@ -0,0 +1,300 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of structs. + +use core::marker::PhantomData; + +use crate::introspect; +use crate::private::layout::{ + InlineComposite, ListBuilder, ListReader, PointerBuilder, PointerReader, +}; +use crate::traits::{FromPointerBuilder, FromPointerReader, HasStructSize, IndexMove, ListIter}; +use crate::Result; + +#[derive(Copy, Clone)] +pub struct Owned +where + T: crate::traits::OwnedStruct, +{ + marker: PhantomData, +} + +impl introspect::Introspect for Owned +where + T: introspect::Introspect + crate::traits::OwnedStruct, +{ + fn introspect() -> introspect::Type { + introspect::Type::list_of(T::introspect()) + } +} + +impl crate::traits::Owned for Owned +where + T: crate::traits::OwnedStruct, +{ + type Reader<'a> = Reader<'a, T>; + type Builder<'a> = Builder<'a, T>; +} + +pub struct Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + marker: PhantomData, + reader: ListReader<'a>, +} + +impl<'a, T> Clone for Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + fn clone(&self) -> Reader<'a, T> { + *self + } +} +impl<'a, T> Copy for Reader<'a, T> where T: crate::traits::OwnedStruct {} + +impl<'a, T> Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, T::Reader<'a>> { + ListIter::new(self, self.len()) + } +} + +impl<'a, T> Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + pub fn reborrow(&self) -> Reader<'_, T> { + Reader { + reader: self.reader, + marker: PhantomData, + } + } +} + +impl<'a, T> FromPointerReader<'a> for Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(InlineComposite, default)?, + marker: PhantomData, + }) + } +} + +impl<'a, T> IndexMove> for Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + fn index_move(&self, index: u32) -> T::Reader<'a> { + self.get(index) + } +} + +impl<'a, T> Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> T::Reader<'a> { + assert!(index < self.len()); + self.reader.get_struct_element(index).into() + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option> { + if index < self.len() { + Some(self.reader.get_struct_element(index).into()) + } else { + None + } + } +} + +impl<'a, T> crate::traits::IntoInternalListReader<'a> for Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + fn into_internal_list_reader(self) -> ListReader<'a> { + self.reader + } +} + +pub struct Builder<'a, T> +where + T: crate::traits::OwnedStruct, +{ + marker: PhantomData, + builder: ListBuilder<'a>, +} + +impl<'a, T> Builder<'a, T> +where + T: crate::traits::OwnedStruct, +{ + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn into_reader(self) -> Reader<'a, T> { + Reader { + marker: PhantomData, + reader: self.builder.into_reader(), + } + } + + /// Sets the list element, with the following limitation based on the fact that structs in a + /// struct list are allocated inline: if the source struct is larger than the target struct + /// (as can happen if it was created with a newer version of the schema), then it will be + /// truncated, losing fields. + pub fn set_with_caveats<'b>(&mut self, index: u32, value: T::Reader<'b>) -> Result<()> + where + T::Reader<'b>: crate::traits::IntoInternalStructReader<'b>, + { + assert!(index < self.len()); + use crate::traits::IntoInternalStructReader; + self.builder + .reborrow() + .get_struct_element(index) + .copy_content_from(&value.into_internal_struct_reader()) + } +} + +impl<'a, T> Builder<'a, T> +where + T: crate::traits::OwnedStruct, +{ + pub fn reborrow(&mut self) -> Builder<'_, T> { + Builder { + builder: self.builder.reborrow(), + marker: PhantomData, + } + } +} + +impl<'a, T> FromPointerBuilder<'a> for Builder<'a, T> +where + T: crate::traits::OwnedStruct, +{ + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a, T> { + Builder { + marker: PhantomData, + builder: builder.init_struct_list(size, T::Builder::STRUCT_SIZE), + } + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + marker: PhantomData, + builder: builder.get_struct_list(T::Builder::STRUCT_SIZE, default)?, + }) + } +} + +impl<'a, T> Builder<'a, T> +where + T: crate::traits::OwnedStruct, +{ + /// Gets the element at position `index`. Panics if `index` is greater than or + /// equal to `len()`. + pub fn get(self, index: u32) -> T::Builder<'a> { + assert!(index < self.len()); + self.builder.get_struct_element(index).into() + } + + /// Gets the element at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option> { + if index < self.len() { + Some(self.builder.get_struct_element(index).into()) + } else { + None + } + } +} + +impl<'a, T> crate::traits::SetPointerBuilder for Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a, T>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize) + } +} + +impl<'a, T> ::core::iter::IntoIterator for Reader<'a, T> +where + T: crate::traits::OwnedStruct, +{ + type Item = T::Reader<'a>; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T: crate::traits::OwnedStruct> From> for crate::dynamic_value::Reader<'a> { + fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( + t.reader, + T::introspect(), + )) + } +} + +impl<'a, T: crate::traits::OwnedStruct> From> for crate::dynamic_value::Builder<'a> { + fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( + t.builder, + T::introspect(), + )) + } +} diff --git a/rust/capnp/text.rs b/rust/capnp/text.rs new file mode 100644 index 000000000000..fa2a72701444 --- /dev/null +++ b/rust/capnp/text.rs @@ -0,0 +1,294 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! UTF-8 encoded text. + +use core::str; + +use crate::Result; + +#[derive(Copy, Clone)] +pub struct Owned(()); + +impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; +} + +impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::TypeVariant::Text.into() + } +} + +/// Wrapper around utf-8 encoded text. +/// This is defined as a tuple struct to allow pattern matching +/// on it via byte literals (for example `text::Reader(b"hello")`). +#[derive(Copy, Clone, PartialEq)] +pub struct Reader<'a>(pub &'a [u8]); + +impl<'a> core::cmp::PartialEq<&'a str> for Reader<'a> { + fn eq(&self, other: &&'a str) -> bool { + self.as_bytes() == other.as_bytes() + } +} + +impl<'a> core::cmp::PartialEq> for &'a str { + fn eq(&self, other: &Reader<'a>) -> bool { + self.as_bytes() == other.as_bytes() + } +} + +impl<'a> core::fmt::Debug for Reader<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self.to_str() { + Ok(s) => write!(f, "{:?}", s), + Err(_) => write!(f, "", self.as_bytes()), + } + } +} + +impl<'a> From<&'a str> for Reader<'a> { + fn from(value: &'a str) -> Self { + Self(value.as_bytes()) + } +} + +impl<'a> From<&'a [u8]> for Reader<'a> { + fn from(value: &'a [u8]) -> Self { + Self(value) + } +} + +impl<'a, const N: usize> From<&'a [u8; N]> for Reader<'a> { + fn from(value: &'a [u8; N]) -> Self { + Self(&value[..]) + } +} + +impl<'a> TryFrom> for &'a str { + type Error = core::str::Utf8Error; + fn try_from(value: Reader<'a>) -> core::result::Result<&'a str, core::str::Utf8Error> { + let Reader(v) = value; + str::from_utf8(v) + } +} + +impl<'a> crate::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &crate::private::layout::PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + reader.get_text(default) + } +} + +impl<'a> Reader<'a> { + /// The string's length, in bytes. + pub fn len(&self) -> usize { + self.as_bytes().len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn as_bytes(self) -> &'a [u8] { + let Self(d) = self; + d + } + + /// Converts to a `str`, returning a error if the data contains invalid utf-8. + pub fn to_str(self) -> core::result::Result<&'a str, core::str::Utf8Error> { + let Self(s) = self; + str::from_utf8(s) + } + + #[cfg(feature = "alloc")] + /// Converts to a `String`, returning a error if the data contains invalid utf-8. + pub fn to_string(self) -> core::result::Result { + Ok(self.to_str()?.into()) + } +} + +pub struct Builder<'a> { + /// Does not include the trailing null byte. + bytes: &'a mut [u8], + + /// Position at which `push_ascii()` and `push_str()` will write to. + pos: usize, +} + +impl<'a> core::cmp::PartialEq for Builder<'a> { + fn eq(&self, other: &Self) -> bool { + self.bytes == other.bytes + } +} + +impl<'a> core::cmp::PartialEq<&'a str> for Builder<'a> { + fn eq(&self, other: &&'a str) -> bool { + self.bytes == other.as_bytes() + } +} + +impl<'a> core::cmp::PartialEq> for &'a str { + fn eq(&self, other: &Builder<'a>) -> bool { + self.as_bytes() == other.bytes + } +} + +impl<'a> Builder<'a> { + pub fn new(bytes: &mut [u8]) -> Builder<'_> { + Builder { bytes, pos: 0 } + } + + pub fn with_pos(bytes: &mut [u8], pos: usize) -> Builder<'_> { + Builder { bytes, pos } + } + + /// The string's length, in bytes. + pub fn len(&self) -> usize { + self.bytes.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn as_bytes(self) -> &'a [u8] { + self.bytes + } + + /// Converts to a `str`, returning a error if the data contains invalid utf-8. + pub fn to_str(self) -> core::result::Result<&'a str, core::str::Utf8Error> { + str::from_utf8(self.bytes) + } + + #[cfg(feature = "alloc")] + /// Converts to a `String`, returning a error if the data contains invalid utf-8. + pub fn to_string(self) -> core::result::Result { + Ok(self.to_str()?.into()) + } + + pub fn as_bytes_mut(self) -> &'a mut [u8] { + &mut self.bytes[..] + } + + /// Writes a single ascii character at position `pos` and increments `pos`. + pub fn push_ascii(&mut self, ascii: u8) { + assert!(ascii < 128); + self.bytes[self.pos] = ascii; + self.pos += 1; + } + + /// Writes a string at position `pos` and increases `pos` a corresponding amount. + pub fn push_str(&mut self, string: &str) { + let bytes = string.as_bytes(); + self.bytes[self.pos..(self.pos + bytes.len())].copy_from_slice(bytes); + self.pos += bytes.len(); + } + + /// Zeroes all data and resets `pos`. + pub fn clear(&mut self) { + for b in &mut self.bytes[..self.pos] { + *b = 0; + } + self.pos = 0; + } + + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + bytes: self.bytes, + pos: self.pos, + } + } + + pub fn into_reader(self) -> Reader<'a> { + Reader(self.bytes) + } + + pub fn reborrow_as_reader(&self) -> Reader<'_> { + Reader(self.bytes) + } +} + +impl<'a> core::fmt::Debug for Builder<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self.reborrow_as_reader().to_str() { + Ok(s) => write!(f, "{:?}", s), + Err(_) => write!(f, ""), + } + } +} + +impl<'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, size: u32) -> Builder<'a> { + builder.init_text(size) + } + fn get_from_pointer( + builder: crate::private::layout::PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + builder.get_text(default) + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + _canonicalize: bool, + ) -> Result<()> { + pointer.set_text(value); + Ok(()) + } +} + +// Extra impl to make any_pointer::Builder::set_as() and similar methods work +// more smoothly. +impl<'a> crate::traits::SetPointerBuilder for &'a str { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: &'a str, + _canonicalize: bool, + ) -> Result<()> { + pointer.set_text(value.into()); + Ok(()) + } +} + +impl<'a> From> for crate::dynamic_value::Reader<'a> { + fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::Text(t) + } +} + +impl<'a> From<&'a str> for crate::dynamic_value::Reader<'a> { + fn from(t: &'a str) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::Text(t.into()) + } +} + +impl<'a> From> for crate::dynamic_value::Builder<'a> { + fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::Text(t) + } +} diff --git a/rust/capnp/text_list.rs b/rust/capnp/text_list.rs new file mode 100644 index 000000000000..72cbd2647ba9 --- /dev/null +++ b/rust/capnp/text_list.rs @@ -0,0 +1,216 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +//! List of strings containing UTF-8 encoded text. + +use crate::private::layout::{ListBuilder, ListReader, Pointer, PointerBuilder, PointerReader}; +use crate::traits::{FromPointerBuilder, FromPointerReader, IndexMove, ListIter}; +use crate::Result; + +#[derive(Copy, Clone)] +pub struct Owned; + +impl crate::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; +} + +impl crate::introspect::Introspect for Owned { + fn introspect() -> crate::introspect::Type { + crate::introspect::Type::list_of(crate::introspect::TypeVariant::Text.into()) + } +} + +#[derive(Clone, Copy)] +pub struct Reader<'a> { + reader: ListReader<'a>, +} + +impl<'a> Reader<'a> { + pub fn new<'b>(reader: ListReader<'b>) -> Reader<'b> { + Reader::<'b> { reader } + } + + pub fn len(&self) -> u32 { + self.reader.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn iter(self) -> ListIter, Result>> { + let l = self.len(); + ListIter::new(self, l) + } +} + +impl<'a> FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Reader { + reader: reader.get_list(Pointer, default)?, + }) + } +} + +impl<'a> IndexMove>> for Reader<'a> { + fn index_move(&self, index: u32) -> Result> { + self.get(index) + } +} + +impl<'a> Reader<'a> { + /// Gets the `text::Reader` at position `index`. Panics if `index` is + /// greater than or equal to `len()`. + pub fn get(self, index: u32) -> Result> { + assert!(index < self.len()); + self.reader.get_pointer_element(index).get_text(None) + } + + /// Gets the `text::Reader` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option>> { + if index < self.len() { + Some(self.reader.get_pointer_element(index).get_text(None)) + } else { + None + } + } +} + +impl<'a> crate::traits::IntoInternalListReader<'a> for Reader<'a> { + fn into_internal_list_reader(self) -> ListReader<'a> { + self.reader + } +} + +pub struct Builder<'a> { + builder: ListBuilder<'a>, +} + +impl<'a> Builder<'a> { + pub fn new(builder: ListBuilder<'a>) -> Builder<'a> { + Builder { builder } + } + + pub fn len(&self) -> u32 { + self.builder.len() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn set(&mut self, index: u32, value: crate::text::Reader) { + assert!(index < self.len()); + self.builder + .reborrow() + .get_pointer_element(index) + .set_text(value); + } + + pub fn into_reader(self) -> Reader<'a> { + Reader { + reader: self.builder.into_reader(), + } + } + + pub fn reborrow<'b>(&'b mut self) -> Builder<'b> { + Builder::<'b> { + builder: self.builder.reborrow(), + } + } +} + +impl<'a> FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: PointerBuilder<'a>, size: u32) -> Builder<'a> { + Builder { + builder: builder.init_list(Pointer, size), + } + } + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result> { + Ok(Builder { + builder: builder.get_list(Pointer, default)?, + }) + } +} + +impl<'a> Builder<'a> { + /// Gets the `text::Builder` at position `index`. Panics if `index` is + /// greater than or equal to `len()`. + pub fn get(self, index: u32) -> Result> { + assert!(index < self.len()); + self.builder.get_pointer_element(index).get_text(None) + } + + /// Gets the `text::Builder` at position `index`. Returns `None` if `index` + /// is greater than or equal to `len()`. + pub fn try_get(self, index: u32) -> Option>> { + if index < self.len() { + Some(self.builder.get_pointer_element(index).get_text(None)) + } else { + None + } + } +} + +impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder<'b>( + mut pointer: crate::private::layout::PointerBuilder<'b>, + value: Reader<'a>, + canonicalize: bool, + ) -> Result<()> { + pointer.set_list(&value.reader, canonicalize) + } +} + +impl<'a> ::core::iter::IntoIterator for Reader<'a> { + type Item = Result>; + type IntoIter = ListIter, Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a> From> for crate::dynamic_value::Reader<'a> { + fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { + crate::dynamic_value::Reader::List(crate::dynamic_list::Reader { + reader: t.reader, + element_type: crate::introspect::TypeVariant::Text.into(), + }) + } +} + +impl<'a> From> for crate::dynamic_value::Builder<'a> { + fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { + crate::dynamic_value::Builder::List(crate::dynamic_list::Builder { + builder: t.builder, + element_type: crate::introspect::TypeVariant::Text.into(), + }) + } +} diff --git a/rust/capnp/traits.rs b/rust/capnp/traits.rs new file mode 100644 index 000000000000..39e050ab4abf --- /dev/null +++ b/rust/capnp/traits.rs @@ -0,0 +1,233 @@ +// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +use crate::private::layout::CapTable; +use crate::private::layout::{ + ListReader, PointerBuilder, PointerReader, StructBuilder, StructReader, StructSize, +}; +use crate::Result; + +use core::marker::PhantomData; + +pub trait HasStructSize { + const STRUCT_SIZE: StructSize; +} + +/// Trait for all types that can be converted to a low-level `StructReader`. +pub trait IntoInternalStructReader<'a> { + fn into_internal_struct_reader(self) -> StructReader<'a>; +} + +/// Trait for all types that can be converted to a low-level `ListReader`. +pub trait IntoInternalListReader<'a> { + fn into_internal_list_reader(self) -> ListReader<'a>; +} + +pub trait FromPointerReader<'a>: Sized { + fn get_from_pointer( + reader: &PointerReader<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result; +} + +/// A trait to encode relationships between readers and builders. +/// +/// If `Foo` is a Cap'n Proto struct and `Bar` is a Rust-native struct, then +/// `foo::Reader<'a>` is to `foo::Owned` as `&'a Bar` is to `Bar`, and +/// `foo::Builder<'a>` is to `foo::Owned` as `&'a mut Bar` is to `Bar`. +/// The relationship is formalized by an `impl capnp::traits::Owned for foo::Owned`. +/// Because Cap'n Proto struct layout differs from Rust struct layout, a `foo::Owned` value +/// cannot be used for anything interesting on its own; the `foo::Owned` type is useful +/// nonetheless as a type parameter, e.g. for a generic container that owns a Cap'n Proto +/// message of type `T: capnp::traits::Owned`. +pub trait Owned: crate::introspect::Introspect { + type Reader<'a>: FromPointerReader<'a> + SetPointerBuilder; + type Builder<'a>: FromPointerBuilder<'a>; +} + +pub trait OwnedStruct: crate::introspect::Introspect { + type Reader<'a>: From> + SetPointerBuilder + IntoInternalStructReader<'a>; + type Builder<'a>: From> + HasStructSize; +} + +pub trait Pipelined { + type Pipeline; +} + +pub trait FromPointerBuilder<'a>: Sized { + fn init_pointer(builder: PointerBuilder<'a>, length: u32) -> Self; + fn get_from_pointer( + builder: PointerBuilder<'a>, + default: Option<&'a [crate::Word]>, + ) -> Result; +} + +pub trait SetPointerBuilder { + fn set_pointer_builder( + builder: PointerBuilder<'_>, + from: Self, + canonicalize: bool, + ) -> Result<()>; +} + +pub trait Imbue<'a> { + fn imbue(&mut self, caps: &'a CapTable); +} + +pub trait ImbueMut<'a> { + fn imbue_mut(&mut self, caps: &'a mut CapTable); +} + +pub trait HasTypeId { + const TYPE_ID: u64; +} + +pub trait IndexMove { + fn index_move(&self, index: I) -> T; +} + +pub struct ListIter { + marker: PhantomData, + list: T, + index: u32, + size: u32, +} + +impl ListIter { + pub fn new(list: T, size: u32) -> Self { + Self { + list, + index: 0, + size, + marker: PhantomData, + } + } +} + +impl> ::core::iter::Iterator for ListIter { + type Item = U; + fn next(&mut self) -> ::core::option::Option { + if self.index < self.size { + let result = self.list.index_move(self.index); + self.index += 1; + Some(result) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.size as usize, Some(self.size as usize)) + } + + fn nth(&mut self, p: usize) -> Option { + if self.index + (p as u32) < self.size { + self.index += p as u32; + let result = self.list.index_move(self.index); + self.index += 1; + Some(result) + } else { + self.index = self.size; + None + } + } +} + +impl> ::core::iter::ExactSizeIterator for ListIter { + fn len(&self) -> usize { + self.size as usize + } +} + +impl> ::core::iter::DoubleEndedIterator for ListIter { + fn next_back(&mut self) -> ::core::option::Option { + if self.size > self.index { + self.size -= 1; + Some(self.list.index_move(self.size)) + } else { + None + } + } +} + +pub struct ShortListIter { + marker: PhantomData, + list: T, + index: u16, + size: u16, +} + +impl ShortListIter { + pub fn new(list: T, size: u16) -> Self { + Self { + list, + index: 0, + size, + marker: PhantomData, + } + } +} + +impl> ::core::iter::Iterator for ShortListIter { + type Item = U; + fn next(&mut self) -> ::core::option::Option { + if self.index < self.size { + let result = self.list.index_move(self.index); + self.index += 1; + Some(result) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.size as usize, Some(self.size as usize)) + } + + fn nth(&mut self, p: usize) -> Option { + if self.index + (p as u16) < self.size { + self.index += p as u16; + let result = self.list.index_move(self.index); + self.index += 1; + Some(result) + } else { + self.index = self.size; + None + } + } +} + +impl> ::core::iter::ExactSizeIterator for ShortListIter { + fn len(&self) -> usize { + self.size as usize + } +} + +impl> ::core::iter::DoubleEndedIterator for ShortListIter { + fn next_back(&mut self) -> ::core::option::Option { + if self.size > self.index { + self.size -= 1; + Some(self.list.index_move(self.size)) + } else { + None + } + } +} From patchwork Thu May 16 19:03:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666491 Received: from aer-iport-4.cisco.com (aer-iport-4.cisco.com [173.38.203.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9EAE715B96B; Thu, 16 May 2024 19:05:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886321; cv=none; b=cC9Hs95gM3AF42H/U/sNWhDWI3Vt4Viym0kK+kean4DXcpvDuqzhOLH0Mb8zyU2pCZH5+X8fSPYZI7Yvfl8cqYpYUWlA4iy6ajc0VstF1/X2LcLBnG1nk7XqXzdFMecbQ7eoX4G31/78SuMa+y2K9dyVfGy8p5E3LDHvOKOcxpI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886321; c=relaxed/simple; bh=dCufPo0k+5EGqgazK+H69P+Cx6l+Va1rtovlf9VP2VY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=VAzjtnnSFXz3pAuv+Baww75bySqO3bhON6sC2h5lovxeDxch/UUzx0fbKLBYafVHpl1eWY39FhOZTte3uo7aIozlY+r1wu8aGt/si9BLNWwvRt7XtVsgpRuF8C9PwBGSQRYUmp9xNJonDO0tj8dHvdngmoz0s6VT75/t1BooHcA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=cN56MSaO; arc=none smtp.client-ip=173.38.203.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="cN56MSaO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=14802; q=dns/txt; s=iport; t=1715886318; x=1717095918; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WikPN1aozAODGlwU5sGnmfF5s8efLsy9tywRfkBTanI=; b=cN56MSaOQjtZGTeikn4Psl2GJ7clDB43R0ktEU4Cux+WG/1gf1UJ5+GA jju0iDuHHxK1vpa9eDFJbxIyP508VShh2liyviTgeoiMhpfVt8Jh+h/Be Ea4yehfFqgCCpKIleeStRJlVaPjlN5WZ9M40rMCJAiLlVXzcjcq0FVuVU I=; X-CSE-ConnectionGUID: t8hH8awMSuy50LezSOW19g== X-CSE-MsgGUID: Tkobr50fQ8SnlWtJPnD7tA== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12379872" Received: from aer-iport-nat.cisco.com (HELO aer-core-12.cisco.com) ([173.38.203.22]) by aer-iport-4.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:10 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-12.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ495v100681 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:09 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 07/22] rust: capnp: add SPDX License Identifiers Date: Thu, 16 May 2024 22:03:30 +0300 Message-Id: <20240516190345.957477-8-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-12.cisco.com Add the SPDX license identifiers, since the initial patch added the upstream sources with no modifications whatsoever. Signed-off-by: Ariel Miculas --- rust/capnp/any_pointer.rs | 2 ++ rust/capnp/any_pointer_list.rs | 2 ++ rust/capnp/capability.rs | 2 ++ rust/capnp/capability_list.rs | 2 ++ rust/capnp/constant.rs | 2 ++ rust/capnp/data.rs | 2 ++ rust/capnp/data_list.rs | 2 ++ rust/capnp/dynamic_list.rs | 2 ++ rust/capnp/dynamic_struct.rs | 2 ++ rust/capnp/dynamic_value.rs | 2 ++ rust/capnp/enum_list.rs | 2 ++ rust/capnp/introspect.rs | 2 ++ rust/capnp/io.rs | 2 ++ rust/capnp/lib.rs | 2 ++ rust/capnp/list_list.rs | 2 ++ rust/capnp/message.rs | 2 ++ rust/capnp/primitive_list.rs | 2 ++ rust/capnp/private/arena.rs | 2 ++ rust/capnp/private/capability.rs | 2 ++ rust/capnp/private/layout.rs | 2 ++ rust/capnp/private/layout_test.rs | 2 ++ rust/capnp/private/mask.rs | 2 ++ rust/capnp/private/mod.rs | 2 ++ rust/capnp/private/primitive.rs | 2 ++ rust/capnp/private/read_limiter.rs | 2 ++ rust/capnp/private/units.rs | 2 ++ rust/capnp/private/zero.rs | 2 ++ rust/capnp/raw.rs | 2 ++ rust/capnp/schema.rs | 2 ++ rust/capnp/schema_capnp.rs | 2 ++ rust/capnp/serialize.rs | 2 ++ rust/capnp/serialize/no_alloc_buffer_segments.rs | 2 ++ rust/capnp/serialize_packed.rs | 2 ++ rust/capnp/stringify.rs | 2 ++ rust/capnp/struct_list.rs | 2 ++ rust/capnp/text.rs | 2 ++ rust/capnp/text_list.rs | 2 ++ rust/capnp/traits.rs | 2 ++ 38 files changed, 76 insertions(+) diff --git a/rust/capnp/any_pointer.rs b/rust/capnp/any_pointer.rs index c49216cd031e..83ae07a20a09 100644 --- a/rust/capnp/any_pointer.rs +++ b/rust/capnp/any_pointer.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/any_pointer_list.rs b/rust/capnp/any_pointer_list.rs index 1c4e9e40c879..f7f4fae5678c 100644 --- a/rust/capnp/any_pointer_list.rs +++ b/rust/capnp/any_pointer_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2018 the capnproto-rust contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/rust/capnp/capability.rs b/rust/capnp/capability.rs index 7cff20bbbcb9..fbe778791c38 100644 --- a/rust/capnp/capability.rs +++ b/rust/capnp/capability.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/capability_list.rs b/rust/capnp/capability_list.rs index 083794e073d1..b139d566a58d 100644 --- a/rust/capnp/capability_list.rs +++ b/rust/capnp/capability_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2017 David Renshaw and contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/rust/capnp/constant.rs b/rust/capnp/constant.rs index fdd1edf487ff..9f174366d89d 100644 --- a/rust/capnp/constant.rs +++ b/rust/capnp/constant.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/rust/capnp/data.rs b/rust/capnp/data.rs index 89e0c6c19ea4..d777f1d626b0 100644 --- a/rust/capnp/data.rs +++ b/rust/capnp/data.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/data_list.rs b/rust/capnp/data_list.rs index f5fee2575fd2..7771ea4bb04d 100644 --- a/rust/capnp/data_list.rs +++ b/rust/capnp/data_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/dynamic_list.rs b/rust/capnp/dynamic_list.rs index f2c93e1cbe16..0b60674cdeab 100644 --- a/rust/capnp/dynamic_list.rs +++ b/rust/capnp/dynamic_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + //! Dynamically-typed lists. use crate::dynamic_value; diff --git a/rust/capnp/dynamic_struct.rs b/rust/capnp/dynamic_struct.rs index d0244fc29f40..9da5a1e5df33 100644 --- a/rust/capnp/dynamic_struct.rs +++ b/rust/capnp/dynamic_struct.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + //! Dynamically-typed structs. use crate::introspect::TypeVariant; diff --git a/rust/capnp/dynamic_value.rs b/rust/capnp/dynamic_value.rs index 83646e26de31..aaca4d82453f 100644 --- a/rust/capnp/dynamic_value.rs +++ b/rust/capnp/dynamic_value.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + //! Dynamically typed values. use crate::introspect::{self, TypeVariant}; diff --git a/rust/capnp/enum_list.rs b/rust/capnp/enum_list.rs index 8fa713029250..0192732fe16b 100644 --- a/rust/capnp/enum_list.rs +++ b/rust/capnp/enum_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/introspect.rs b/rust/capnp/introspect.rs index d994b180c93a..a3494935b4d5 100644 --- a/rust/capnp/introspect.rs +++ b/rust/capnp/introspect.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + //! Traits and types to support run-time type introspection, i.e. reflection. use crate::private::layout::ElementSize; diff --git a/rust/capnp/io.rs b/rust/capnp/io.rs index 59d149b37c26..82c429f8c263 100644 --- a/rust/capnp/io.rs +++ b/rust/capnp/io.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + //! Custom I/O traits that roughly mirror `std::io::{Read, BufRead, Write}`. //! This extra layer of indirection enables support of no-std environments. diff --git a/rust/capnp/lib.rs b/rust/capnp/lib.rs index daafc23c19d5..d3aa0f9f3451 100644 --- a/rust/capnp/lib.rs +++ b/rust/capnp/lib.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/list_list.rs b/rust/capnp/list_list.rs index 7c31560958d3..ec7e830df7e1 100644 --- a/rust/capnp/list_list.rs +++ b/rust/capnp/list_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/message.rs b/rust/capnp/message.rs index fe40e0a7c313..595f6975c489 100644 --- a/rust/capnp/message.rs +++ b/rust/capnp/message.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/primitive_list.rs b/rust/capnp/primitive_list.rs index 4ea31a7b50eb..a761320788b5 100644 --- a/rust/capnp/primitive_list.rs +++ b/rust/capnp/primitive_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/arena.rs b/rust/capnp/private/arena.rs index 46626c1f0ce3..40c539d72142 100644 --- a/rust/capnp/private/arena.rs +++ b/rust/capnp/private/arena.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/rust/capnp/private/capability.rs b/rust/capnp/private/capability.rs index ba725fb60535..522d0b1b0418 100644 --- a/rust/capnp/private/capability.rs +++ b/rust/capnp/private/capability.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/layout.rs b/rust/capnp/private/layout.rs index 02ecb6e7bfb5..dbfe97235cd9 100644 --- a/rust/capnp/private/layout.rs +++ b/rust/capnp/private/layout.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/layout_test.rs b/rust/capnp/private/layout_test.rs index 8715e9edab43..fb5a8de9bb44 100644 --- a/rust/capnp/private/layout_test.rs +++ b/rust/capnp/private/layout_test.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/mask.rs b/rust/capnp/private/mask.rs index dfa211521ca7..70937b802bf6 100644 --- a/rust/capnp/private/mask.rs +++ b/rust/capnp/private/mask.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/mod.rs b/rust/capnp/private/mod.rs index 1e6bcdab6d6e..2126235199fe 100644 --- a/rust/capnp/private/mod.rs +++ b/rust/capnp/private/mod.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/primitive.rs b/rust/capnp/private/primitive.rs index 00e41ce40f08..f70f3a7486f3 100644 --- a/rust/capnp/private/primitive.rs +++ b/rust/capnp/private/primitive.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + pub trait Primitive { type Raw; diff --git a/rust/capnp/private/read_limiter.rs b/rust/capnp/private/read_limiter.rs index 0bb6a7a8415c..f4f0cf348af1 100644 --- a/rust/capnp/private/read_limiter.rs +++ b/rust/capnp/private/read_limiter.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/units.rs b/rust/capnp/private/units.rs index 90fbf663f777..37782edeef56 100644 --- a/rust/capnp/private/units.rs +++ b/rust/capnp/private/units.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/private/zero.rs b/rust/capnp/private/zero.rs index 00769cfebafc..12e4a723105a 100644 --- a/rust/capnp/private/zero.rs +++ b/rust/capnp/private/zero.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/raw.rs b/rust/capnp/raw.rs index 5883b1207be9..3127b6adc0fc 100644 --- a/rust/capnp/raw.rs +++ b/rust/capnp/raw.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2018 the capnproto-rust contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/rust/capnp/schema.rs b/rust/capnp/schema.rs index 4120868f4051..b7677056cc10 100644 --- a/rust/capnp/schema.rs +++ b/rust/capnp/schema.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + //! Convenience wrappers of the datatypes defined in schema.capnp. use crate::dynamic_value; diff --git a/rust/capnp/schema_capnp.rs b/rust/capnp/schema_capnp.rs index 4f92ee288821..820a1187bf59 100644 --- a/rust/capnp/schema_capnp.rs +++ b/rust/capnp/schema_capnp.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. // DO NOT EDIT. // source: schema.capnp diff --git a/rust/capnp/serialize.rs b/rust/capnp/serialize.rs index ad9e130e5ed7..025bcd45ee61 100644 --- a/rust/capnp/serialize.rs +++ b/rust/capnp/serialize.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/serialize/no_alloc_buffer_segments.rs b/rust/capnp/serialize/no_alloc_buffer_segments.rs index d3837738d702..de902a0ee4d4 100644 --- a/rust/capnp/serialize/no_alloc_buffer_segments.rs +++ b/rust/capnp/serialize/no_alloc_buffer_segments.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + use core::convert::TryInto; use crate::message::ReaderOptions; diff --git a/rust/capnp/serialize_packed.rs b/rust/capnp/serialize_packed.rs index 286a36950981..63ed7264848e 100644 --- a/rust/capnp/serialize_packed.rs +++ b/rust/capnp/serialize_packed.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/stringify.rs b/rust/capnp/stringify.rs index d11bfbeb7b14..426025fea0e8 100644 --- a/rust/capnp/stringify.rs +++ b/rust/capnp/stringify.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + use crate::dynamic_value; use core::fmt::{self, Formatter}; diff --git a/rust/capnp/struct_list.rs b/rust/capnp/struct_list.rs index 5c2775ddc1fd..7133e69560bc 100644 --- a/rust/capnp/struct_list.rs +++ b/rust/capnp/struct_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/text.rs b/rust/capnp/text.rs index fa2a72701444..406ddb5ba8ac 100644 --- a/rust/capnp/text.rs +++ b/rust/capnp/text.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/text_list.rs b/rust/capnp/text_list.rs index 72cbd2647ba9..222521a6741e 100644 --- a/rust/capnp/text_list.rs +++ b/rust/capnp/text_list.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // diff --git a/rust/capnp/traits.rs b/rust/capnp/traits.rs index 39e050ab4abf..e12c38346d56 100644 --- a/rust/capnp/traits.rs +++ b/rust/capnp/traits.rs @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + // Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // From patchwork Thu May 16 19:03:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666489 Received: from aer-iport-5.cisco.com (aer-iport-5.cisco.com [173.38.203.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E57B915B0F2; Thu, 16 May 2024 19:05:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.67 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886317; cv=none; b=snrNU6CIiP/ytC4MvhBsT+a8YNBhYa7rYhw4ZUBopv1ovI3ZbsVM5cvG8xGwCpiZIGhkIhjqtlpzJC7xswXIPxYff/22+AsYTGp4WdVZabyMOeBPcmy8lLI9bkzLdP6M7USHFHnLL10G17UZnMW7GDJjGq47IdOxpDfdF04wtf8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886317; c=relaxed/simple; bh=Un26QMeCw3vpFkkSsLB4y9SsB1DGWGmNJr9wdtwpPVQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UjL9jJK2JjmR9f4kgAgk6w98sd5TckV48N1siAXxD0IhfuZArksXv83NmAup2Q0rtUJQvxEy+8i9mW66fmEA1Xqv7FYtczQr3c3/QdHwHlHbGIGRpbywmmBMXDTxy+2G/umYDgPZFRC3sHpUDmEFEXUozdzIYfYzO8ATl8VEaNs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=mYcMPAKw; arc=none smtp.client-ip=173.38.203.67 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="mYcMPAKw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=1219; q=dns/txt; s=iport; t=1715886315; x=1717095915; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SlAafPKrZ/klEmNYXl2TJjHIbtqsyFs7FtP+G4kmq8Y=; b=mYcMPAKwwJlGcEQNSMU6KA5ZwDJmJ2lq2+s45UilNjBjLK77MxSL805i 4KueADQpyDr59etEGd9iDD2kR4dfsxiZFY7fgykQRmgFU8E8cbewcRkM0 d8r0TVreUkI+5Ovlz0KdvcabYZt9Lt3P/8IukJ/4zFsL9LDaLUvhX9UF/ A=; X-CSE-ConnectionGUID: S1hSJNSaTp6Q9UX5slpTsA== X-CSE-MsgGUID: R3iLQmPOQvSxEe8c+vp2gw== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="9839850" Received: from aer-iport-nat.cisco.com (HELO aer-core-4.cisco.com) ([173.38.203.22]) by aer-iport-5.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:11 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-4.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4AsO006132 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:11 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 08/22] rust: capnp: return an error when trying to display floating point values Date: Thu, 16 May 2024 22:03:31 +0300 Message-Id: <20240516190345.957477-9-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-4.cisco.com The kernel doesn't support floating point values, so return an error when the kernel feature is enabled. Signed-off-by: Ariel Miculas --- rust/capnp/stringify.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/capnp/stringify.rs b/rust/capnp/stringify.rs index 426025fea0e8..f93e3521ce0b 100644 --- a/rust/capnp/stringify.rs +++ b/rust/capnp/stringify.rs @@ -71,8 +71,12 @@ pub(crate) fn print( dynamic_value::Reader::UInt16(x) => formatter.write_fmt(format_args!("{x}")), dynamic_value::Reader::UInt32(x) => formatter.write_fmt(format_args!("{x}")), dynamic_value::Reader::UInt64(x) => formatter.write_fmt(format_args!("{x}")), + #[cfg(not(feature = "kernel"))] dynamic_value::Reader::Float32(x) => formatter.write_fmt(format_args!("{x}")), + #[cfg(not(feature = "kernel"))] dynamic_value::Reader::Float64(x) => formatter.write_fmt(format_args!("{x}")), + #[cfg(feature = "kernel")] + dynamic_value::Reader::Float32(_) | dynamic_value::Reader::Float64(_) => Err(fmt::Error), dynamic_value::Reader::Enum(e) => match cvt(e.get_enumerant())? { Some(enumerant) => { formatter.write_str(cvt(cvt(enumerant.get_proto().get_name())?.to_str())?) From patchwork Thu May 16 19:03:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666492 Received: from aer-iport-6.cisco.com (aer-iport-6.cisco.com [173.38.203.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9990415AAD3; Thu, 16 May 2024 19:05:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.68 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886325; cv=none; b=Nk48Puo7SbYbLesfe2PUKDLbWpjpZKnjPDOEYu+KPvdhN9j78XWoOxQ79e5eiegXag68Zw2NmXvRXX5Tif6nnY429eIWpqdobOTzUsPVWpr61/PTt9AfLmRop/oIYyz4Em5koosQXqb50mH3SIFVcjTWwyB+IwKhhwhWffLyVJw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886325; c=relaxed/simple; bh=yLauolBXrHXd3uryAiWbWkiottax/Pz7IPpXWXka154=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qBLMgJQkv58dPJPjQdzMHrDcfKTDlkCTmVqtOYlLHX3rouJRD3GAs55b3yw376ov5zos1kNa2o3LTd9eRGyeOPeFgY9pB4cwoxZ4ITnqsotxEsoerwXahVNIJuCLpqWtctVCGFvL0yNr0UXtl1+PBfmUpoaTx+LkGk+jbziOwV4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=ZQC7mWQM; arc=none smtp.client-ip=173.38.203.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="ZQC7mWQM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=2754; q=dns/txt; s=iport; t=1715886324; x=1717095924; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BZDiRqz2la8YaFUbhmJvVA89OpRYWxJrlsQsevwHzgg=; b=ZQC7mWQMUH7WnQVfHQrKY7vHlKXqXsFMKgUGACxdNEwsyUWMxy5eGehC 5qmFvdER4foXkkfao0DW+ziOljtFro2LtPJFapnYemR5xft0Nu47pssFn FDBUwOj4aysX162xdLRAyzB+P02IIrvMncJizQinc2avfEX5zrczLEdQj w=; X-CSE-ConnectionGUID: ZWTzMNIzQI+Z/UGXhKyUVQ== X-CSE-MsgGUID: Dqvu3BUkRxquSWbt47rBBw== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="10016312" Received: from aer-iport-nat.cisco.com (HELO aer-core-6.cisco.com) ([173.38.203.22]) by aer-iport-6.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:12 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-6.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4Bpp006168 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:12 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 09/22] rust: Kbuild: enable `capnp` Date: Thu, 16 May 2024 22:03:32 +0300 Message-Id: <20240516190345.957477-10-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-6.cisco.com With all the new files in place for capnp, this patch adds support for it in the build system. Signed-off-by: Ariel Miculas --- rust/Makefile | 23 ++++++++++++++++++++--- scripts/Makefile.build | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/rust/Makefile b/rust/Makefile index fef8e38fbebd..f088ff4bdd34 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -15,7 +15,7 @@ always-$(CONFIG_RUST) += libmacros.so no-clean-files += libmacros.so always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs -obj-$(CONFIG_RUST) += alloc.o bindings.o hex.o kernel.o +obj-$(CONFIG_RUST) += alloc.o bindings.o hex.o capnp.o kernel.o always-$(CONFIG_RUST) += exports_alloc_generated.h exports_bindings_generated.h \ exports_kernel_generated.h @@ -74,6 +74,16 @@ hex-flags := \ --edition=2018 \ -Amissing_docs +capnp-skip_flags := \ + -Drust_2018_idioms \ + -Dunsafe_op_in_unsafe_fn \ + -Dunreachable_pub + +capnp-flags := \ + -Amissing_docs \ + --cfg 'feature="kernel"' \ + --cfg 'feature="sync_reader"' + quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< cmd_rustdoc = \ OBJTREE=$(abspath $(objtree)) \ @@ -470,11 +480,18 @@ $(obj)/hex.o: private rustc_target_flags = $(hex-flags) $(obj)/hex.o: $(src)/hex/lib.rs $(obj)/compiler_builtins.o FORCE $(call if_changed_dep,rustc_library) +$(obj)/canpproto.o: private skip_clippy = 1 +$(obj)/capnp.o: private skip_flags = $(capnp-skip_flags) +$(obj)/capnp.o: private rustc_target_flags = $(capnp-flags) +$(obj)/capnp.o: $(src)/capnp/lib.rs $(obj)/compiler_builtins.o FORCE + $(call if_changed_dep,rustc_library) + $(obj)/kernel.o: private rustc_target_flags = --extern alloc \ --extern build_error --extern macros --extern bindings --extern uapi \ - --extern hex + --extern hex --extern capnp $(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \ - $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o $(obj)/hex.o FORCE + $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o $(obj)/hex.o \ + $(obj)/capnp.o FORCE $(call if_changed_dep,rustc_library) endif # CONFIG_RUST diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 2e9a64224c51..8a500593ea05 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -273,7 +273,7 @@ rust_common_cmd = \ -Zallow-features=$(rust_allowed_features) \ -Zcrate-attr=no_std \ -Zcrate-attr='feature($(rust_allowed_features))' \ - --extern alloc --extern kernel --extern hex \ + --extern alloc --extern kernel --extern hex --extern capnp \ --crate-type rlib -L $(objtree)/rust/ \ --crate-name $(basename $(notdir $@)) \ --sysroot=/dev/null \ From patchwork Thu May 16 19:03:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666490 Received: from aer-iport-1.cisco.com (aer-iport-1.cisco.com [173.38.203.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31DA415AAD3; Thu, 16 May 2024 19:05:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886319; cv=none; b=u0CYdtd/Eh+fmWAJSjsU4ifN4Kuem0vBljcVkTtDhVBe832mhx0Yw9cqpzusALRPXZ2rmnlZ5rF0OZm2A+7lli5Shti+naUnFQTEapYY6HB7L3eq1gi80pobJ+G9teghYy6/BSis5PE5SQ9Tr9ebzvxu6sau5as9ZT0CcoJspTQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886319; c=relaxed/simple; bh=ENTYd1tmMLCd25GHq6+1pJgglWWixUwPgOOq0MHQ8MQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jpguLVhl0Kz9qusCP5guEGoRrL6iG+sXBATUnhmKZXaNdB245QIZ0ELfAkG+rIuoYiK+3itczlnR6/MdESXnikvtdaByCjEEPeb6kD12Cx7gU/hX+a4stltjpYDN2jScv7RW9w1N4942frbvfraQnc2uz2PoJ9rntrHfNTLKJIY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=h9BKPGpa; arc=none smtp.client-ip=173.38.203.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="h9BKPGpa" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=3812; q=dns/txt; s=iport; t=1715886317; x=1717095917; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9Pz3QTH8A7TfsLwBUIF2u4gRQxFMrjIamD+SRvopNdE=; b=h9BKPGpacEprKxEP1bC+QsWTCVS68J7XeB/IKLKvHQ7L+64Mj4PyvtxM PmdMD5n4lkMPAIFFUskcxntZEMFenSiQcZ90PIAtd/wP7BihRvkWEn1od iaoF0BQJaGxytKC01Yxjbpa7P6Gn5Dz23C2h397jl7QxshdmW5xWHdd11 k=; X-CSE-ConnectionGUID: xfZILYdcSgOitZwphdK/BQ== X-CSE-MsgGUID: DkDGam0+R/Cnyrr97QGkBg== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12419635" Received: from aer-iport-nat.cisco.com (HELO aer-core-3.cisco.com) ([173.38.203.22]) by aer-iport-1.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:13 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-3.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4DkX017896 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:13 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 10/22] rust: kernel: add an abstraction over vfsmount to allow cloning a new private mount Date: Thu, 16 May 2024 22:03:33 +0300 Message-Id: <20240516190345.957477-11-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-3.cisco.com Provide an abstraction over vfsmount so that we can create a new private mount from Rust code. PuzzleFS needs a private mount of the PuzzleFS image, so it can access the chunks from the data store independent of the future changes to the mount namespace. Signed-off-by: Ariel Miculas --- rust/bindings/bindings_helper.h | 1 + rust/kernel/lib.rs | 1 + rust/kernel/mount.rs | 73 +++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 rust/kernel/mount.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 629fce394dbe..2d87bb9f87c9 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 445599d4bff6..7f0d89b902ce 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -37,6 +37,7 @@ #[cfg(CONFIG_KUNIT)] pub mod kunit; pub mod mem_cache; +pub mod mount; #[cfg(CONFIG_NET)] pub mod net; pub mod prelude; diff --git a/rust/kernel/mount.rs b/rust/kernel/mount.rs new file mode 100644 index 000000000000..50cfe7f7437a --- /dev/null +++ b/rust/kernel/mount.rs @@ -0,0 +1,73 @@ +//! Mount interface +//! +//! C headers: [`include/linux/mount.h`](../../../../include/linux/mount.h) + +use kernel::bindings; +use kernel::error::from_err_ptr; +use kernel::pr_err; +use kernel::prelude::*; +use kernel::str::CStr; +use kernel::types::Opaque; + +/// Wraps the kernel's `struct path`. +#[repr(transparent)] +pub struct Path(pub(crate) Opaque); + +/// Wraps the kernel's `struct vfsmount`. +#[repr(transparent)] +#[derive(Debug)] +pub struct Vfsmount { + vfsmount: *mut bindings::vfsmount, +} + +// SAFETY: No one besides us has the raw pointer, so we can safely transfer Vfsmount to another thread +unsafe impl Send for Vfsmount {} +// SAFETY: It's OK to access `Vfsmount` through references from other threads because we're not +// accessing any properties from the underlying raw pointer +unsafe impl Sync for Vfsmount {} + +impl Vfsmount { + /// Create a new private mount clone based on a path name + pub fn new_private_mount(path_name: &CStr) -> Result { + let path: Path = Path(Opaque::uninit()); + // SAFETY: path_name is a &CStr, so it's a valid string pointer; path is an uninitialized + // struct stored on the stack and it's ok because kern_path expects an out parameter + let err = unsafe { + bindings::kern_path( + path_name.as_ptr().cast::(), + bindings::LOOKUP_FOLLOW | bindings::LOOKUP_DIRECTORY, + path.0.get(), + ) + }; + if err != 0 { + pr_err!("failed to resolve '{}': {}\n", path_name, err); + return Err(EINVAL); + } + + // SAFETY: path is a struct stored on the stack and it is initialized because the call to + // kern_path succeeded + let vfsmount = unsafe { from_err_ptr(bindings::clone_private_mount(path.0.get()))? }; + + // Don't inherit atime flags + // CAST: these flags fit into i32 + let skip_flags = + !(bindings::MNT_NOATIME | bindings::MNT_NODIRATIME | bindings::MNT_RELATIME) as i32; + // SAFETY: we called from_err_ptr so it's safe to dereference this pointer + unsafe { + (*vfsmount).mnt_flags &= skip_flags; + } + Ok(Self { vfsmount }) + } + + /// Returns a raw pointer to vfsmount + pub fn get(&self) -> *mut bindings::vfsmount { + self.vfsmount + } +} + +impl Drop for Vfsmount { + fn drop(&mut self) { + // SAFETY new_private_mount makes sure to return a valid pointer + unsafe { bindings::kern_unmount(self.vfsmount) }; + } +} From patchwork Thu May 16 19:03:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666493 Received: from aer-iport-7.cisco.com (aer-iport-7.cisco.com [173.38.203.69]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26AB615DBCE; Thu, 16 May 2024 19:05:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.69 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886328; cv=none; b=eoEff+NFukibGKrsVrX82wUYnFFWBn9r5c+fvMY8oAoKchsEV6CJCVtBk0l0ecMKe4QASicWsdzj0vQfM3CTxaETFoCxTxQ5aPkugakxDV4pMV9/aHI7pXhw7M3k7rEEO68hPy83bCvatJhcPQePa2KvXE/Y/nfK7c4nHBpf1k8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886328; c=relaxed/simple; bh=Dz0gY/c1vUKma34oa1qxnWPM+toKhYV0/teb5v0jICY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dxcGHbKAUgGWuQQDo58GDsTvysFW4AxIz76ry9m4No0e1sV+GKwS9S71UTXuem5WSrxbo9kFxQZGEpzevhiLGlpnLFeZSmqZjtPyaS+WumgVqhGbXqjTZFGv936NTMZGcRvsOyORq4BYApdHvBJTzOw0DKhYvH1RhByAN7BdpUY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=FACq3hiF; arc=none smtp.client-ip=173.38.203.69 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="FACq3hiF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=8763; q=dns/txt; s=iport; t=1715886326; x=1717095926; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5Zfgw+5jkP6UldlboEjN6TYcmmohaRCDa/+fIuipmTo=; b=FACq3hiFh+OUm1HG/vpRjVqYN7PaYvUYxBJWDvWGASKBUV1tMOPMr5mx bZ0HV0XHjktPMDX4RkgN0VaPeWficEwbdP02HmVXCPbAVZFRBmWVc5Yq2 fN6oT1szB1ay7rIPn07irpp0zMid/x9KTRuhUVLjrZUMySTaorgn1VIyi U=; X-CSE-ConnectionGUID: ylCF91jLTHmQaXFxkL82OQ== X-CSE-MsgGUID: I2kJKejwSomKFhk4qWuDOA== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="13072182" Received: from aer-iport-nat.cisco.com (HELO aer-core-4.cisco.com) ([173.38.203.22]) by aer-iport-7.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:14 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-4.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4EuC006367 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:14 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Wedson Almeida Filho , Daniel Xu , Alice Ryhl , Ariel Miculas Subject: [RFC PATCH v3 11/22] rust: file: add bindings for `struct file` Date: Thu, 16 May 2024 22:03:34 +0300 Message-Id: <20240516190345.957477-12-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-4.cisco.com From: Wedson Almeida Filho Using these bindings it becomes possible to access files from drivers written in Rust. This patch only adds support for accessing the flags, and for managing the refcount of the file. Signed-off-by: Wedson Almeida Filho Co-Developed-by: Daniel Xu Signed-off-by: Daniel Xu Co-Developed-by: Alice Ryhl Signed-off-by: Alice Ryhl [Adapted for upstream] Signed-off-by: Ariel Miculas --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 16 +++ rust/kernel/file.rs | 176 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 4 files changed, 194 insertions(+) create mode 100644 rust/kernel/file.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 2d87bb9f87c9..0491bb05270c 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers.c b/rust/helpers.c index c26aa07cb20f..90acf9677aa6 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -353,6 +354,21 @@ void rust_helper_set_delayed_call(struct delayed_call *call, } EXPORT_SYMBOL_GPL(rust_helper_set_delayed_call); +struct inode *rust_helper_d_inode(const struct dentry *dentry) +{ + return d_inode(dentry); +} +EXPORT_SYMBOL_GPL(rust_helper_d_inode); + +int rust_helper_fs_parse(struct fs_context *fc, + const struct fs_parameter_spec *desc, + struct fs_parameter *param, + struct fs_parse_result *result) +{ + return fs_parse(fc, desc, param, result); +} +EXPORT_SYMBOL_GPL(rust_helper_fs_parse); + /* * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can * use it in contexts where Rust expects a `usize` like slice (array) indices. diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs new file mode 100644 index 000000000000..99657adf2472 --- /dev/null +++ b/rust/kernel/file.rs @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Files and file descriptors. +//! +//! C headers: [`include/linux/fs.h`](../../../../include/linux/fs.h) and +//! [`include/linux/file.h`](../../../../include/linux/file.h) + +use crate::{ + bindings, + error::{code::*, Error, Result}, + types::{ARef, AlwaysRefCounted, Opaque}, +}; +use core::ptr; + +/// Flags associated with a [`File`]. +pub mod flags { + /// File is opened in append mode. + pub const O_APPEND: u32 = bindings::O_APPEND; + + /// Signal-driven I/O is enabled. + pub const O_ASYNC: u32 = bindings::FASYNC; + + /// Close-on-exec flag is set. + pub const O_CLOEXEC: u32 = bindings::O_CLOEXEC; + + /// File was created if it didn't already exist. + pub const O_CREAT: u32 = bindings::O_CREAT; + + /// Direct I/O is enabled for this file. + pub const O_DIRECT: u32 = bindings::O_DIRECT; + + /// File must be a directory. + pub const O_DIRECTORY: u32 = bindings::O_DIRECTORY; + + /// Like [`O_SYNC`] except metadata is not synced. + pub const O_DSYNC: u32 = bindings::O_DSYNC; + + /// Ensure that this file is created with the `open(2)` call. + pub const O_EXCL: u32 = bindings::O_EXCL; + + /// Large file size enabled (`off64_t` over `off_t`). + pub const O_LARGEFILE: u32 = bindings::O_LARGEFILE; + + /// Do not update the file last access time. + pub const O_NOATIME: u32 = bindings::O_NOATIME; + + /// File should not be used as process's controlling terminal. + pub const O_NOCTTY: u32 = bindings::O_NOCTTY; + + /// If basename of path is a symbolic link, fail open. + pub const O_NOFOLLOW: u32 = bindings::O_NOFOLLOW; + + /// File is using nonblocking I/O. + pub const O_NONBLOCK: u32 = bindings::O_NONBLOCK; + + /// Also known as `O_NDELAY`. + /// + /// This is effectively the same flag as [`O_NONBLOCK`] on all architectures + /// except SPARC64. + pub const O_NDELAY: u32 = bindings::O_NDELAY; + + /// Used to obtain a path file descriptor. + pub const O_PATH: u32 = bindings::O_PATH; + + /// Write operations on this file will flush data and metadata. + pub const O_SYNC: u32 = bindings::O_SYNC; + + /// This file is an unnamed temporary regular file. + pub const O_TMPFILE: u32 = bindings::O_TMPFILE; + + /// File should be truncated to length 0. + pub const O_TRUNC: u32 = bindings::O_TRUNC; + + /// Bitmask for access mode flags. + /// + /// # Examples + /// + /// ``` + /// use kernel::file; + /// # fn do_something() {} + /// # let flags = 0; + /// if (flags & file::flags::O_ACCMODE) == file::flags::O_RDONLY { + /// do_something(); + /// } + /// ``` + pub const O_ACCMODE: u32 = bindings::O_ACCMODE; + + /// File is read only. + pub const O_RDONLY: u32 = bindings::O_RDONLY; + + /// File is write only. + pub const O_WRONLY: u32 = bindings::O_WRONLY; + + /// File can be both read and written. + pub const O_RDWR: u32 = bindings::O_RDWR; +} + +/// Wraps the kernel's `struct file`. +/// +/// # Invariants +/// +/// Instances of this type are always ref-counted, that is, a call to `get_file` ensures that the +/// allocation remains valid at least until the matching call to `fput`. +#[repr(transparent)] +pub struct File(Opaque); + +// SAFETY: By design, the only way to access a `File` is via an immutable reference or an `ARef`. +// This means that the only situation in which a `File` can be accessed mutably is when the +// refcount drops to zero and the destructor runs. It is safe for that to happen on any thread, so +// it is ok for this type to be `Send`. +unsafe impl Send for File {} + +// SAFETY: It's OK to access `File` through shared references from other threads because we're +// either accessing properties that don't change or that are properly synchronised by C code. +unsafe impl Sync for File {} + +impl File { + /// Constructs a new `struct file` wrapper from a file descriptor. + /// + /// The file descriptor belongs to the current process. + pub fn from_fd(fd: u32) -> Result, BadFdError> { + // SAFETY: FFI call, there are no requirements on `fd`. + let ptr = ptr::NonNull::new(unsafe { bindings::fget(fd) }).ok_or(BadFdError)?; + + // SAFETY: `fget` increments the refcount before returning. + Ok(unsafe { ARef::from_raw(ptr.cast()) }) + } + + /// Creates a reference to a [`File`] from a valid pointer. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` points at a valid file and that its refcount does not + /// reach zero until after the end of the lifetime 'a. + pub unsafe fn from_ptr<'a>(ptr: *const bindings::file) -> &'a File { + // SAFETY: The safety requirements guarantee the validity of the dereference, while the + // `File` type being transparent makes the cast ok. + unsafe { &*ptr.cast() } + } + + /// Returns the flags associated with the file. + /// + /// The flags are a combination of the constants in [`flags`]. + pub fn flags(&self) -> u32 { + // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount. + // + // This uses a volatile read because C code may be modifying this field in parallel using + // non-atomic unsynchronized writes. This corresponds to how the C macro READ_ONCE is + // implemented. + unsafe { core::ptr::addr_of!((*self.0.get()).f_flags).read_volatile() } + } +} + +// SAFETY: The type invariants guarantee that `File` is always ref-counted. +unsafe impl AlwaysRefCounted for File { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { bindings::get_file(self.0.get()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is nonzero. + unsafe { bindings::fput(obj.cast().as_ptr()) } + } +} + +/// Represents the EBADF error code. +/// +/// Used for methods that can only fail with EBADF. +pub struct BadFdError; + +impl From for Error { + fn from(_: BadFdError) -> Error { + EBADF + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 7f0d89b902ce..ea1411a25ee4 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -30,6 +30,7 @@ pub mod block; mod build_assert; pub mod error; +pub mod file; pub mod folio; pub mod fs; pub mod init; From patchwork Thu May 16 19:03:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666475 Received: from aer-iport-2.cisco.com (aer-iport-2.cisco.com [173.38.203.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 238FC14533D; Thu, 16 May 2024 19:04:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886261; cv=none; b=ntavZk71l5vZN2+xP4Etqi1CdsnhZupcktyAtaGy5/cqOUYvokub2RKjYaXG3l7d1kM/BT5UlnWI7K+N4KtdmY0WDEzIZuUPFjTGYxhwCC8vPUiusKpgJ9ngUsmjvnufo4deZpD85b+URVZGMuJ+HcKywMxyRlcyLEdlX1+gGOA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886261; c=relaxed/simple; bh=ZW6e38D7V579eUYjN8wx+opoFbYZthAY3SWMwT68uA4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pugBNa2FzupcRsLPcKLy3hnLTYmtJt8qKw8j1T2FxOG685ZL8m1kgJE89/xTu7pB72HS0YCZ4sY3+2zXW46NB7A+EALIbJDyg7uw1A0oj4hwyxrqhmQvYXxMWZfmpDUAJJXVTd6QpxuW7CSnd91V/zfCpDKB4y8TK1i6AK/imYY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=j+WGEDmG; arc=none smtp.client-ip=173.38.203.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="j+WGEDmG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=6116; q=dns/txt; s=iport; t=1715886258; x=1717095858; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gtETx0x72o83B4fsks8iN1y24qrMuZAVeU7lzntU45E=; b=j+WGEDmGX/g0WHHUPLpaplSOlw/RrCGrvB+laRN4KNsM0qLD3kEVNTtN q/qX355FuMLqwVxsCfesgXd9TJsf1SxBJGn7PEtPgkC/DdwnJ/IgWUuyZ THQYE56PQ46kD/u6CZ3WM8yzqwGlXOnI5gLGV+gp+vt2V2HrZI8TKqqMW 0=; X-CSE-ConnectionGUID: HMe8tTQ/T8S85WGsTTj5nA== X-CSE-MsgGUID: 8UtqKVBVRKWMKr4vvm8D5Q== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12416988" Received: from aer-iport-nat.cisco.com (HELO aer-core-5.cisco.com) ([173.38.203.22]) by aer-iport-2.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:16 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-5.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4Fgt055638 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:16 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 12/22] rust: file: Add support for reading files using their path Date: Thu, 16 May 2024 22:03:35 +0300 Message-Id: <20240516190345.957477-13-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-5.cisco.com Implement from_path, from_path_in_root_mnt, read_with_offset, read_to_end and get_file_size methods for a RegularFile newtype. `kernel_read_file` is used under the hood for reading files. These functions will be used for reading the PuzzleFS metadata files and the chunks in the data store. Signed-off-by: Ariel Miculas --- rust/kernel/error.rs | 2 +- rust/kernel/file.rs | 124 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index edada157879a..3cf916bc884f 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -263,7 +263,7 @@ pub fn to_result(err: core::ffi::c_int) -> Result { /// from_err_ptr(unsafe { bindings::devm_platform_ioremap_resource(pdev.to_ptr(), index) }) /// } /// ``` -pub(crate) fn from_err_ptr(ptr: *mut T) -> Result<*mut T> { +pub fn from_err_ptr(ptr: *mut T) -> Result<*mut T> { // CAST: Casting a pointer to `*const core::ffi::c_void` is always valid. let const_ptr: *const core::ffi::c_void = ptr.cast(); // SAFETY: The FFI function does not deref the pointer. diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs index 99657adf2472..c381cc297f3a 100644 --- a/rust/kernel/file.rs +++ b/rust/kernel/file.rs @@ -5,11 +5,16 @@ //! C headers: [`include/linux/fs.h`](../../../../include/linux/fs.h) and //! [`include/linux/file.h`](../../../../include/linux/file.h) +use crate::alloc::flags::GFP_KERNEL; +use crate::alloc::vec_ext::VecExt; use crate::{ bindings, - error::{code::*, Error, Result}, + error::{code::*, from_err_ptr, Error, Result}, + mount::Vfsmount, + str::CStr, types::{ARef, AlwaysRefCounted, Opaque}, }; +use alloc::vec::Vec; use core::ptr; /// Flags associated with a [`File`]. @@ -164,6 +169,123 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } +/// A newtype over file, specific to regular files +pub struct RegularFile(ARef); +impl RegularFile { + /// Creates a new instance of Self if the file is a regular file + /// + /// # Safety + /// + /// The caller must ensure file_ptr.f_inode is initialized to a valid pointer (e.g. file_ptr is + /// a pointer returned by path_openat); It must also ensure that file_ptr's reference count was + /// incremented at least once + unsafe fn create_if_regular(file_ptr: *mut bindings::file) -> Result { + let file_ptr = ptr::NonNull::new(file_ptr).ok_or(ENOENT)?; + // SAFETY: file_ptr is a NonNull pointer + let inode = unsafe { core::ptr::addr_of!((*file_ptr.as_ptr()).f_inode).read() }; + // SAFETY: the caller must ensure f_inode is initialized to a valid pointer + let inode_mode = unsafe { (*inode).i_mode as u32 }; + if bindings::S_IFMT & inode_mode != bindings::S_IFREG { + return Err(EINVAL); + } + // SAFETY: the safety requirements state that file_ptr's reference count was incremented at + // least once + Ok(RegularFile(unsafe { ARef::from_raw(file_ptr.cast()) })) + } + /// Constructs a new [`struct file`] wrapper from a path. + pub fn from_path(filename: &CStr, flags: i32, mode: u16) -> Result { + // SAFETY: filename is a reference, so it's a valid pointer + let file_ptr = unsafe { + from_err_ptr(bindings::filp_open( + filename.as_ptr().cast::(), + flags, + mode, + ))? + }; + + // SAFETY: `filp_open` initializes the refcount with 1 + unsafe { Self::create_if_regular(file_ptr) } + } + + /// Constructs a new [`struct file`] wrapper from a path and a vfsmount. + pub fn from_path_in_root_mnt( + mount: &Vfsmount, + filename: &CStr, + flags: i32, + mode: u16, + ) -> Result { + let mnt = mount.get(); + // construct a path from vfsmount, see file_open_root_mnt + let raw_path = bindings::path { + mnt, + // SAFETY: Vfsmount structure stores a valid vfsmount object + dentry: unsafe { (*mnt).mnt_root }, + }; + let file_ptr = unsafe { + // SAFETY: raw_path and filename are both references + from_err_ptr(bindings::file_open_root( + &raw_path, + filename.as_ptr().cast::(), + flags, + mode, + ))? + }; + // SAFETY: `file_open_root` initializes the refcount with 1 + unsafe { Self::create_if_regular(file_ptr) } + } + + /// Read from the file into the specified buffer + pub fn read_with_offset(&self, buf: &mut [u8], offset: u64) -> Result { + // kernel_read_file expects a pointer to a "void *" buffer + let mut ptr_to_buf = buf.as_mut_ptr() as *mut core::ffi::c_void; + // Unless we give a non-null pointer to the file size: + // 1. we cannot give a non-zero value for the offset + // 2. we cannot have offset 0 and buffer_size > file_size + let mut file_size = 0; + + // SAFETY: 'file' is valid because it's taken from Self, 'buf' and 'file_size` are + // references to the stack variables 'ptr_to_buf' and 'file_size'; ptr_to_buf is also + // a pointer to a valid buffer that was obtained from a reference + let result = unsafe { + bindings::kernel_read_file( + self.0 .0.get(), + offset.try_into()?, + &mut ptr_to_buf, + buf.len(), + &mut file_size, + bindings::kernel_read_file_id_READING_UNKNOWN, + ) + }; + + // kernel_read_file returns the number of bytes read on success or negative on error. + if result < 0 { + return Err(Error::from_errno(result.try_into()?)); + } + + Ok(result.try_into()?) + } + + /// Allocate and return a vector containing the contents of the entire file + pub fn read_to_end(&self) -> Result> { + let file_size = self.get_file_size()?; + let mut buffer = Vec::with_capacity(file_size, GFP_KERNEL)?; + buffer.resize(file_size, 0, GFP_KERNEL)?; + self.read_with_offset(&mut buffer, 0)?; + Ok(buffer) + } + + fn get_file_size(&self) -> Result { + // SAFETY: 'file' is valid because it's taken from Self + let file_size = unsafe { bindings::i_size_read((*self.0 .0.get()).f_inode) }; + + if file_size < 0 { + return Err(EINVAL); + } + + Ok(file_size.try_into()?) + } +} + /// Represents the EBADF error code. /// /// Used for methods that can only fail with EBADF. From patchwork Thu May 16 19:03:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666496 Received: from aer-iport-8.cisco.com (aer-iport-8.cisco.com [173.38.203.70]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 09554157E84; Thu, 16 May 2024 19:07:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.70 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886462; cv=none; b=tp5TC/Fpn5w7luCpoSixR41Y7qTyDALiXCHBnr+EVsp96uQwSk8Q5S36kRwUQ/4SpqVXT1yeKgvMCaJMIf7vorNjVm6CVZGndpSlJpuwXdKiiHVL9+s/fdB73032YfrgQd0wWf7pCAsophr73hyRTkWk3PxvLeZBnQkbci1crVU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886462; c=relaxed/simple; bh=4jcFQHpyHtc8RiIQMEs9vzqF2onapH927vZvD1JXyME=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=j4aJiwLWAwb5kA+ZmQIgbAL3qcjD/rh+b0ZSAvCtaS/pN+VLkLmGlPsS/9eDilH+/ANZgFruO/Z9s8AOD26vMrHkV+Dh+ImN2Au/Ekt+zzbsDelZNniarkQQsCuCginWH1QbRwlKKKTyq+6DwzPM87ilc0gS7CuEsCew852XjKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=DVFQ+EIx; arc=none smtp.client-ip=173.38.203.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="DVFQ+EIx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=187796; q=dns/txt; s=iport; t=1715886453; x=1717096053; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=n8OYYA2FlfuEOlWK1MYVdn1VBSudZULRl/4bBAxGXxc=; b=DVFQ+EIxVHPCBIQ0dxk4N0FwYqEnvui4frMLXzwMPNT1F/3GXzsv4zoT A9R5H+KT9lSI8CIJ3tJDKwCOgT09x5/wajwCLOcCf29H75QWGycLmH0ul 5lTFd3+qlHaFOKdrJAigVRls8w0JFXjDFJYs7DZD6vTQWNO7Xp0yO6ANc 4=; X-CSE-ConnectionGUID: fLk6vcteR3S4m3Os9zkr0Q== X-CSE-MsgGUID: pcAbmh5wTNqMTM/oZVbSPA== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="9784122" Received: from aer-iport-nat.cisco.com (HELO aer-core-10.cisco.com) ([173.38.203.22]) by aer-iport-8.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:17 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-10.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4G66101480 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:17 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 13/22] fs: puzzlefs: Implement the initial version of PuzzleFS Date: Thu, 16 May 2024 22:03:36 +0300 Message-Id: <20240516190345.957477-14-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-10.cisco.com Implement the file system trait fs::FileSystem for PuzzleFS, directory iteration, inode lookup and the read_folio operations. The puzzlefs image path and the manifest digest are hard-coded for now due to the lack of module parameters support. Puzzlefs uses capnproto for storing the filesystem metadata, defined in manifest.capnp and metadata.capnp. The files manifest_capnp.rs and metadata_capnp.rs were generated with (Cap'n Proto version 0.10.4): ``` capnp compile -orust manifest.capnp capnp compile -orust metadata.capnp ``` , formatted with rustfmt and I have also added the following line: ``` #![allow(unreachable_pub)] #![allow(dead_code)] ``` to avoid warnings. capnp version used: ``` $ capnp --version Cap'n Proto version 0.10.4 $ cargo install --list | grep capnp capnpc v0.18.0: capnpc-rust capnpc-rust-bootstrap ``` Ideally, manifest_capnp.rs and metadata_capnp.rs should be automatically generated at build time. However, this means the capnp binary becomes a dependency for the build and I didn't want this. Besides, the metadata schemas are not expected to change frequently, so it's acceptable to manually regenerate the two rust files when this happens. The code is adapted from the puzzlefs FUSE driver [1]. The data structures required for the filesystem metadata are defined in types.rs. Each structure has a `from_capnp` method used to convert between the capnp memory layout and the native Rust structures. This leaves room for improvement [2]. inode.rs implements the PuzzleFS structure which contains a list of metadata layers. Link: https://github.com/project-machine/puzzlefs [1] Link: https://lore.kernel.org/rust-for-linux/ZI3ZnFk2uELYFX0R@moria.home.lan/ [2] Signed-off-by: Ariel Miculas --- fs/Kconfig | 1 + fs/Makefile | 1 + fs/puzzlefs/Kconfig | 14 + fs/puzzlefs/Makefile | 8 + fs/puzzlefs/puzzle.rs | 5 + fs/puzzlefs/puzzle/error.rs | 105 + fs/puzzlefs/puzzle/inode.rs | 100 + fs/puzzlefs/puzzle/oci.rs | 70 + fs/puzzlefs/puzzle/types.rs | 377 ++ fs/puzzlefs/puzzle/types/manifest.capnp | 15 + fs/puzzlefs/puzzle/types/manifest_capnp.rs | 757 ++++ fs/puzzlefs/puzzle/types/metadata.capnp | 65 + fs/puzzlefs/puzzle/types/metadata_capnp.rs | 4049 ++++++++++++++++++++ fs/puzzlefs/puzzlefs.rs | 227 ++ rust/kernel/error.rs | 2 +- 15 files changed, 5795 insertions(+), 1 deletion(-) create mode 100644 fs/puzzlefs/Kconfig create mode 100644 fs/puzzlefs/Makefile create mode 100644 fs/puzzlefs/puzzle.rs create mode 100644 fs/puzzlefs/puzzle/error.rs create mode 100644 fs/puzzlefs/puzzle/inode.rs create mode 100644 fs/puzzlefs/puzzle/oci.rs create mode 100644 fs/puzzlefs/puzzle/types.rs create mode 100644 fs/puzzlefs/puzzle/types/manifest.capnp create mode 100644 fs/puzzlefs/puzzle/types/manifest_capnp.rs create mode 100644 fs/puzzlefs/puzzle/types/metadata.capnp create mode 100644 fs/puzzlefs/puzzle/types/metadata_capnp.rs create mode 100644 fs/puzzlefs/puzzlefs.rs diff --git a/fs/Kconfig b/fs/Kconfig index a46b0cbc4d8f..88ac055d6b49 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -337,6 +337,7 @@ source "fs/sysv/Kconfig" source "fs/ufs/Kconfig" source "fs/erofs/Kconfig" source "fs/vboxsf/Kconfig" +source "fs/puzzlefs/Kconfig" endif # MISC_FILESYSTEMS diff --git a/fs/Makefile b/fs/Makefile index 6ecc9b0a53f2..5cfc91653b4a 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -129,3 +129,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ obj-$(CONFIG_EROFS_FS) += erofs/ obj-$(CONFIG_VBOXSF_FS) += vboxsf/ obj-$(CONFIG_ZONEFS_FS) += zonefs/ +obj-$(CONFIG_PUZZLEFS_FS) += puzzlefs/ diff --git a/fs/puzzlefs/Kconfig b/fs/puzzlefs/Kconfig new file mode 100644 index 000000000000..256fb542dc92 --- /dev/null +++ b/fs/puzzlefs/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +# + +config PUZZLEFS_FS + tristate "PuzzleFS file system support" + depends on RUST + help + This option builds PuzzleFS, a next-generation container filesystem. + + To compile this as a module, choose M here: + the module will be called puzzlefs. + + If unsure, say N. + diff --git a/fs/puzzlefs/Makefile b/fs/puzzlefs/Makefile new file mode 100644 index 000000000000..24eb4ff20224 --- /dev/null +++ b/fs/puzzlefs/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the linux puzzlefs filesystem. +# + +obj-$(CONFIG_PUZZLEFS_FS) += puzzlefs.o + +puzzlefs-y := puzzlefs.o diff --git a/fs/puzzlefs/puzzle.rs b/fs/puzzlefs/puzzle.rs new file mode 100644 index 000000000000..e74a248c39ff --- /dev/null +++ b/fs/puzzlefs/puzzle.rs @@ -0,0 +1,5 @@ +pub(crate) mod error; +pub(crate) mod types; +pub(crate) use types::{manifest_capnp, metadata_capnp}; +pub(crate) mod inode; +pub(crate) mod oci; diff --git a/fs/puzzlefs/puzzle/error.rs b/fs/puzzlefs/puzzle/error.rs new file mode 100644 index 000000000000..6ed7ef3d8568 --- /dev/null +++ b/fs/puzzlefs/puzzle/error.rs @@ -0,0 +1,105 @@ +use core::ffi::c_int; +use core::fmt::{self, Display}; +use kernel::prelude::EINVAL; + +pub(crate) enum WireFormatError { + InvalidSerializedData, + KernelError(kernel::error::Error), + AllocError(kernel::alloc::AllocError), + CapnpError(capnp::Error), + FromIntError(core::num::TryFromIntError), + FromSliceError(core::array::TryFromSliceError), + HexError(hex::FromHexError), +} + +impl WireFormatError { + pub(crate) fn to_errno(&self) -> c_int { + match self { + WireFormatError::InvalidSerializedData => kernel::error::Error::to_errno(EINVAL), + WireFormatError::KernelError(e) => kernel::error::Error::to_errno(*e), + WireFormatError::AllocError(_) => kernel::error::Error::to_errno(EINVAL), + WireFormatError::CapnpError(_) => kernel::error::Error::to_errno(EINVAL), + WireFormatError::FromIntError(_) => kernel::error::Error::to_errno(EINVAL), + WireFormatError::FromSliceError(_) => kernel::error::Error::to_errno(EINVAL), + WireFormatError::HexError(_) => kernel::error::Error::to_errno(EINVAL), + } + } + + pub(crate) fn from_errno(errno: kernel::error::Error) -> Self { + Self::KernelError(errno) + } +} + +impl Display for WireFormatError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + WireFormatError::InvalidSerializedData => f.write_str("invalid serialized data"), + WireFormatError::KernelError(e) => { + f.write_fmt(format_args!("Kernel error {}", e.to_errno())) + } + WireFormatError::AllocError(_) => f.write_str("AllocError"), + WireFormatError::CapnpError(e) => f.write_fmt(format_args!("Capnp error: {e}")), + WireFormatError::FromIntError(_) => f.write_str("TryFromIntError"), + WireFormatError::FromSliceError(_) => f.write_str("TryFromSliceError"), + WireFormatError::HexError(e) => f.write_fmt(format_args!("HexError {e}")), + } + } +} + +pub(crate) type Result = kernel::error::Result; + +// TODO figure out how to use thiserror +#[allow(unused_qualifications)] +impl core::convert::From for WireFormatError { + #[allow(deprecated)] + fn from(source: kernel::error::Error) -> Self { + WireFormatError::KernelError(source) + } +} + +#[allow(unused_qualifications)] +impl core::convert::From for WireFormatError { + #[allow(deprecated)] + fn from(source: kernel::alloc::AllocError) -> Self { + WireFormatError::AllocError(source) + } +} + +#[allow(unused_qualifications)] +impl core::convert::From for WireFormatError { + #[allow(deprecated)] + fn from(source: capnp::Error) -> Self { + WireFormatError::CapnpError(source) + } +} + +#[allow(unused_qualifications)] +impl core::convert::From for WireFormatError { + #[allow(deprecated)] + fn from(source: core::array::TryFromSliceError) -> Self { + WireFormatError::FromSliceError(source) + } +} + +#[allow(unused_qualifications)] +impl core::convert::From for WireFormatError { + #[allow(deprecated)] + fn from(source: core::num::TryFromIntError) -> Self { + WireFormatError::FromIntError(source) + } +} + +impl core::convert::From for WireFormatError { + #[allow(deprecated)] + fn from(source: hex::FromHexError) -> Self { + WireFormatError::HexError(source) + } +} + +#[allow(unused_qualifications)] +impl core::convert::From for kernel::error::Error { + #[allow(deprecated)] + fn from(source: WireFormatError) -> Self { + kernel::error::Error::from_errno(source.to_errno()) + } +} diff --git a/fs/puzzlefs/puzzle/inode.rs b/fs/puzzlefs/puzzle/inode.rs new file mode 100644 index 000000000000..318edbdc5163 --- /dev/null +++ b/fs/puzzlefs/puzzle/inode.rs @@ -0,0 +1,100 @@ +// This contents of this file is taken from puzzlefs.rs (the userspace implementation) +// It is named inode.rs instead puzzlefs.rs since the root of this kernel module already has that name + +use crate::puzzle::error::Result; +use crate::puzzle::error::WireFormatError; +use crate::puzzle::oci::Image; +use crate::puzzle::types as format; +use crate::puzzle::types::{Digest, Inode, InodeMode}; +use alloc::vec::Vec; +use kernel::mount::Vfsmount; +use kernel::prelude::{VecExt, ENOENT, ENOTDIR, GFP_KERNEL}; +use kernel::str::CStr; + +pub(crate) struct PuzzleFS { + pub(crate) oci: Image, + layers: Vec, +} + +impl PuzzleFS { + pub(crate) fn open(oci_root_dir: &CStr, rootfs_path: &CStr) -> Result { + let vfs_mount = Vfsmount::new_private_mount(oci_root_dir)?; + let oci = Image::open(vfs_mount)?; + let rootfs = oci.open_rootfs_blob(rootfs_path)?; + + let mut layers = Vec::new(); + for md in rootfs.metadatas.iter() { + let digest = Digest::try_from(md)?; + layers.push(oci.open_metadata_blob(&digest)?, GFP_KERNEL)?; + } + + Ok(PuzzleFS { oci, layers }) + } + + pub(crate) fn find_inode(&self, ino: u64) -> Result { + for layer in self.layers.iter() { + if let Some(inode) = layer.find_inode(ino)? { + let inode = Inode::from_capnp(inode)?; + if let InodeMode::Wht = inode.mode { + // TODO: seems like this should really be an Option. + return Err(WireFormatError::from_errno(ENOENT)); + } + return Ok(inode); + } + } + + Err(WireFormatError::from_errno(ENOENT)) + } +} + +pub(crate) fn file_read( + oci: &Image, + inode: &Inode, + offset: usize, + data: &mut [u8], +) -> Result { + let chunks = match &inode.mode { + InodeMode::File { chunks } => chunks, + _ => return Err(WireFormatError::from_errno(ENOTDIR)), + }; + + // TODO: fix all this casting... + let end = offset + data.len(); + + let mut file_offset = 0; + let mut buf_offset = 0; + for chunk in chunks { + // have we read enough? + if file_offset > end { + break; + } + + // should we skip this chunk? + if file_offset + (chunk.len as usize) < offset { + file_offset += chunk.len as usize; + continue; + } + + let addl_offset = if offset > file_offset { + offset - file_offset + } else { + 0 + }; + + // ok, need to read this chunk; how much? + let left_in_buf = data.len() - buf_offset; + let to_read = core::cmp::min(left_in_buf, chunk.len as usize - addl_offset); + + let start = buf_offset; + let finish = start + to_read; + file_offset += addl_offset; + + // how many did we actually read? + let n = oci.fill_from_chunk(chunk.blob, addl_offset as u64, &mut data[start..finish])?; + file_offset += n; + buf_offset += n; + } + + // discard any extra if we hit EOF + Ok(buf_offset) +} diff --git a/fs/puzzlefs/puzzle/oci.rs b/fs/puzzlefs/puzzle/oci.rs new file mode 100644 index 000000000000..bd285281278d --- /dev/null +++ b/fs/puzzlefs/puzzle/oci.rs @@ -0,0 +1,70 @@ +use crate::puzzle::error::{Result, WireFormatError}; +use crate::puzzle::types::{BlobRef, Digest, MetadataBlob, Rootfs}; +use kernel::c_str; +use kernel::file; +use kernel::file::RegularFile; +use kernel::mount::Vfsmount; +use kernel::pr_debug; +use kernel::prelude::ENOTSUPP; +use kernel::str::{CStr, CString}; + +#[derive(Debug)] +pub(crate) struct Image { + pub(crate) vfs_mount: Vfsmount, +} + +impl Image { + pub(crate) fn open(vfsmount: Vfsmount) -> Result { + Ok(Image { + vfs_mount: vfsmount, + }) + } + + pub(crate) fn blob_path_relative(&self) -> &CStr { + c_str!("blobs/sha256") + } + + fn open_raw_blob(&self, digest: &Digest) -> Result { + let filename = + CString::try_from_fmt(format_args!("{}/{digest}", self.blob_path_relative()))?; + pr_debug!("trying to open {:?}\n", &*filename); + + let file = RegularFile::from_path_in_root_mnt( + &self.vfs_mount, + &filename, + file::flags::O_RDONLY.try_into().unwrap(), + 0, + )?; + + Ok(file) + } + + pub(crate) fn open_metadata_blob(&self, digest: &Digest) -> Result { + let f = self.open_raw_blob(digest)?; + MetadataBlob::new(f) + } + + pub(crate) fn open_rootfs_blob(&self, path: &CStr) -> Result { + let digest = Digest::try_from(path)?; + let rootfs = Rootfs::open(self.open_raw_blob(&digest)?)?; + Ok(rootfs) + } + + pub(crate) fn fill_from_chunk( + &self, + chunk: BlobRef, + addl_offset: u64, + buf: &mut [u8], + ) -> Result { + let digest = &::try_from(chunk)?; + + let blob = if chunk.compressed { + return Err(WireFormatError::KernelError(ENOTSUPP)); + } else { + self.open_raw_blob(digest)? + }; + + let n = blob.read_with_offset(buf, chunk.offset + addl_offset)?; + Ok(n) + } +} diff --git a/fs/puzzlefs/puzzle/types.rs b/fs/puzzlefs/puzzle/types.rs new file mode 100644 index 000000000000..ec9bc77cf1ee --- /dev/null +++ b/fs/puzzlefs/puzzle/types.rs @@ -0,0 +1,377 @@ +use crate::puzzle::error::Result; +use crate::puzzle::error::WireFormatError; +use alloc::vec::Vec; +use capnp::{message, serialize}; +use core::fmt; +use hex::{encode_hex_iter, FromHexError}; +use kernel::file; +use kernel::prelude::{VecExt, ENOENT, ENOTDIR, GFP_KERNEL}; +use kernel::str::CStr; + +pub(crate) mod manifest_capnp; +pub(crate) mod metadata_capnp; + +pub(crate) const SHA256_BLOCK_SIZE: usize = 32; + +#[derive(Debug)] +pub(crate) struct Rootfs { + pub(crate) metadatas: Vec, + #[allow(dead_code)] + pub(crate) manifest_version: u64, +} + +impl Rootfs { + pub(crate) fn open(file: file::RegularFile) -> Result { + let manifest_buffer = file.read_to_end()?; + let message_reader = serialize::read_message_from_flat_slice_no_alloc( + &mut &manifest_buffer[..], + ::capnp::message::ReaderOptions::new(), + )?; + let rootfs = message_reader.get_root::>()?; + Self::from_capnp(rootfs) + } + + pub(crate) fn from_capnp(reader: crate::manifest_capnp::rootfs::Reader<'_>) -> Result { + let metadatas = reader.get_metadatas()?; + + let mut metadata_vec = Vec::new(); + for blobref in metadatas.iter() { + metadata_vec.push(BlobRef::from_capnp(blobref)?, GFP_KERNEL)?; + } + + Ok(Rootfs { + metadatas: metadata_vec, + manifest_version: reader.get_manifest_version(), + }) + } +} + +// TODO: should this be an ociv1 digest and include size and media type? +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) struct BlobRef { + pub(crate) digest: [u8; SHA256_BLOCK_SIZE], + pub(crate) offset: u64, + pub(crate) compressed: bool, +} + +impl BlobRef { + pub(crate) fn from_capnp(reader: metadata_capnp::blob_ref::Reader<'_>) -> Result { + let digest = reader.get_digest()?; + Ok(BlobRef { + digest: digest.try_into()?, + offset: reader.get_offset(), + compressed: reader.get_compressed(), + }) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct DirEnt { + pub(crate) ino: Ino, + pub(crate) name: Vec, +} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct DirList { + // TODO: flags instead? + pub(crate) look_below: bool, + pub(crate) entries: Vec, +} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct FileChunk { + pub(crate) blob: BlobRef, + pub(crate) len: u64, +} + +pub(crate) type Ino = u64; + +impl FileChunk { + pub(crate) fn from_capnp(reader: metadata_capnp::file_chunk::Reader<'_>) -> Result { + let len = reader.get_len(); + let blob = BlobRef::from_capnp(reader.get_blob()?)?; + + Ok(FileChunk { blob, len }) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct Inode { + pub(crate) ino: Ino, + pub(crate) mode: InodeMode, + pub(crate) uid: u32, + pub(crate) gid: u32, + pub(crate) permissions: u16, + pub(crate) additional: Option, +} + +impl Inode { + pub(crate) fn from_capnp(reader: metadata_capnp::inode::Reader<'_>) -> Result { + Ok(Inode { + ino: reader.get_ino(), + mode: InodeMode::from_capnp(reader.get_mode())?, + uid: reader.get_uid(), + gid: reader.get_gid(), + permissions: reader.get_permissions(), + additional: InodeAdditional::from_capnp(reader.get_additional()?)?, + }) + } + + pub(crate) fn dir_entries(&self) -> Result<&Vec> { + match &self.mode { + InodeMode::Dir { dir_list } => Ok(&dir_list.entries), + _ => Err(WireFormatError::from_errno(ENOTDIR)), + } + } + + pub(crate) fn dir_lookup(&self, name: &[u8]) -> Result { + let entries = self.dir_entries()?; + entries + .iter() + .find(|dir_ent| dir_ent.name == name) + .map(|dir_ent| dir_ent.ino) + .ok_or_else(|| WireFormatError::from_errno(ENOENT)) + } + + pub(crate) fn size(&self) -> Result { + match &self.mode { + InodeMode::Dir { dir_list } => Ok(dir_list.entries.len().try_into()?), + InodeMode::File { chunks } => { + let mut size = 0; + for chunk in chunks { + size += chunk.len; + } + Ok(size.try_into()?) + } + _ => todo!(), + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) enum InodeMode { + Unknown, + Fifo, + Chr { major: u64, minor: u64 }, + Dir { dir_list: DirList }, + Blk { major: u64, minor: u64 }, + File { chunks: Vec }, + Lnk, + Sock, + Wht, +} + +impl InodeMode { + fn from_capnp(reader: metadata_capnp::inode::mode::Reader<'_>) -> Result { + match reader.which() { + Ok(metadata_capnp::inode::mode::Unknown(())) => Ok(InodeMode::Unknown), + Ok(metadata_capnp::inode::mode::Fifo(())) => Ok(InodeMode::Fifo), + Ok(metadata_capnp::inode::mode::Lnk(())) => Ok(InodeMode::Lnk), + Ok(metadata_capnp::inode::mode::Sock(())) => Ok(InodeMode::Sock), + Ok(metadata_capnp::inode::mode::Wht(())) => Ok(InodeMode::Wht), + Ok(metadata_capnp::inode::mode::Chr(reader)) => { + let r = reader?; + Ok(InodeMode::Chr { + major: r.get_major(), + minor: r.get_minor(), + }) + } + Ok(metadata_capnp::inode::mode::Blk(reader)) => { + let r = reader?; + Ok(InodeMode::Blk { + major: r.get_major(), + minor: r.get_minor(), + }) + } + Ok(metadata_capnp::inode::mode::File(reader)) => { + let r = reader?; + let mut chunks = Vec::new(); + for chunk in r.iter() { + chunks.push(FileChunk::from_capnp(chunk)?, GFP_KERNEL)?; + } + + Ok(InodeMode::File { chunks }) + } + Ok(metadata_capnp::inode::mode::Dir(reader)) => { + let r = reader?; + let mut entries = Vec::new(); + for entry in r.get_entries()?.iter() { + let ino = entry.get_ino(); + let dir_entry = + Vec::from_iter_fallible(entry.get_name()?.iter().cloned(), GFP_KERNEL)?; + entries.push( + DirEnt { + ino, + name: dir_entry, + }, + GFP_KERNEL, + )?; + } + let look_below = r.get_look_below(); + Ok(InodeMode::Dir { + dir_list: DirList { + look_below, + entries, + }, + }) + } + Err(::capnp::NotInSchema(_e)) => Err(WireFormatError::InvalidSerializedData), + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct InodeAdditional { + pub(crate) xattrs: Vec, + pub(crate) symlink_target: Option>, +} + +impl InodeAdditional { + pub(crate) fn from_capnp( + reader: metadata_capnp::inode_additional::Reader<'_>, + ) -> Result> { + if !(reader.has_xattrs() || reader.has_symlink_target()) { + return Ok(None); + } + + let mut xattrs = Vec::new(); + if reader.has_xattrs() { + for capnp_xattr in reader.get_xattrs()? { + let xattr = Xattr::from_capnp(capnp_xattr)?; + xattrs.push(xattr, GFP_KERNEL)?; + } + } + + let symlink_target = if reader.has_symlink_target() { + Some(Vec::from_iter_fallible( + reader.get_symlink_target()?.iter().cloned(), + GFP_KERNEL, + )?) + } else { + None + }; + + Ok(Some(InodeAdditional { + xattrs, + symlink_target, + })) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct Xattr { + pub(crate) key: Vec, + pub(crate) val: Vec, +} + +impl Xattr { + pub(crate) fn from_capnp(reader: metadata_capnp::xattr::Reader<'_>) -> Result { + let key = Vec::from_iter_fallible(reader.get_key()?.iter().cloned(), GFP_KERNEL)?; + let val = Vec::from_iter_fallible(reader.get_val()?.iter().cloned(), GFP_KERNEL)?; + Ok(Xattr { key, val }) + } +} + +pub(crate) struct MetadataBlob { + reader: message::TypedReader< + ::capnp::serialize::NoAllocBufferSegments>, + metadata_capnp::inode_vector::Owned, + >, +} + +impl MetadataBlob { + pub(crate) fn new(f: file::RegularFile) -> Result { + // We know the loaded message is safe, so we're allowing unlimited reads. + let unlimited_reads = message::ReaderOptions { + traversal_limit_in_words: None, + nesting_limit: 64, + }; + let metadata_buffer = f.read_to_end()?; + let segments = ::capnp::serialize::NoAllocBufferSegments::from_buffer( + metadata_buffer, + unlimited_reads, + )?; + let reader = message::Reader::new(segments, unlimited_reads).into_typed(); + + Ok(MetadataBlob { reader }) + } + + pub(crate) fn get_inode_vector( + &self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'_, metadata_capnp::inode::Owned>> { + self.reader.get()?.get_inodes() + } + + pub(crate) fn find_inode(&self, ino: Ino) -> Result>> { + let mut left = 0; + let inodes = self.get_inode_vector()?; + let mut right = inodes.len() - 1; + + while left <= right { + let mid = left + (right - left) / 2; + let i = inodes.get(mid); + + if i.get_ino() == ino { + return Ok(Some(i)); + } + + if i.get_ino() < ino { + left = mid + 1; + } else { + // don't underflow... + if mid == 0 { + break; + } + right = mid - 1; + }; + } + + Ok(None) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct Digest([u8; SHA256_BLOCK_SIZE]); + +impl Digest { + pub(crate) fn underlying(&self) -> [u8; SHA256_BLOCK_SIZE] { + let mut dest = [0_u8; SHA256_BLOCK_SIZE]; + dest.copy_from_slice(&self.0); + dest + } +} + +impl fmt::Display for Digest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut hex_string = + Vec::from_iter_fallible(encode_hex_iter(&self.underlying()), GFP_KERNEL) + .map_err(|_| fmt::Error)?; + // append NUL character + hex_string.push(0, GFP_KERNEL).map_err(|_| fmt::Error)?; + let hex_string = CStr::from_bytes_with_nul(&hex_string).map_err(|_| fmt::Error)?; + write!(f, "{}", hex_string) + } +} + +impl TryFrom<&CStr> for Digest { + type Error = FromHexError; + fn try_from(s: &CStr) -> kernel::error::Result { + let mut digest: [u8; SHA256_BLOCK_SIZE] = [0; SHA256_BLOCK_SIZE]; + hex::decode_to_slice(s.as_bytes(), &mut digest)?; + Ok(Digest(digest)) + } +} + +impl TryFrom for Digest { + type Error = WireFormatError; + fn try_from(v: BlobRef) -> kernel::error::Result { + Ok(Digest(v.digest)) + } +} + +impl TryFrom<&BlobRef> for Digest { + type Error = WireFormatError; + fn try_from(v: &BlobRef) -> kernel::error::Result { + Ok(Digest(v.digest)) + } +} diff --git a/fs/puzzlefs/puzzle/types/manifest.capnp b/fs/puzzlefs/puzzle/types/manifest.capnp new file mode 100644 index 000000000000..24d8a6f1fe19 --- /dev/null +++ b/fs/puzzlefs/puzzle/types/manifest.capnp @@ -0,0 +1,15 @@ +@0xe0b6d460b1f22bb5; + +using Metadata = import "metadata.capnp"; + +struct VerityData { + digest@0: Data; + verity@1: Data; +} + +struct Rootfs { + metadatas@0: List(Metadata.BlobRef); + fsVerityData@1: List(VerityData); + manifestVersion@2: UInt64; +} + diff --git a/fs/puzzlefs/puzzle/types/manifest_capnp.rs b/fs/puzzlefs/puzzle/types/manifest_capnp.rs new file mode 100644 index 000000000000..721765c095bd --- /dev/null +++ b/fs/puzzlefs/puzzle/types/manifest_capnp.rs @@ -0,0 +1,757 @@ +// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. +// DO NOT EDIT. +// source: manifest.capnp + +#![allow(unreachable_pub)] +#![allow(dead_code)] + +pub mod verity_data { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_digest(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_digest(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_verity(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_verity(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 2, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_digest(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_digest(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_digest(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_digest(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_verity(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_verity(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(1).set_data(value); + } + #[inline] + pub fn init_verity(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(1).init_data(size) + } + #[inline] + pub fn has_verity(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 48] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(255, 223, 52, 143, 102, 148, 140, 205), + ::capnp::word(15, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(181, 43, 242, 177, 96, 212, 182, 224), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 97, 110, 105, 102, 101, 115, 116), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 86), + ::capnp::word(101, 114, 105, 116, 121, 68, 97, 116), + ::capnp::word(97, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(100, 105, 103, 101, 115, 116, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(118, 101, 114, 105, 116, 121, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xcd8c_9466_8f34_dfff; + } +} + +pub mod rootfs { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_metadatas( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::metadata_capnp::blob_ref::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_metadatas(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_fs_verity_data( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Reader<'a, crate::manifest_capnp::verity_data::Owned>, + > { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_fs_verity_data(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + #[inline] + pub fn get_manifest_version(self) -> u64 { + self.reader.get_data_field::(0) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 1, + pointers: 2, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_metadatas( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Builder<'a, crate::metadata_capnp::blob_ref::Owned>, + > { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_metadatas( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::metadata_capnp::blob_ref::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_metadatas( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::metadata_capnp::blob_ref::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_metadatas(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_fs_verity_data( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Builder<'a, crate::manifest_capnp::verity_data::Owned>, + > { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_fs_verity_data( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::manifest_capnp::verity_data::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_fs_verity_data( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::manifest_capnp::verity_data::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(1), + size, + ) + } + #[inline] + pub fn has_fs_verity_data(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + #[inline] + pub fn get_manifest_version(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_manifest_version(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 73] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(216, 230, 154, 208, 49, 166, 59, 237), + ::capnp::word(15, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(181, 43, 242, 177, 96, 212, 182, 224), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 175, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 97, 110, 105, 102, 101, 115, 116), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 82), + ::capnp::word(111, 111, 116, 102, 115, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(12, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(69, 0, 0, 0, 82, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(68, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(96, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(93, 0, 0, 0, 106, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(92, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(120, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(2, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(117, 0, 0, 0, 130, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(116, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(128, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(115, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(70, 64, 38, 97, 160, 43, 222, 175), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(102, 115, 86, 101, 114, 105, 116, 121), + ::capnp::word(68, 97, 116, 97, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(255, 223, 52, 143, 102, 148, 140, 205), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 97, 110, 105, 102, 101, 115, 116), + ::capnp::word(86, 101, 114, 115, 105, 111, 110, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 2 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xed3b_a631_d09a_e6d8; + } +} diff --git a/fs/puzzlefs/puzzle/types/metadata.capnp b/fs/puzzlefs/puzzle/types/metadata.capnp new file mode 100644 index 000000000000..0a2d6c174dad --- /dev/null +++ b/fs/puzzlefs/puzzle/types/metadata.capnp @@ -0,0 +1,65 @@ +@0x84ae5e6e88b7cbb7; + +struct Chr { + major@0: UInt64; + minor@1: UInt64; +} + +struct DirEntry { + ino@0: UInt64; + name@1: Data; +} + +struct Dir { + entries@0: List(DirEntry); + lookBelow@1: Bool; +} + +struct Blk { + major@0: UInt64; + minor@1: UInt64; +} + +struct FileChunk { + blob@0: BlobRef; + len@1: UInt64; +} + +struct BlobRef { + digest@0: Data; + offset@1: UInt64; + compressed@2: Bool; +} + +struct Xattr { + key@0: Data; + val@1: Data; +} + +struct InodeAdditional { + xattrs@0: List(Xattr); + symlinkTarget@1: Data; +} + +struct Inode { + ino@0: UInt64; + mode: union { + unknown@1: Void; + fifo@2: Void; + chr@3: Chr; + dir@4: Dir; + blk@5: Blk; + file@6: List(FileChunk); + lnk@7: Void; + sock@8: Void; + wht@9: Void; + } + uid@10: UInt32; + gid@11: UInt32; + permissions@12: UInt16; + additional@13: InodeAdditional; +} + +struct InodeVector { + inodes@0: List(Inode); +} diff --git a/fs/puzzlefs/puzzle/types/metadata_capnp.rs b/fs/puzzlefs/puzzle/types/metadata_capnp.rs new file mode 100644 index 000000000000..e89a8feb6093 --- /dev/null +++ b/fs/puzzlefs/puzzle/types/metadata_capnp.rs @@ -0,0 +1,4049 @@ +// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. +// DO NOT EDIT. +// source: metadata.capnp + +#![allow(unreachable_pub)] + +pub mod chr { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_major(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_minor(self) -> u64 { + self.reader.get_data_field::(1) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 2, + pointers: 0, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_major(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_major(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_minor(self) -> u64 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_minor(&mut self, value: u64) { + self.builder.set_data_field::(1, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 47] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(112, 90, 179, 204, 206, 228, 254, 162), + ::capnp::word(15, 0, 0, 0, 1, 0, 2, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 154, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 67), + ::capnp::word(104, 114, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(109, 97, 106, 111, 114, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 105, 110, 111, 114, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xa2fe_e4ce_ccb3_5a70; + } +} + +pub mod dir_entry { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_ino(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 1, + pointers: 1, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_ino(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_ino(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 47] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(229, 236, 93, 69, 176, 175, 227, 153), + ::capnp::word(15, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 194, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 68), + ::capnp::word(105, 114, 69, 110, 116, 114, 121, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(105, 110, 111, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => ::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x99e3_afb0_455d_ece5; + } +} + +pub mod dir { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_entries( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Reader<'a, crate::metadata_capnp::dir_entry::Owned>, + > { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_entries(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_look_below(self) -> bool { + self.reader.get_bool_field(0) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 1, + pointers: 1, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_entries( + self, + ) -> ::capnp::Result< + ::capnp::struct_list::Builder<'a, crate::metadata_capnp::dir_entry::Owned>, + > { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_entries( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::metadata_capnp::dir_entry::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_entries( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::metadata_capnp::dir_entry::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_entries(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_look_below(self) -> bool { + self.builder.get_bool_field(0) + } + #[inline] + pub fn set_look_below(&mut self, value: bool) { + self.builder.set_bool_field(0, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 52] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(4, 150, 39, 131, 249, 197, 58, 163), + ::capnp::word(15, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 154, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 68), + ::capnp::word(105, 114, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 66, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(64, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(61, 0, 0, 0, 82, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(60, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(72, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(101, 110, 116, 114, 105, 101, 115, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(229, 236, 93, 69, 176, 175, 227, 153), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(108, 111, 111, 107, 66, 101, 108, 111), + ::capnp::word(119, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xa33a_c5f9_8327_9604; + } +} + +pub mod blk { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_major(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_minor(self) -> u64 { + self.reader.get_data_field::(1) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 2, + pointers: 0, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_major(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_major(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_minor(self) -> u64 { + self.builder.get_data_field::(1) + } + #[inline] + pub fn set_minor(&mut self, value: u64) { + self.builder.set_data_field::(1, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 47] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(105, 137, 149, 129, 43, 27, 209, 242), + ::capnp::word(15, 0, 0, 0, 1, 0, 2, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 154, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 66), + ::capnp::word(108, 107, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(109, 97, 106, 111, 114, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 105, 110, 111, 114, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xf2d1_1b2b_8195_8969; + } +} + +pub mod file_chunk { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_blob(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_blob(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_len(self) -> u64 { + self.reader.get_data_field::(0) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 1, + pointers: 1, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_blob(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_blob( + &mut self, + value: crate::metadata_capnp::blob_ref::Reader<'_>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_blob(self) -> crate::metadata_capnp::blob_ref::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + #[inline] + pub fn has_blob(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_len(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_len(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_blob(&self) -> crate::metadata_capnp::blob_ref::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) + } + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 48] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(210, 21, 210, 230, 255, 156, 237, 140), + ::capnp::word(15, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 202, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 70), + ::capnp::word(105, 108, 101, 67, 104, 117, 110, 107), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(98, 108, 111, 98, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(70, 64, 38, 97, 160, 43, 222, 175), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(108, 101, 110, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x8ced_9cff_e6d2_15d2; + } +} + +pub mod blob_ref { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_digest(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_digest(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_offset(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_compressed(self) -> bool { + self.reader.get_bool_field(64) + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 2, + pointers: 1, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_digest(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_digest(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_digest(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_digest(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_offset(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_offset(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_compressed(self) -> bool { + self.builder.get_bool_field(64) + } + #[inline] + pub fn set_compressed(&mut self, value: bool) { + self.builder.set_bool_field(64, value); + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 63] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(70, 64, 38, 97, 160, 43, 222, 175), + ::capnp::word(15, 0, 0, 0, 1, 0, 2, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 186, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 175, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 66), + ::capnp::word(108, 111, 98, 82, 101, 102, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(12, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(69, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(64, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(76, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(73, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(68, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(80, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(2, 0, 0, 0, 64, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(77, 0, 0, 0, 90, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(76, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(88, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(100, 105, 103, 101, 115, 116, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(111, 102, 102, 115, 101, 116, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(99, 111, 109, 112, 114, 101, 115, 115), + ::capnp::word(101, 100, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xafde_2ba0_6126_4046; + } +} + +pub mod xattr { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_key(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_key(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_val(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_val(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 2, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_key(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_key(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_key(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_key(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_val(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_val(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(1).set_data(value); + } + #[inline] + pub fn init_val(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(1).init_data(size) + } + #[inline] + pub fn has_val(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 47] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(64, 205, 159, 7, 194, 75, 43, 217), + ::capnp::word(15, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 170, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 88), + ::capnp::word(97, 116, 116, 114, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(107, 101, 121, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(118, 97, 108, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xd92b_4bc2_079f_cd40; + } +} + +pub mod inode_additional { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_xattrs( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::metadata_capnp::xattr::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_xattrs(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_symlink_target(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_symlink_target(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 2, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_xattrs( + self, + ) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::metadata_capnp::xattr::Owned>> + { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_xattrs( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::metadata_capnp::xattr::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_xattrs( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::metadata_capnp::xattr::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_xattrs(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_symlink_target(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_symlink_target(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(1).set_data(value); + } + #[inline] + pub fn init_symlink_target(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(1).init_data(size) + } + #[inline] + pub fn has_symlink_target(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 53] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(211, 144, 125, 86, 42, 166, 175, 153), + ::capnp::word(15, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 73), + ::capnp::word(110, 111, 100, 101, 65, 100, 100, 105), + ::capnp::word(116, 105, 111, 110, 97, 108, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(64, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(61, 0, 0, 0, 114, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(60, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(72, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(120, 97, 116, 116, 114, 115, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(64, 205, 159, 7, 194, 75, 43, 217), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(115, 121, 109, 108, 105, 110, 107, 84), + ::capnp::word(97, 114, 103, 101, 116, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0x99af_a62a_567d_90d3; + } +} + +pub mod inode { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_ino(self) -> u64 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_mode(self) -> crate::metadata_capnp::inode::mode::Reader<'a> { + self.reader.into() + } + #[inline] + pub fn get_uid(self) -> u32 { + self.reader.get_data_field::(3) + } + #[inline] + pub fn get_gid(self) -> u32 { + self.reader.get_data_field::(4) + } + #[inline] + pub fn get_permissions(self) -> u16 { + self.reader.get_data_field::(5) + } + #[inline] + pub fn get_additional( + self, + ) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_additional(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 3, + pointers: 2, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_ino(self) -> u64 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_ino(&mut self, value: u64) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_mode(self) -> crate::metadata_capnp::inode::mode::Builder<'a> { + self.builder.into() + } + #[inline] + pub fn init_mode(mut self) -> crate::metadata_capnp::inode::mode::Builder<'a> { + self.builder.set_data_field::(4, 0); + self.builder.reborrow().get_pointer_field(0).clear(); + self.builder.into() + } + #[inline] + pub fn get_uid(self) -> u32 { + self.builder.get_data_field::(3) + } + #[inline] + pub fn set_uid(&mut self, value: u32) { + self.builder.set_data_field::(3, value); + } + #[inline] + pub fn get_gid(self) -> u32 { + self.builder.get_data_field::(4) + } + #[inline] + pub fn set_gid(&mut self, value: u32) { + self.builder.set_data_field::(4, value); + } + #[inline] + pub fn get_permissions(self) -> u16 { + self.builder.get_data_field::(5) + } + #[inline] + pub fn set_permissions(&mut self, value: u16) { + self.builder.set_data_field::(5, value); + } + #[inline] + pub fn get_additional( + self, + ) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_additional( + &mut self, + value: crate::metadata_capnp::inode_additional::Reader<'_>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_additional(self) -> crate::metadata_capnp::inode_additional::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) + } + #[inline] + pub fn has_additional(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_mode(&self) -> crate::metadata_capnp::inode::mode::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.noop()) + } + pub fn get_additional(&self) -> crate::metadata_capnp::inode_additional::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 102] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(161, 114, 128, 2, 173, 206, 117, 185), + ::capnp::word(15, 0, 0, 0, 1, 0, 3, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 170, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 87, 1, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 73), + ::capnp::word(110, 111, 100, 101, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(24, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(153, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(148, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(160, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(54, 46, 90, 92, 135, 239, 140, 194), + ::capnp::word(157, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(2, 0, 0, 0, 3, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 10, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(133, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(128, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(140, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(3, 0, 0, 0, 4, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 11, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(137, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(132, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(144, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(4, 0, 0, 0, 5, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 12, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(141, 0, 0, 0, 98, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(140, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(152, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(5, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 13, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(149, 0, 0, 0, 90, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(148, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(160, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(105, 110, 111, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 111, 100, 101, 0, 0, 0, 0), + ::capnp::word(117, 105, 100, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(103, 105, 100, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(112, 101, 114, 109, 105, 115, 115, 105), + ::capnp::word(111, 110, 115, 0, 0, 0, 0, 0), + ::capnp::word(7, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(7, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(97, 100, 100, 105, 116, 105, 111, 110), + ::capnp::word(97, 108, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(211, 144, 125, 86, 42, 166, 175, 153), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => ::introspect(), + 5 => ::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1, 2, 3, 4, 5]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xb975_cead_0280_72a1; + } + + pub mod mode { + pub use self::Which::{Blk, Chr, Dir, Fifo, File, Lnk, Sock, Unknown, Wht}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn has_chr(&self) -> bool { + if self.reader.get_data_field::(4) != 2 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_dir(&self) -> bool { + if self.reader.get_data_field::(4) != 3 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_blk(&self) -> bool { + if self.reader.get_data_field::(4) != 4 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_file(&self) -> bool { + if self.reader.get_data_field::(4) != 5 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Unknown(())), + 1 => ::core::result::Result::Ok(Fifo(())), + 2 => ::core::result::Result::Ok(Chr( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 3 => ::core::result::Result::Ok(Dir( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 4 => ::core::result::Result::Ok(Blk( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(File( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 6 => ::core::result::Result::Ok(Lnk(())), + 7 => ::core::result::Result::Ok(Sock(())), + 8 => ::core::result::Result::Ok(Wht(())), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 3, + pointers: 2, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_unknown(&mut self, _value: ()) { + self.builder.set_data_field::(4, 0); + } + #[inline] + pub fn set_fifo(&mut self, _value: ()) { + self.builder.set_data_field::(4, 1); + } + #[inline] + pub fn set_chr( + &mut self, + value: crate::metadata_capnp::chr::Reader<'_>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(4, 2); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_chr(self) -> crate::metadata_capnp::chr::Builder<'a> { + self.builder.set_data_field::(4, 2); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_chr(&self) -> bool { + if self.builder.get_data_field::(4) != 2 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_dir( + &mut self, + value: crate::metadata_capnp::dir::Reader<'_>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(4, 3); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_dir(self) -> crate::metadata_capnp::dir::Builder<'a> { + self.builder.set_data_field::(4, 3); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_dir(&self) -> bool { + if self.builder.get_data_field::(4) != 3 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_blk( + &mut self, + value: crate::metadata_capnp::blk::Reader<'_>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(4, 4); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_blk(self) -> crate::metadata_capnp::blk::Builder<'a> { + self.builder.set_data_field::(4, 4); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + 0, + ) + } + #[inline] + pub fn has_blk(&self) -> bool { + if self.builder.get_data_field::(4) != 4 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_file( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::metadata_capnp::file_chunk::Owned>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(4, 5); + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_file( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::metadata_capnp::file_chunk::Owned> + { + self.builder.set_data_field::(4, 5); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_file(&self) -> bool { + if self.builder.get_data_field::(4) != 5 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_lnk(&mut self, _value: ()) { + self.builder.set_data_field::(4, 6); + } + #[inline] + pub fn set_sock(&mut self, _value: ()) { + self.builder.set_data_field::(4, 7); + } + #[inline] + pub fn set_wht(&mut self, _value: ()) { + self.builder.set_data_field::(4, 8); + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(4) { + 0 => ::core::result::Result::Ok(Unknown(())), + 1 => ::core::result::Result::Ok(Fifo(())), + 2 => ::core::result::Result::Ok(Chr( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 3 => ::core::result::Result::Ok(Dir( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 4 => ::core::result::Result::Ok(Blk( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(File( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 6 => ::core::result::Result::Ok(Lnk(())), + 7 => ::core::result::Result::Ok(Sock(())), + 8 => ::core::result::Result::Ok(Wht(())), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 156] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(54, 46, 90, 92, 135, 239, 140, 194), + ::capnp::word(21, 0, 0, 0, 1, 0, 3, 0), + ::capnp::word(161, 114, 128, 2, 173, 206, 117, 185), + ::capnp::word(2, 0, 7, 0, 1, 0, 9, 0), + ::capnp::word(4, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 255, 1, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 73), + ::capnp::word(110, 111, 100, 101, 46, 109, 111, 100), + ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 255, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(237, 0, 0, 0, 66, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(232, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(244, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 254, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(241, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(236, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(248, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(2, 0, 253, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 3, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(245, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(240, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(252, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(3, 0, 252, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 4, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(249, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(244, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(0, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(4, 0, 251, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 5, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(253, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(248, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(4, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(5, 0, 250, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 6, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 1, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(252, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(24, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(6, 0, 249, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 1, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(28, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(7, 0, 248, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 8, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 1, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(20, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(32, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(8, 0, 247, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 9, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 1, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(24, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(36, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(117, 110, 107, 110, 111, 119, 110, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(102, 105, 102, 111, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(99, 104, 114, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(112, 90, 179, 204, 206, 228, 254, 162), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(100, 105, 114, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(4, 150, 39, 131, 249, 197, 58, 163), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(98, 108, 107, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(105, 137, 149, 129, 43, 27, 209, 242), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(102, 105, 108, 101, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(210, 21, 210, 230, 255, 156, 237, 140), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(108, 110, 107, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(115, 111, 99, 107, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(119, 104, 116, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <() as ::capnp::introspect::Introspect>::introspect(), + 1 => <() as ::capnp::introspect::Introspect>::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => ::introspect(), + 5 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 6 => <() as ::capnp::introspect::Introspect>::introspect(), + 7 => <() as ::capnp::introspect::Introspect>::introspect(), + 8 => <() as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; + pub const TYPE_ID: u64 = 0xc28c_ef87_5c5a_2e36; + } + pub enum Which { + Unknown(()), + Fifo(()), + Chr(A0), + Dir(A1), + Blk(A2), + File(A3), + Lnk(()), + Sock(()), + Wht(()), + } + pub type WhichReader<'a> = Which< + ::capnp::Result>, + ::capnp::Result>, + ::capnp::Result>, + ::capnp::Result< + ::capnp::struct_list::Reader<'a, crate::metadata_capnp::file_chunk::Owned>, + >, + >; + pub type WhichBuilder<'a> = Which< + ::capnp::Result>, + ::capnp::Result>, + ::capnp::Result>, + ::capnp::Result< + ::capnp::struct_list::Builder<'a, crate::metadata_capnp::file_chunk::Owned>, + >, + >; + } +} + +pub mod inode_vector { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl<'a> ::core::marker::Copy for Reader<'a> {} + impl<'a> ::core::clone::Clone for Reader<'a> { + fn clone(&self) -> Self { + *self + } + } + + impl<'a> ::capnp::traits::HasTypeId for Reader<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::core::fmt::Debug for Reader<'a> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_inodes( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::metadata_capnp::inode::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_inodes(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl<'a> ::capnp::traits::HasStructSize for Builder<'a> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 1, + }; + } + impl<'a> ::capnp::traits::HasTypeId for Builder<'a> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl<'a> ::capnp::traits::SetPointerBuilder for Reader<'a> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_inodes( + self, + ) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::metadata_capnp::inode::Owned>> + { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_inodes( + &mut self, + value: ::capnp::struct_list::Reader<'a, crate::metadata_capnp::inode::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetPointerBuilder::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_inodes( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::metadata_capnp::inode::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_inodes(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 37] = [ + ::capnp::word(0, 0, 0, 0, 5, 0, 6, 0), + ::capnp::word(35, 20, 59, 240, 58, 227, 99, 162), + ::capnp::word(15, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(183, 203, 183, 136, 110, 94, 174, 132), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 218, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 63, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(109, 101, 116, 97, 100, 97, 116, 97), + ::capnp::word(46, 99, 97, 112, 110, 112, 58, 73), + ::capnp::word(110, 111, 100, 101, 86, 101, 99, 116), + ::capnp::word(111, 114, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(4, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(36, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(105, 110, 111, 100, 101, 115, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(161, 114, 128, 2, 173, 206, 117, 185), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + panic!("invalid annotation indices ({:?}, {}) ", child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub const TYPE_ID: u64 = 0xa263_e33a_f03b_1423; + } +} diff --git a/fs/puzzlefs/puzzlefs.rs b/fs/puzzlefs/puzzlefs.rs new file mode 100644 index 000000000000..a062bf0249f6 --- /dev/null +++ b/fs/puzzlefs/puzzlefs.rs @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! PuzzleFS, a next-generation container filesystem. + +use kernel::fs::{ + address_space, dentry, dentry::DEntry, file, file::DirEntryType, file::File, inode, + inode::INode, sb, Offset, +}; +use kernel::prelude::*; +use kernel::types::{ARef, Either, Locked}; +use kernel::{c_str, folio::Folio, folio::PageCache, fs, str::CString, time::UNIX_EPOCH, user}; +mod puzzle; +use crate::puzzle::inode::{file_read, PuzzleFS}; +use crate::puzzle::types::{DirEnt, Inode, InodeMode}; +// Required by the autogenerated '_capnp.rs' files +use puzzle::{manifest_capnp, metadata_capnp}; + +kernel::module_fs! { + type: PuzzleFsModule, + name: "PuzzleFS", + author: "Ariel Miculas", + description: "A next-generation container filesystem", + license: "GPL", +} + +fn mode_to_fs_type(inode: &Inode) -> Result { + Ok(match inode.mode { + InodeMode::File { .. } => DirEntryType::Reg, + InodeMode::Dir { .. } => DirEntryType::Dir, + InodeMode::Fifo { .. } => DirEntryType::Fifo, + InodeMode::Chr { .. } => DirEntryType::Chr, + InodeMode::Blk { .. } => DirEntryType::Blk, + InodeMode::Lnk { .. } => DirEntryType::Lnk, + InodeMode::Sock { .. } => DirEntryType::Sock, + _ => return Err(EINVAL), + }) +} + +const DIR_FOPS: file::Ops = file::Ops::new::(); +const DIR_IOPS: inode::Ops = inode::Ops::new::(); +const FILE_AOPS: address_space::Ops = address_space::Ops::new::(); + +struct PuzzleFsModule; + +impl PuzzleFsModule { + fn iget(sb: &sb::SuperBlock, ino: u64) -> Result>> { + let mut new = match sb.get_or_create_inode(ino)? { + Either::Left(existing) => return Ok(existing), + Either::Right(new) => new, + }; + + let puzzlefs = sb.data(); + let inode = puzzlefs.find_inode(ino)?; + + let (nlink, typ) = match inode.mode { + InodeMode::Dir { .. } => { + new.set_iops(DIR_IOPS).set_fops(DIR_FOPS); + (2, inode::Type::Dir) + } + InodeMode::File { .. } => { + new.set_fops(file::Ops::generic_ro_file()) + .set_aops(FILE_AOPS); + (1, inode::Type::Reg) + } + InodeMode::Lnk { .. } => { + new.set_iops(inode::Ops::simple_symlink_inode()); + let target = inode + .additional + .as_ref() + .ok_or(ENODATA)? + .symlink_target + .as_ref() + .ok_or(ENODATA)?; + ( + 1, + inode::Type::Lnk(Some(CString::try_from(target.as_slice())?)), + ) + } + _ => return Err(ENOENT), + }; + + let size = inode.size()?; + + new.init(inode::Params { + typ, + mode: inode.permissions, + size, + blocks: (u64::try_from(size)? + 511) / 512, + nlink, + uid: inode.uid, + gid: inode.gid, + atime: UNIX_EPOCH, + ctime: UNIX_EPOCH, + mtime: UNIX_EPOCH, + value: inode, + }) + } +} + +impl fs::FileSystem for PuzzleFsModule { + type Data = Box; + type INodeData = Inode; + const NAME: &'static CStr = c_str!("puzzlefs"); + + fn fill_super( + sb: &mut sb::SuperBlock, + _: Option, + ) -> Result> { + let puzzlefs = PuzzleFS::open( + c_str!("/home/puzzlefs_oci"), + c_str!("83aa96c40a20671edc4490cfefadbb487b2ab23dfc0570049b56f0cc49b56eaf"), + ); + + if let Err(ref e) = puzzlefs { + pr_info!("error opening puzzlefs {e}\n"); + } + + let puzzlefs = puzzlefs?; + sb.set_magic(0x7a7a7570); + Ok(Box::new(puzzlefs, GFP_KERNEL)?) + } + + fn init_root(sb: &sb::SuperBlock) -> Result> { + let inode = Self::iget(sb, 1)?; + dentry::Root::try_new(inode) + } +} + +#[vtable] +impl inode::Operations for PuzzleFsModule { + type FileSystem = Self; + + fn lookup( + parent: &Locked<&INode, inode::ReadSem>, + dentry: dentry::Unhashed<'_, Self>, + ) -> Result>>> { + let name = dentry.name(); + if let Ok(ino) = parent.data().dir_lookup(name) { + let inode = Self::iget(parent.super_block(), ino)?; + dentry.splice_alias(Some(inode)) + } else { + dentry.splice_alias(None) + } + } + + fn get_link<'a>( + dentry: Option<&DEntry>, + inode: &'a INode, + ) -> Result> { + if dentry.is_none() { + return Err(ECHILD); + } + + let name_buf = inode + .data() + .additional + .as_ref() + .ok_or(ENODATA)? + .symlink_target + .as_ref() + .ok_or(ENODATA)?; + let mut name = Box::new_slice( + name_buf.len().checked_add(1).ok_or(ENOMEM)?, + b'\0', + GFP_KERNEL, + )?; + name[..name_buf.len()].copy_from_slice(&name_buf); + Ok(Either::Left(name.try_into()?)) + } +} + +#[vtable] +impl address_space::Operations for PuzzleFsModule { + type FileSystem = Self; + + fn read_folio(_: Option<&File>, mut folio: Locked<&Folio>>) -> Result { + let puzzlefs = folio.inode().super_block().data(); + let inode = folio.inode().data(); + let mut buf = Vec::with_capacity(folio.size(), GFP_KERNEL)?; + buf.resize(folio.size(), 0, GFP_KERNEL)?; + let offset = usize::try_from(folio.pos()).unwrap_or(usize::MAX); + let nr_bytes_read = file_read(&puzzlefs.oci, inode, offset, &mut buf)?; + buf.truncate(nr_bytes_read); + + folio.write(0, &buf[..])?; + folio.zero_out(nr_bytes_read, folio.size() - nr_bytes_read)?; + folio.mark_uptodate(); + folio.flush_dcache(); + + Ok(()) + } +} + +#[vtable] +impl file::Operations for PuzzleFsModule { + type FileSystem = Self; + + fn seek(file: &File, offset: Offset, whence: file::Whence) -> Result { + file::generic_seek(file, offset, whence) + } + + fn read(_: &File, _: &mut user::Writer, _: &mut Offset) -> Result { + Err(EISDIR) + } + + fn read_dir( + _file: &File, + inode: &Locked<&INode, inode::ReadSem>, + emitter: &mut file::DirEmitter, + ) -> Result { + let puzzlefs = inode.super_block().data(); + let inode = inode.data(); + let entries = inode.dir_entries()?; + + for DirEnt { name, ino: ino_r } in entries.iter().skip(emitter.pos().try_into()?) { + let ino = *ino_r; + let inode = puzzlefs.find_inode(ino)?; + let kind = mode_to_fs_type(&inode)?; + + if !emitter.emit(1, name, ino, kind) { + return Ok(()); + } + } + + Ok(()) + } +} diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 3cf916bc884f..f8c9aa485844 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -100,7 +100,7 @@ impl Error { /// /// It is a bug to pass an out-of-range `errno`. `EINVAL` would /// be returned in such a case. - pub(crate) fn from_errno(errno: core::ffi::c_int) -> Error { + pub fn from_errno(errno: core::ffi::c_int) -> Error { if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 { // TODO: Make it a `WARN_ONCE` once available. crate::pr_warn!( From patchwork Thu May 16 19:03:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666476 Received: from aer-iport-4.cisco.com (aer-iport-4.cisco.com [173.38.203.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F39C5156F29; Thu, 16 May 2024 19:04:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886263; cv=none; b=ngVcwjV8uUEcAvdUUzhP+kU2fvBgkvvoj/dOzaO+DsSssmgHf7RLlvP6fE+gljTtVpPySn3uaiFNGXdCF6yaaI6M4FF8zkKfw1i7sBHfryEyEsIaQcVwaRQ7u2xEcpFY89g4AZFiQs6PNwnAxbf50fnShvOukJ8FrDi2i3BHNF4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886263; c=relaxed/simple; bh=0lJ0FxB1P4rcK9zFSRBA5T+g6CrZ0Gf7SJqvtne45QA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Y0YChVzG+7YlkB/RruhQ8P4zdQh/8NLtREtAVi72qcclgvJyF0DQxfJwiU+POYC1N1uKoNa9SjKdfu6M3egmyGjppE/rZpVTh+ZoTBff+fr49kHSjQWmeuhrGervMP+FUOHRHpvZpPH1E3VuAxR0Ko+TqoA96COFPOhMzXkuoeI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=Y45+4JjE; arc=none smtp.client-ip=173.38.203.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="Y45+4JjE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=967; q=dns/txt; s=iport; t=1715886261; x=1717095861; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RM2bpcKeFIOuwJsUXBWZw4CVFhC5QI3+qCCBvqPUBZo=; b=Y45+4JjEVPEgetC8nH5A6haMkizYINtaHu4gEwAurckM5okiDt6f9MGX 4hSirA1iB/qHoK8jYHnArjafGhS2YfzS2/jNhdcMHaMUhJUYcJf2b9jy0 VN0SHSofetW/JSq62Ycf6VFXjHDhFkSNn2hdeKmGh/+mXdEY1ytVaH8yp Q=; X-CSE-ConnectionGUID: MAYFYa3ZSRKzGDsl4DkK+w== X-CSE-MsgGUID: XZR3mbPyTBmG61iWLKTEaQ== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12379874" Received: from aer-iport-nat.cisco.com (HELO aer-core-11.cisco.com) ([173.38.203.22]) by aer-iport-4.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:19 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-11.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4IDD020825 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:18 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 14/22] rust: kernel: add from_iter_fallible for Vec Date: Thu, 16 May 2024 22:03:37 +0300 Message-Id: <20240516190345.957477-15-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-11.cisco.com This function takes an iterator and creates a new vector with its elements. It is used in multiple places in the PuzzleFS code. Signed-off-by: Ariel Miculas --- rust/kernel/alloc/vec_ext.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/kernel/alloc/vec_ext.rs b/rust/kernel/alloc/vec_ext.rs index 6ad0b6da45d3..cbc8b06183d7 100644 --- a/rust/kernel/alloc/vec_ext.rs +++ b/rust/kernel/alloc/vec_ext.rs @@ -132,6 +132,18 @@ fn resize(&mut self, new_len: usize, value: T, flags: Flags) -> Result<(), Alloc { self.resize_with(new_len, flags, || value.clone()) } + + /// See https://doc.rust-lang.org/std/vec/struct.Vec.html#examples-31 + fn from_iter_fallible( + iter: impl Iterator, + flags: Flags, + ) -> Result, AllocError> { + let mut vec = Vec::new(); + for value in iter { + vec.push(value, flags)?; + } + Ok(vec) + } } impl VecExt for Vec { From patchwork Thu May 16 19:03:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666478 Received: from aer-iport-1.cisco.com (aer-iport-1.cisco.com [173.38.203.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37B28157480; Thu, 16 May 2024 19:04:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886264; cv=none; b=HupLk2iJfs4J9LcoQFYpCctID/W/TKPW+pk/M7E7QX8rFVmXRTNmalwUTHzpvk2Kd2Yw8gkJ9uIx1J3/H+7bpsWLLkgM2pUvNtO+LWybs1yj7yh5RZ9Em3DNZxTY1nPuWMWzSEpfu9MERhqDs9hjzP2l1T2KBbF+Iq2eWXPP7Hk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886264; c=relaxed/simple; bh=RTfl/i6q2sPFKWcYzH7ngHYJOUucpLUhkTgs3xxTvDs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TQZ1R/xqQ61FqAdTWwVUfrLpsYLg3i/li0YPDOjFYTRrXeF8zjuv7JuX2FKMHBpWw9BjL5JcOJxfiaHMI/bzRDi/QdhhQRc0WPtpd4xf4j6n88MBtNir5CTKyvv5B2UFU/XaW1XlTIxXKJDbMe7HCWRXR8p8jGK6C43SO+NWHIw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=I7iR2ltH; arc=none smtp.client-ip=173.38.203.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="I7iR2ltH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=692; q=dns/txt; s=iport; t=1715886262; x=1717095862; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/+z83rjDMf0hIPuN0qCl5hLA1YJ/zJf3S1o0TXgJcNY=; b=I7iR2ltHtX4bog64OKtNwxhFfsNaxVYz9DqwMinVXtsph0UzKDv+bgCt DSgSWHmea3yWseTPbwLJVzTC0AHerHm/pfw1SgFTDsqGQISmCWKUCOm8a hRcBANgaiQPHJ5AV3tMw1yXm+AynnKyYda+SDiRdDr6eyZTxSSEG6syl+ g=; X-CSE-ConnectionGUID: ufl74RToTz6u0lT7JgbpbQ== X-CSE-MsgGUID: r2GFHIxEQvqCTWCAqW320A== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12419637" Received: from aer-iport-nat.cisco.com (HELO aer-core-12.cisco.com) ([173.38.203.22]) by aer-iport-1.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:20 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-12.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4J7Q100699 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:20 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 15/22] kernel: configs: add puzzlefs config fragment Date: Thu, 16 May 2024 22:03:38 +0300 Message-Id: <20240516190345.957477-16-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-12.cisco.com Add a config fragment for PuzzleFS for convenience. A minimal configuration which contains PuzzleFS can be generated by running: make LLVM=1 allnoconfig qemu-busybox-min.config puzzlefs.config Signed-off-by: Ariel Miculas --- kernel/configs/puzzlefs.config | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 kernel/configs/puzzlefs.config diff --git a/kernel/configs/puzzlefs.config b/kernel/configs/puzzlefs.config new file mode 100644 index 000000000000..e4fc4b4a9eac --- /dev/null +++ b/kernel/configs/puzzlefs.config @@ -0,0 +1,4 @@ +CONFIG_BUFFER_HEAD=y +CONFIG_RUST=y +CONFIG_MISC_FILESYSTEMS=y +CONFIG_PUZZLEFS_FS=y From patchwork Thu May 16 19:03:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666477 Received: from aer-iport-2.cisco.com (aer-iport-2.cisco.com [173.38.203.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B29E4156F53; Thu, 16 May 2024 19:04:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886264; cv=none; b=byYUHRtSoD8dkST+4SaXhdjazZY5WogJGt622yh/5EBPR5AhV/tjm7sH3270zox35G4ejfX5tlWEakneLOBJiOFRLlDlTO4GVsIchM3XTAEHRNvHpoSe/0q3lZxcxuji+DQOGLedZGq0h7Uz4qDO6pcAIOrG0+M3V4f9iTRnevs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886264; c=relaxed/simple; bh=3nnpWWKMStpUeM3Ik6Rv784yA2JQMowYJQgZdZU31uY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=g1NAI6NZKEUkqOKILqsk5IbJgT7JzDXVD9r8B8ilntgmkT464OLPiUQkMCw7KBeieJHhP9U8ZnoN4OCDi6JQk7g6YqwHLUPnrIui5jE30emQw0wb2zC1E/6oaaRqSXFx3PJlr19O8iHFYVc+kyLvlG/UviT1vc6LB/SrhowcBvk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=Gl/ORZvq; arc=none smtp.client-ip=173.38.203.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="Gl/ORZvq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=894; q=dns/txt; s=iport; t=1715886262; x=1717095862; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=L5yDgP+cxPTKmz+g24R6+/RadbYoww9Xk7B9o4e4exM=; b=Gl/ORZvqSstJ5aoCzJZG6jHLTVA7+35XPz7DlWoVkYHRA5+pwPIuFebK 4JfSCsaqiygbHLIPs2vdEWeL1TPcC0JVphcjkdCVr4BVnq8HPU/U164V1 F3nu1c4NZvJ970MeDaAyg3qUFYqp44luU3hAazkFAWw62M//HDNjZ1sjF 8=; X-CSE-ConnectionGUID: 3gwLQrPxT+2Tcptk91gRkA== X-CSE-MsgGUID: L99Lj4d9T0GlqFWcxSX9fw== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12416990" Received: from aer-iport-nat.cisco.com (HELO aer-core-1.cisco.com) ([173.38.203.22]) by aer-iport-2.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:21 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-1.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4KvF030203 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:21 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 16/22] scripts: add fs directory to rust-analyzer Date: Thu, 16 May 2024 22:03:39 +0300 Message-Id: <20240516190345.957477-17-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-1.cisco.com This enables the Rust code navigation features inside fs/, where PuzzleFS resides. Signed-off-by: Ariel Miculas --- scripts/generate_rust_analyzer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py index f270c7b0cf34..6985b9e37429 100755 --- a/scripts/generate_rust_analyzer.py +++ b/scripts/generate_rust_analyzer.py @@ -116,7 +116,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs): # Then, the rest outside of `rust/`. # # We explicitly mention the top-level folders we want to cover. - extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers")) + extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers", "fs")) if external_src is not None: extra_dirs = [external_src] for folder in extra_dirs: From patchwork Thu May 16 19:03:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666479 Received: from aer-iport-5.cisco.com (aer-iport-5.cisco.com [173.38.203.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 88A401581E6; Thu, 16 May 2024 19:04:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.67 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886266; cv=none; b=MzpdQkD54KrVq7YOuo+EzawfPvAZvewIezSrVUhUIlkCe6FAlLSsWIvr5PHU1Wm/4nohxfwIKwPYbn9pRIXygoeM/AEDwvkl2WYH5YLR2EB2C8HoRDnZ97V67kyU3aglp0ZXkJset0LymjrpCyAj1PqmKBnK42hIyRsnYqSi4cE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886266; c=relaxed/simple; bh=14cppHrxJNO2k5SkDzm3ABrvDJviaSVFS2X9pDuyXsE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gx8x1PTg6zHCCk1DrOgZe6T3/RNTOOnLnfHA/Nj53tiYv2vBI+MWTxSwFEi2TgYFxK3IZ/3jaDReTHtXzw0HSA9sbxy+xNkDJk0yEjwijscj+mYa98/RDMZo0NkTi2R4JTB9T0Xd6dnbRMoqzkhTLT7rWk4gK0ZVERVG5gGKA0U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=YCUgijMb; arc=none smtp.client-ip=173.38.203.67 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="YCUgijMb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=5421; q=dns/txt; s=iport; t=1715886265; x=1717095865; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2VScZVKYmKMf1+GFQpbDD6K0vkZQjVRPPErj0F66jK0=; b=YCUgijMbi7LkTk/ljMIQwSGDmTcJDydJT5NnlR2sSuBOgbiWEVWct9Ce 8qcvSnjwwAIP6XOrBQU9dBFkzDURJZFeJ4lUxX1XfGBGKe/izJR7wiNdA mqg4/q653Uz1r5p9W2gWHIsHlm4oquUzUYyX10rwhbtRC9+24FkGn4npV s=; X-CSE-ConnectionGUID: PVvKQ4oGQgiG0wFAL2j9fA== X-CSE-MsgGUID: iJUPC6w/SzyZrLVpmc525w== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="9839853" Received: from aer-iport-nat.cisco.com (HELO aer-core-2.cisco.com) ([173.38.203.22]) by aer-iport-5.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:22 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-2.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4L0j007823 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:22 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 17/22] fs: puzzlefs: add extended attributes support Date: Thu, 16 May 2024 22:03:40 +0300 Message-Id: <20240516190345.957477-18-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-2.cisco.com Implement the listxattr callback in the filesystem abstractions. Implement both read_xattr and listxattr for PuzzleFS. Signed-off-by: Ariel Miculas --- fs/puzzlefs/puzzlefs.rs | 50 +++++++++++++++++++++++++++++-- rust/kernel/fs/inode.rs | 66 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 4 deletions(-) diff --git a/fs/puzzlefs/puzzlefs.rs b/fs/puzzlefs/puzzlefs.rs index a062bf0249f6..9622ea71eda0 100644 --- a/fs/puzzlefs/puzzlefs.rs +++ b/fs/puzzlefs/puzzlefs.rs @@ -107,8 +107,8 @@ fn fill_super( _: Option, ) -> Result> { let puzzlefs = PuzzleFS::open( - c_str!("/home/puzzlefs_oci"), - c_str!("83aa96c40a20671edc4490cfefadbb487b2ab23dfc0570049b56f0cc49b56eaf"), + c_str!("/home/puzzlefs_xattr"), + c_str!("ed63ace21eccceabab08d89afb75e94dae47973f82a17a172396a19ea953c8ab"), ); if let Err(ref e) = puzzlefs { @@ -124,6 +124,36 @@ fn init_root(sb: &sb::SuperBlock) -> Result> { let inode = Self::iget(sb, 1)?; dentry::Root::try_new(inode) } + + fn read_xattr( + _dentry: &DEntry, + inode: &INode, + name: &CStr, + outbuf: &mut [u8], + ) -> Result { + let inode = inode.data(); + let readonly = outbuf.len() == 0; + // pr_info!("outbuf len {}\n", outbuf.len()); + + if let Some(add) = &inode.additional { + let xattr = add + .xattrs + .iter() + .find(|elem| elem.key == name.as_bytes()) + .ok_or(ENODATA)?; + if readonly { + return Ok(xattr.val.len()); + } + + if xattr.val.len() > outbuf.len() { + return Err(ERANGE); + } + + outbuf[0..xattr.val.len()].copy_from_slice(xattr.val.as_slice()); + return Ok(xattr.val.len()); + } + Err(ENODATA) + } } #[vtable] @@ -143,6 +173,22 @@ fn lookup( } } + fn listxattr( + inode: &INode, + mut add_entry: impl FnMut(&[i8]) -> Result<()>, + ) -> Result<()> { + let inode = inode.data(); + + if let Some(add) = &inode.additional { + for xattr in &add.xattrs { + // convert a u8 slice into an i8 slice + let i8slice = unsafe { &*(xattr.key.as_slice() as *const _ as *const [i8]) }; + add_entry(i8slice)?; + } + } + Ok(()) + } + fn get_link<'a>( dentry: Option<&DEntry>, inode: &'a INode, diff --git a/rust/kernel/fs/inode.rs b/rust/kernel/fs/inode.rs index b2b7d000080e..a092ee150d43 100644 --- a/rust/kernel/fs/inode.rs +++ b/rust/kernel/fs/inode.rs @@ -10,7 +10,7 @@ address_space, dentry, dentry::DEntry, file, mode, sb::SuperBlock, FileSystem, Offset, PageOffset, UnspecifiedFS, }; -use crate::error::{code::*, from_err_ptr, Result}; +use crate::error::{code::*, from_err_ptr, from_result, Result}; use crate::types::{ARef, AlwaysRefCounted, Either, ForeignOwnable, Lockable, Locked, Opaque}; use crate::{ bindings, block, build_error, container_of, folio, folio::Folio, mem_cache::MemCache, @@ -48,6 +48,14 @@ fn lookup( ) -> Result>>> { Err(ENOTSUPP) } + + /// Get extended attributes list + fn listxattr<'a>( + _inode: &'a INode, + mut _add_entry: impl FnMut(&[i8]) -> Result<()>, + ) -> Result<()> { + Err(ENOSYS) + } } /// A node (inode) in the file index. @@ -615,7 +623,7 @@ impl Table { rename: None, setattr: None, getattr: None, - listxattr: None, + listxattr: Some(Self::listxattr_callback), fiemap: None, update_time: None, atomic_open: None, @@ -688,6 +696,60 @@ extern "C" fn drop_cstring(ptr: *mut core::ffi::c_void) { } } } + + extern "C" fn listxattr_callback( + dentry: *mut bindings::dentry, + buffer: *mut core::ffi::c_char, + buffer_size: usize, + ) -> isize { + from_result(|| { + // SAFETY: The C API guarantees that `dentry` is valid for read. + let inode = unsafe { bindings::d_inode(dentry) }; + // SAFETY: The C API guarantees that `d_inode` inside `dentry` is valid for read. + let inode = unsafe { INode::from_raw(inode) }; + + // `buffer_size` should be 0 when `buffer` is NULL, but we enforce it + let (mut buffer_ptr, buffer_size) = match ptr::NonNull::new(buffer) { + Some(buf) => (buf, buffer_size), + None => (ptr::NonNull::dangling(), 0), + }; + + // SAFETY: The C API guarantees that `buffer` is at least `buffer_size` bytes in + // length. Also, when `buffer_size` is 0, `buffer_ptr` is NonNull::dangling, as + // suggested by `from_raw_parts_mut` documentation + let outbuf = unsafe { + core::slice::from_raw_parts_mut(buffer_ptr.as_mut(), buffer_size) + }; + + let mut offset = 0; + let mut total_len = 0; + + // The extended attributes keys must be placed into the output buffer sequentially, + // separated by the NUL character. We do this in the callback because it simplifies + // the implementation of the `listxattr` abstraction: the user just calls the + // add_entry function for each extended attribute key, passing a slice. + T::listxattr(inode, |xattr_key| { + let len = xattr_key.len(); + total_len += isize::try_from(len)? + 1; + + if buffer_size == 0 { + return Ok(()); + } + + let max = offset + len + 1; + if max > buffer_size { + return Err(ERANGE); + } + + outbuf[offset..max - 1].copy_from_slice(xattr_key); + outbuf[max - 1] = 0; + offset = max; + Ok(()) + })?; + + Ok(total_len) + }) + } } Self(&Table::::TABLE, PhantomData) } From patchwork Thu May 16 19:03:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666494 Received: from aer-iport-6.cisco.com (aer-iport-6.cisco.com [173.38.203.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 484D41586DB; Thu, 16 May 2024 19:05:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.68 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886328; cv=none; b=VpeRX2+8Y68W97H1DJzVB1FgZRForVf3dYAm2Y/l79aGXf03WOWWbQUuWzr2mxIKlqJRzXPUjfVcbiLzA4jtiF85+m71F3zvKTlSAdDKIPR8Eyvys7oBYfIju5QFpxIzzW0Hw6MHhhIArDkRc4XM0SP58Izx1Bbj5FpMtApnp50= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886328; c=relaxed/simple; bh=ivMYgIYWIJYUOpRQp9sC48jKIyVBnsdndwyo/5V1fdw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZY0qpLU8OBym6+EbGpX8HxS7uuEuHsWGWCteR4S6Cwx0VS2kosGGUshvfJmpgcwoodcooIHlDy+KkPSCfUDK2es3Lq8oXLdsN+Kaji7qNI2kbc1R1LpPHotJhedXd8GV9Sb9t6QCtODoYcE/j472f6MZfATKLT3RVw767mB7XGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=QeEAS47O; arc=none smtp.client-ip=173.38.203.68 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="QeEAS47O" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=10222; q=dns/txt; s=iport; t=1715886326; x=1717095926; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=r1r9rd3KeEvtlJHyqBIHLSruG9tMof1Km6W29D4ICag=; b=QeEAS47ObBHz5ssKohIDUcnuIoi36QTrVGYGOTnnlgzy1lCZ1biXDbsB aImmhATQcpLfuo84Ot9yeKSkh057dQg7knAYNCqreT8x/UG9djRCjbHsF QgGCzm4M4J27gDedopZocUFcSBfv3l0gtIQz1Dy310Sjho2SCeMqUnRW+ 0=; X-CSE-ConnectionGUID: RoOBx6bTTeS67jNRJTcCCg== X-CSE-MsgGUID: SM4doMEZR8O+f5sjHbTXBQ== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="10016315" Received: from aer-iport-nat.cisco.com (HELO aer-core-3.cisco.com) ([173.38.203.22]) by aer-iport-6.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:23 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-3.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4Nig017911 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:23 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Alice Ryhl , Benno Lossin , Martin Rodriguez Reboredo , Boqun Feng , Ariel Miculas Subject: [RFC PATCH v3 18/22] rust: add improved version of `ForeignOwnable::borrow_mut` Date: Thu, 16 May 2024 22:03:41 +0300 Message-Id: <20240516190345.957477-19-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-3.cisco.com From: Alice Ryhl Previously, the `ForeignOwnable` trait had a method called `borrow_mut` that was intended to provide mutable access to the inner value. However, the method accidentally made it possible to change the address of the object being modified, which usually isn't what we want. (And when we want that, it can be done by calling `from_foreign` and `into_foreign`, like how the old `borrow_mut` was implemented.) In this patch, we introduce an alternate definition of `borrow_mut` that solves the previous problem. Conceptually, given a pointer type `P` that implements `ForeignOwnable`, the `borrow_mut` method gives you the same kind of access as an `&mut P` would, except that it does not let you change the pointer `P` itself. This is analogous to how the existing `borrow` method provides the same kind of access to the inner value as an `&P`. Note that for types like `Arc`, having an `&mut Arc` only gives you immutable access to the inner `T`. This is because mutable references assume exclusive access, but there might be other handles to the same reference counted value, so the access isn't exclusive. The `Arc` type implements this by making `borrow_mut` return the same type as `borrow`. Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Boqun Feng Link: https://lore.kernel.org/r/20230710074642.683831-1-aliceryhl@google.com Signed-off-by: Ariel Miculas --- rust/kernel/sync/arc.rs | 25 +++++++---- rust/kernel/types.rs | 93 ++++++++++++++++++++++++++++++----------- 2 files changed, 86 insertions(+), 32 deletions(-) diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index 3673496c2363..9023479281f0 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -356,26 +356,35 @@ pub fn into_unique_or_drop(self) -> Option>> { impl ForeignOwnable for Arc { type Borrowed<'a> = ArcBorrow<'a, T>; + // Mutable access to the `Arc` does not give any extra abilities over + // immutable access. + type BorrowedMut<'a> = ArcBorrow<'a, T>; fn into_foreign(self) -> *const core::ffi::c_void { ManuallyDrop::new(self).ptr.as_ptr() as _ } + unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { + // SAFETY: By the safety requirement of this function, we know that `ptr` came from + // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and + // holds a reference count increment that is transferrable to us. + unsafe { Self::from_inner(NonNull::new_unchecked(ptr as _)) } + } + unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> ArcBorrow<'a, T> { // SAFETY: By the safety requirement of this function, we know that `ptr` came from // a previous call to `Arc::into_foreign`. - let inner = NonNull::new(ptr as *mut ArcInner).unwrap(); + let inner = unsafe { NonNull::new_unchecked(ptr as *mut ArcInner) }; - // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive - // for the lifetime of the returned value. + // SAFETY: The safety requirements ensure that we will not give up our + // foreign-owned refcount while the `ArcBorrow` is still live. unsafe { ArcBorrow::new(inner) } } - unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { - // SAFETY: By the safety requirement of this function, we know that `ptr` came from - // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and - // holds a reference count increment that is transferrable to us. - unsafe { Self::from_inner(NonNull::new(ptr as _).unwrap()) } + unsafe fn borrow_mut<'a>(ptr: *const core::ffi::c_void) -> ArcBorrow<'a, T> { + // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety + // requirements for `borrow`. + unsafe { Self::borrow(ptr) } } } diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 4d8f02671e0b..17b66d6187ae 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -20,31 +20,25 @@ /// This trait is meant to be used in cases when Rust objects are stored in C objects and /// eventually "freed" back to Rust. pub trait ForeignOwnable: Sized { - /// Type of values borrowed between calls to [`ForeignOwnable::into_foreign`] and - /// [`ForeignOwnable::from_foreign`]. + /// Type used to immutably borrow a value that is currently foreign-owned. type Borrowed<'a>; + /// Type used to mutably borrow a value that is currently foreign-owned. + type BorrowedMut<'a>; + /// Converts a Rust-owned object to a foreign-owned one. /// /// The foreign representation is a pointer to void. fn into_foreign(self) -> *const core::ffi::c_void; - /// Borrows a foreign-owned object. - /// - /// # Safety - /// - /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for - /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. - unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>; - /// Converts a foreign-owned object back to a Rust-owned one. /// /// # Safety /// - /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for - /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. - /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for - /// this object must have been dropped. + /// The provided pointer must have been returned by a previous call to [`into_foreign`], and it + /// must not be passed to `from_foreign` more than once. + /// + /// [`into_foreign`]: Self::into_foreign unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self; /// Tries to convert a foreign-owned object back to a Rust-owned one. @@ -65,40 +59,91 @@ unsafe fn try_from_foreign(ptr: *const core::ffi::c_void) -> Option { unsafe { Some(Self::from_foreign(ptr)) } } } + + /// Borrows a foreign-owned object immutably. + /// + /// This method provides a way to access a foreign-owned value from Rust immutably. It provides + /// you with exactly the same abilities as an `&Self` when the value is Rust-owned. + /// + /// # Safety + /// + /// The provided pointer must have been returned by a previous call to [`into_foreign`], and if + /// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of + /// the lifetime 'a. + /// + /// [`into_foreign`]: Self::into_foreign + /// [`from_foreign`]: Self::from_foreign + unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>; + + /// Borrows a foreign-owned object mutably. + /// + /// This method provides a way to access a foreign-owned value from Rust mutably. It provides + /// you with exactly the same abilities as an `&mut Self` when the value is Rust-owned, except + /// that this method does not let you swap the foreign-owned object for another. (That is, it + /// does not let you change the address of the void pointer that the foreign code is storing.) + /// + /// Note that for types like [`Arc`], an `&mut Arc` only gives you immutable access to the + /// inner value, so this method also only provides immutable access in that case. + /// + /// In the case of `Box`, this method gives you the ability to modify the inner `T`, but it + /// does not let you change the box itself. That is, you cannot change which allocation the box + /// points at. + /// + /// # Safety + /// + /// The provided pointer must have been returned by a previous call to [`into_foreign`], and if + /// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of + /// the lifetime 'a. + /// + /// The lifetime 'a must not overlap with the lifetime of any other call to [`borrow`] or + /// `borrow_mut` on the same object. + /// + /// [`into_foreign`]: Self::into_foreign + /// [`from_foreign`]: Self::from_foreign + /// [`borrow`]: Self::borrow + /// [`Arc`]: crate::sync::Arc + unsafe fn borrow_mut<'a>(ptr: *const core::ffi::c_void) -> Self::BorrowedMut<'a>; } impl ForeignOwnable for Box { type Borrowed<'a> = &'a T; + type BorrowedMut<'a> = &'a mut T; fn into_foreign(self) -> *const core::ffi::c_void { Box::into_raw(self) as _ } - unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T { - // SAFETY: The safety requirements for this function ensure that the object is still alive, - // so it is safe to dereference the raw pointer. - // The safety requirements of `from_foreign` also ensure that the object remains alive for - // the lifetime of the returned value. - unsafe { &*ptr.cast() } - } - unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous // call to `Self::into_foreign`. unsafe { Box::from_raw(ptr as _) } } + + unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T { + // SAFETY: The safety requirements of this method ensure that the object remains alive and + // immutable for the duration of 'a. + unsafe { &*ptr.cast() } + } + + unsafe fn borrow_mut<'a>(ptr: *const core::ffi::c_void) -> &'a mut T { + // SAFETY: The safety requirements of this method ensure that the pointer is valid and that + // nothing else will access the value for the duration of 'a. + unsafe { &mut *ptr.cast_mut().cast() } + } } impl ForeignOwnable for () { type Borrowed<'a> = (); + type BorrowedMut<'a> = (); fn into_foreign(self) -> *const core::ffi::c_void { core::ptr::NonNull::dangling().as_ptr() } - unsafe fn borrow<'a>(_: *const core::ffi::c_void) -> Self::Borrowed<'a> {} - unsafe fn from_foreign(_: *const core::ffi::c_void) -> Self {} + + unsafe fn borrow<'a>(_: *const core::ffi::c_void) -> Self::Borrowed<'a> {} + unsafe fn borrow_mut<'a>(_: *const core::ffi::c_void) -> Self::BorrowedMut<'a> {} } /// Runs a cleanup function/closure when dropped. From patchwork Thu May 16 19:03:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666497 Received: from aer-iport-8.cisco.com (aer-iport-8.cisco.com [173.38.203.70]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F7FD15820F; Thu, 16 May 2024 19:07:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.70 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886464; cv=none; b=T/WqDmcfb4dDl3kYEzWlLM44M7Q/E4TGJ6uhq7nkLxy0ThEGfI7GLGknN2dkwsCxKhClyiK9qUV/H9nAOiuVbFeAzRRSw75CRiBsgIIWVJRMjfrPxJsdX50zp5PxbrCiFux9lUJ8qypugiSj6QLYkCpRZ27NOL5WacAVmXnMuoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886464; c=relaxed/simple; bh=MqQvAYPJnEbPgiMJ/KAsv+WELCKQHh977LECrhqpreU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MEgqz3MAsa8DW0thNqCsuVfyfroRMahZay7GBiLnZCGeaKbU0PpymPOtkLuk3m71Us0HxAA0lC5HWm/Sc17UYS59nG8HtAVHa6OIaXzWEE+WZ+zN72eDmIWVq0nU5O1rgQT02Z0FfUvu2ofKaZR6dAttqrklNwAz7etEXEaTVOY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=Lqi5I+J7; arc=none smtp.client-ip=173.38.203.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="Lqi5I+J7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=2431; q=dns/txt; s=iport; t=1715886463; x=1717096063; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IsRVprSkTcedn+zbjClnxOQsSEIZcaVQUIwJQMEacFU=; b=Lqi5I+J7p5BD3bJajeuIzqedcy7H3K15Zrb85zx96f4dTmh+tDeoi8qI sJe2nXF1oH5jTqMz3Xji5Jj0S/FmJ5aQJlymHNNVAD/rc4eWCF9Nt7EzD 3/FZq5R/EV2nomvYvdbOMBr/3JM8ubZZtrueXo9enk05zrbaybczSNTNJ Q=; X-CSE-ConnectionGUID: 3vlKbWuhRUSRVklW0FF6rQ== X-CSE-MsgGUID: e4J0BcmTTdyIH+jEv28DOg== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="9784124" Received: from aer-iport-nat.cisco.com (HELO aer-core-6.cisco.com) ([173.38.203.22]) by aer-iport-8.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:24 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-6.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4OOw006188 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:24 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 19/22] Add borrow_mut implementation to a ForeignOwnable CString Date: Thu, 16 May 2024 22:03:42 +0300 Message-Id: <20240516190345.957477-20-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-6.cisco.com Since the `borrow_mut` function was added to the ForeignOwnable trait, we need to implement it for each type that implements it. Signed-off-by: Ariel Miculas --- rust/kernel/str.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index c45612900fe2..b0a35d71bd49 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -197,6 +197,25 @@ pub unsafe fn from_char_ptr<'a>(ptr: *const core::ffi::c_char) -> &'a Self { unsafe { Self::from_bytes_with_nul_unchecked(bytes) } } + /// Like from_char_ptr, but returns a mutable reference + /// + /// # Safety + /// + /// `ptr` must be a valid pointer to a `NUL`-terminated C string, and it must + /// last at least `'a`. When `CStr` is alive, the memory pointed by `ptr` + /// must not be mutated. + #[inline] + pub unsafe fn from_char_ptr_mut<'a>(ptr: *const core::ffi::c_char) -> &'a mut Self { + // SAFETY: The safety precondition guarantees `ptr` is a valid pointer + // to a `NUL`-terminated C string. + let len = unsafe { bindings::strlen(ptr) } + 1; + // SAFETY: Lifetime guaranteed by the safety precondition. + let bytes = unsafe { core::slice::from_raw_parts_mut(ptr as _, len as _) }; + // SAFETY: As `len` is returned by `strlen`, `bytes` does not contain interior `NUL`. + // As we have added 1 to `len`, the last byte is known to be `NUL`. + unsafe { Self::from_bytes_with_nul_unchecked_mut(bytes) } + } + /// Creates a [`CStr`] from a `[u8]`. /// /// The provided slice must be `NUL`-terminated, does not contain any @@ -901,6 +920,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl ForeignOwnable for CString { type Borrowed<'a> = &'a CStr; + type BorrowedMut<'a> = &'a mut CStr; fn into_foreign(self) -> *const core::ffi::c_void { Box::into_raw(self.buf) as _ @@ -910,6 +930,10 @@ unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a> { unsafe { CStr::from_char_ptr(ptr.cast::()) } } + unsafe fn borrow_mut<'a>(ptr: *const core::ffi::c_void) -> Self::BorrowedMut<'a> { + unsafe { CStr::from_char_ptr_mut(ptr.cast::()) } + } + unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self { // SAFETY: The safety requirements of this function satisfy those of `Self::borrow`. let str = unsafe { Self::borrow(ptr) }; From patchwork Thu May 16 19:03:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666481 Received: from aer-iport-1.cisco.com (aer-iport-1.cisco.com [173.38.203.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B299D158A0D; Thu, 16 May 2024 19:04:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886270; cv=none; b=A0B7xNQf1dQm9lkNhiAJaop8w7atlSdJHvzgLxhH4Zor8jHzjYw49wJyJ7VBZdBmRTj9JocLavFAHZ31TZnPKge9PqYez9pjBfFuARRzOwK1VFKWnCyWQ4G/sFm3GoJTAOMlaIM1FaSumxTZBnEhVfCiz9aMLD6xwNtCd9+3FjI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886270; c=relaxed/simple; bh=FYYpShULCzDGTY8DrJKTdxNXS4tsuaRgjgT2GsYK0fg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ogPjr9otuSGNqjrZekZL53uisgOgLWEXthmFO+/IeUXSb57fA3DPzDxrMJ+j/k52ycMlk225UINu00dRs75kvfn37g5GuX77kYhsiWwNFhjl0EK7vZlI5TfWqBjmAEivgWH5fC9+3c7VOj6c3MwGzubrwv8WfwIK4VGSFr+2mYo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=HQ5bDztO; arc=none smtp.client-ip=173.38.203.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="HQ5bDztO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=32908; q=dns/txt; s=iport; t=1715886267; x=1717095867; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dyh5UB2XyHkCg+QkFyQRlUygD3C+Gcdg9yxYiudF0YI=; b=HQ5bDztOhYEjxfKTd3VY49xYtJv4slTqTXRcvY2fihNHexKIJ8hqTAT/ rrnWgVQ0g4DrApYLD1W2uCyhUMUOGrLQ/otkL3DZ/VqZkOL4CHI8hfAl8 eOJ1tAcHmfhCv3NoCYmMjbJp8H/XV6qVTRg84RDh7OMW+acyKO3hd4p2b k=; X-CSE-ConnectionGUID: CC5w0j8wRuCvUat6eQfJMg== X-CSE-MsgGUID: 9DT0Ng7FSU2CtwQzxEUv7Q== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12419639" Received: from aer-iport-nat.cisco.com (HELO aer-core-7.cisco.com) ([173.38.203.22]) by aer-iport-1.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:26 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-7.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4Pkt117285 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:25 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Wedson Almeida Filho , Ariel Miculas Subject: [RFC PATCH v3 20/22] rust: add support for file system parameters Date: Thu, 16 May 2024 22:03:43 +0300 Message-Id: <20240516190345.957477-21-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-7.cisco.com From: Wedson Almeida Filho This allows file system contexts to be further initialised with parameters from userspace before a fs is mounted or reconfigured. Signed-off-by: Wedson Almeida Filho [ Changes made: * adapt for upstream * replace UnsafeCell with Opaque, * replace from_kernel_result with from_result * replace Type with FileSystem * add Context in FileSystem from [1] * add the EmptyContext from [1] * add the free_callback from [2] * add count_paren_items from [3] * add PAGE_SIZE constant from [4] * initialize the Context in init_fs_context_callback * get the data Context in fill_super_callback and pass it to super_params * avoid freeing s_fs_info in free_callback, it's already freed in kill_sb_callback [1] https://github.com/wedsonaf/linux/commit/6633c50b345f388a07b4c551f752efe34c15c089 [2] https://github.com/wedsonaf/linux/commit/3c3ccce85af9aae9dfc0e17e2331674da520177c [3] https://github.com/wedsonaf/linux/commit/c3f395b1b0126b4db7eb833bdee769212c8c79d8 [4] https://github.com/wedsonaf/linux/commit/4021d947dea69506d11b148486e1565961a85e53 ] Signed-off-by: Ariel Miculas --- fs/puzzlefs/puzzlefs.rs | 1 + rust/bindings/bindings_helper.h | 1 + rust/kernel/fs.rs | 212 +++++++++++- rust/kernel/fs/param.rs | 576 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 7 + samples/rust/rust_rofs.rs | 32 +- 6 files changed, 821 insertions(+), 8 deletions(-) create mode 100644 rust/kernel/fs/param.rs diff --git a/fs/puzzlefs/puzzlefs.rs b/fs/puzzlefs/puzzlefs.rs index 9622ea71eda0..f4e94568c9cc 100644 --- a/fs/puzzlefs/puzzlefs.rs +++ b/fs/puzzlefs/puzzlefs.rs @@ -103,6 +103,7 @@ impl fs::FileSystem for PuzzleFsModule { const NAME: &'static CStr = c_str!("puzzlefs"); fn fill_super( + _data: (), sb: &mut sb::SuperBlock, _: Option, ) -> Result> { diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 0491bb05270c..3f18e5abcc5c 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -27,6 +27,7 @@ #include #include #include +#include /* `bindgen` gets confused at certain things. */ const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs index b7a654546d23..9ca653f64388 100644 --- a/rust/kernel/fs.rs +++ b/rust/kernel/fs.rs @@ -12,7 +12,7 @@ use core::{ffi, marker::PhantomData, mem::size_of, mem::ManuallyDrop, pin::Pin, ptr}; use dentry::DEntry; use inode::INode; -use macros::{pin_data, pinned_drop}; +use macros::{pin_data, pinned_drop, vtable}; use sb::SuperBlock; pub mod address_space; @@ -20,6 +20,7 @@ pub mod file; pub mod inode; pub mod iomap; +pub mod param; pub mod sb; /// The offset of a file in a file system. @@ -59,11 +60,52 @@ pub mod mode { pub const S_IFSOCK: u16 = bindings::S_IFSOCK as u16; } +/// A file system context. +/// +/// It is used to gather configuration to then mount or reconfigure a file system. +#[vtable] +pub trait Context { + /// Type of the data associated with the context. + type Data: ForeignOwnable + Send + Sync + 'static; + + /// The typed file system parameters. + /// + /// Users are encouraged to define it using the [`crate::define_fs_params`] macro. + const PARAMS: param::SpecTable<'static, Self::Data> = param::SpecTable::empty(); + + /// Creates a new context. + fn try_new() -> Result; + + /// Parses a parameter that wasn't specified in [`Self::PARAMS`]. + fn parse_unknown_param( + _data: &mut ::BorrowedMut<'_>, + _name: &CStr, + _value: param::Value<'_>, + ) -> Result { + Err(ENOPARAM) + } + + /// Parses the whole parameter block, potentially skipping regular handling for parts of it. + /// + /// The return value is the portion of the input buffer for which the regular handling + /// (involving [`Self::PARAMS`] and [`Self::parse_unknown_param`]) will still be carried out. + /// If it's `None`, the regular handling is not performed at all. + fn parse_monolithic<'a>( + _data: &mut ::BorrowedMut<'_>, + _buf: Option<&'a mut [u8]>, + ) -> Result> { + Ok(None) + } +} + /// Maximum size of an inode. pub const MAX_LFS_FILESIZE: Offset = bindings::MAX_LFS_FILESIZE; /// A file system type. pub trait FileSystem { + /// The context used to build fs configuration before it is mounted or reconfigured. + type Context: Context + ?Sized = EmptyContext; + /// Data associated with each file system instance (super-block). type Data: ForeignOwnable + Send + Sync; @@ -84,6 +126,7 @@ pub trait FileSystem { /// Initialises the new superblock and returns the data to attach to it. fn fill_super( + data: >::Data, sb: &mut SuperBlock, mapper: Option, ) -> Result; @@ -143,7 +186,11 @@ impl FileSystem for UnspecifiedFS { type INodeData = (); const NAME: &'static CStr = crate::c_str!("unspecified"); const IS_UNSPECIFIED: bool = true; - fn fill_super(_: &mut SuperBlock, _: Option) -> Result { + fn fill_super( + _: >::Data, + _: &mut SuperBlock, + _: Option, + ) -> Result<()> { Err(ENOTSUPP) } @@ -199,9 +246,11 @@ pub fn new(module: &'static ThisModule) -> impl PinInit< fc_ptr: *mut bindings::fs_context, ) -> ffi::c_int { from_result(|| { + let data = T::Context::try_new()?; // SAFETY: The C callback API guarantees that `fc_ptr` is valid. let fc = unsafe { &mut *fc_ptr }; fc.ops = &Tables::::CONTEXT; + fc.fs_private = data.into_foreign() as _; Ok(0) }) } @@ -242,14 +291,32 @@ fn drop(self: Pin<&mut Self>) { } } +/// An empty file system context. +/// +/// That is, one that doesn't take any arguments and doesn't hold any state. It is a convenience +/// type for file systems that don't need context for mounting/reconfiguring. +pub struct EmptyContext; + +#[vtable] +impl Context for EmptyContext { + type Data = (); + fn try_new() -> Result { + Ok(()) + } +} + struct Tables(T); impl Tables { const CONTEXT: bindings::fs_context_operations = bindings::fs_context_operations { - free: None, - parse_param: None, + free: Some(Self::free_callback), + parse_param: Some(Self::parse_param_callback), get_tree: Some(Self::get_tree_callback), reconfigure: None, - parse_monolithic: None, + parse_monolithic: if >::HAS_PARSE_MONOLITHIC { + Some(Self::parse_monolithic_callback) + } else { + None + }, dup: None, }; @@ -268,9 +335,73 @@ impl Tables { } } + unsafe extern "C" fn free_callback(fc: *mut bindings::fs_context) { + // SAFETY: The callback contract guarantees that `fc` is valid. + let fc = unsafe { &*fc }; + + let ptr = fc.fs_private; + if !ptr.is_null() { + // SAFETY: `fs_private` was initialised with the result of a `to_pointer` call in + // `init_fs_context_callback`, so it's ok to call `from_foreign` here. + unsafe { >::Data::from_foreign(ptr) }; + } + } + + unsafe extern "C" fn parse_param_callback( + fc: *mut bindings::fs_context, + param: *mut bindings::fs_parameter, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: The callback contract guarantees that `fc` is valid. + let ptr = unsafe { (*fc).fs_private }; + + // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in + // `init_fs_context_callback` to the result of an `into_foreign` call. Since the + // context is valid, `from_foreign` wasn't called yet, so `ptr` is valid. Additionally, + // the callback contract guarantees that callbacks are serialised, so it is ok to + // mutably reference it. + let mut data = + unsafe { <>::Data as ForeignOwnable>::borrow_mut(ptr) }; + let mut result = bindings::fs_parse_result::default(); + // SAFETY: All parameters are valid at least for the duration of the call. + let opt = + unsafe { bindings::fs_parse(fc, T::Context::PARAMS.first, param, &mut result) }; + + // SAFETY: The callback contract guarantees that `param` is valid for the duration of + // the callback. + let param = unsafe { &*param }; + if opt >= 0 { + let opt = opt as usize; + if opt >= T::Context::PARAMS.handlers.len() { + return Err(EINVAL); + } + T::Context::PARAMS.handlers[opt].handle_param(&mut data, param, &result)?; + return Ok(0); + } + + if opt != ENOPARAM.to_errno() { + return Err(Error::from_errno(opt)); + } + + if !T::Context::HAS_PARSE_UNKNOWN_PARAM { + return Err(ENOPARAM); + } + + let val = param::Value::from_fs_parameter(param); + // SAFETY: The callback contract guarantees the parameter key to be valid and last at + // least the duration of the callback. + T::Context::parse_unknown_param( + &mut data, + unsafe { CStr::from_char_ptr(param.key) }, + val, + )?; + Ok(0) + }) + } + unsafe extern "C" fn fill_super_callback( sb_ptr: *mut bindings::super_block, - _fc: *mut bindings::fs_context, + fc: *mut bindings::fs_context, ) -> ffi::c_int { from_result(|| { // SAFETY: The callback contract guarantees that `sb_ptr` is a unique pointer to a @@ -280,6 +411,20 @@ impl Tables { // SAFETY: The callback contract guarantees that `sb_ptr`, from which `new_sb` is // derived, is valid for write. let sb = unsafe { &mut *new_sb.0.get() }; + + // SAFETY: The callback contract guarantees that `fc` is valid. It also guarantees that + // the callbacks are serialised for a given `fc`, so it is safe to mutably dereference + // it. + let fc = unsafe { &mut *fc }; + let ptr = core::mem::replace(&mut fc.fs_private, ptr::null_mut()); + + // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in + // `init_fs_context_callback` to the result of an `into_foreign` call. The context is + // being used to initialise a superblock, so we took over `ptr` (`fs_private` is set to + // null now) and call `from_foreign` below. + let data = + unsafe { <>::Data as ForeignOwnable>::from_foreign(ptr) }; + sb.s_op = &Tables::::SUPER_BLOCK; sb.s_xattr = &Tables::::XATTR_HANDLERS[0]; sb.s_flags |= bindings::SB_RDONLY; @@ -291,7 +436,7 @@ impl Tables { None }; - let data = T::fill_super(new_sb, mapper)?; + let data = T::fill_super(data, new_sb, mapper)?; // N.B.: Even on failure, `kill_sb` is called and frees the data. sb.s_fs_info = data.into_foreign().cast_mut(); @@ -317,6 +462,41 @@ impl Tables { }) } + unsafe extern "C" fn parse_monolithic_callback( + fc: *mut bindings::fs_context, + buf: *mut core::ffi::c_void, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: The callback contract guarantees that `fc` is valid. + let ptr = unsafe { (*fc).fs_private }; + + // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in + // `init_fs_context_callback` to the result of an `into_pointer` call. Since the + // context is valid, `from_pointer` wasn't called yet, so `ptr` is valid. Additionally, + // the callback contract guarantees that callbacks are serialised, so it is ok to + // mutably reference it. + let mut data = + unsafe { <>::Data as ForeignOwnable>::borrow_mut(ptr) }; + let page = if buf.is_null() { + None + } else { + // SAFETY: This callback is called to handle the `mount` syscall, which takes a + // page-sized buffer as data. + Some(unsafe { &mut *ptr::slice_from_raw_parts_mut(buf.cast(), crate::PAGE_SIZE) }) + }; + let regular = T::Context::parse_monolithic(&mut data, page)?; + if let Some(buf) = regular { + // SAFETY: Both `fc` and `buf` are guaranteed to be valid; the former because the + // callback is still ongoing and the latter because its lifefime is tied to that of + // `page`, which is also valid for the duration of the callback. + to_result(unsafe { + bindings::generic_parse_monolithic(fc, buf.as_mut_ptr().cast()) + })?; + } + Ok(0) + }) + } + const SUPER_BLOCK: bindings::super_operations = bindings::super_operations { alloc_inode: if size_of::() != 0 { Some(INode::::alloc_inode_callback) @@ -490,3 +670,21 @@ macro_rules! module_fs { } } } + +/// Wraps the kernel's `struct filename`. +#[repr(transparent)] +pub struct Filename(pub(crate) Opaque); + +impl Filename { + /// Creates a reference to a [`Filename`] from a valid pointer. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the + /// returned [`Filename`] instance. + pub(crate) unsafe fn from_ptr<'a>(ptr: *const bindings::filename) -> &'a Filename { + // SAFETY: The safety requirements guarantee the validity of the dereference, while the + // `Filename` type being transparent makes the cast ok. + unsafe { &*ptr.cast() } + } +} diff --git a/rust/kernel/fs/param.rs b/rust/kernel/fs/param.rs new file mode 100644 index 000000000000..590fdaaab0ad --- /dev/null +++ b/rust/kernel/fs/param.rs @@ -0,0 +1,576 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! File system parameters and parsing them. +//! +//! C headers: [`include/linux/fs_parser.h`](../../../../../include/linux/fs_parser.h) + +use crate::types::ForeignOwnable; +use crate::{bindings, error::Result, file, fs, str::CStr}; +use core::{marker::PhantomData, ptr}; + +/// The value of a file system parameter. +pub enum Value<'a> { + /// The value is undefined. + Undefined, + + /// There is no value, but parameter itself is a flag. + Flag, + + /// The value is the given string. + String(&'a CStr), + + /// The value is the given binary blob. + Blob(&'a mut [u8]), + + /// The value is the given file. + File(&'a file::File), + + /// The value is the given filename and the given directory file descriptor (which may be + /// `AT_FDCWD`, to indicate the current directory). + Filename(&'a fs::Filename, i32), +} + +impl<'a> Value<'a> { + pub(super) fn from_fs_parameter(p: &'a bindings::fs_parameter) -> Self { + match p.type_() { + bindings::fs_value_type_fs_value_is_string => { + // SAFETY: `type_` is string, so it is ok to use the union field. Additionally, it + // is guaranteed to be valid while `p` is valid. + Self::String(unsafe { CStr::from_char_ptr(p.__bindgen_anon_1.string) }) + } + bindings::fs_value_type_fs_value_is_flag => Self::Flag, + bindings::fs_value_type_fs_value_is_blob => { + // SAFETY: `type_` is blob, so it is ok to use the union field and size. + // Additionally, it is guaranteed to be valid while `p` is valid. + let slice = unsafe { + &mut *ptr::slice_from_raw_parts_mut(p.__bindgen_anon_1.blob.cast(), p.size) + }; + Self::Blob(slice) + } + bindings::fs_value_type_fs_value_is_file => { + // SAFETY: `type_` is file, so it is ok to use the union field. Additionally, it is + // guaranteed to be valid while `p` is valid. + let file_ptr = unsafe { p.__bindgen_anon_1.file }; + if file_ptr.is_null() { + Self::Undefined + } else { + // SAFETY: `file_ptr` is non-null and guaranteed to be valid while `p` is. + Self::File(unsafe { file::File::from_ptr(file_ptr) }) + } + } + bindings::fs_value_type_fs_value_is_filename => { + // SAFETY: `type_` is filename, so it is ok to use the union field. Additionally, + // it is guaranteed to be valid while `p` is valid. + let filename_ptr = unsafe { p.__bindgen_anon_1.name }; + if filename_ptr.is_null() { + Self::Undefined + } else { + // SAFETY: `filename_ptr` is non-null and guaranteed to be valid while `p` is. + Self::Filename(unsafe { fs::Filename::from_ptr(filename_ptr) }, p.dirfd) + } + } + _ => Self::Undefined, + } + } +} + +/// A specification of a file system parameter. +pub struct Spec { + name: &'static CStr, + flags: u16, + type_: bindings::fs_param_type, + extra: *const core::ffi::c_void, +} + +const DEFAULT: Spec = Spec { + name: crate::c_str!(""), + flags: 0, + type_: None, + extra: core::ptr::null(), +}; + +macro_rules! define_param_type { + ($name:ident, $fntype:ty, $spec:expr, |$param:ident, $result:ident| $value:expr) => { + /// Module to support `$name` parameter types. + pub mod $name { + use super::*; + + #[doc(hidden)] + pub const fn spec(name: &'static CStr) -> Spec { + const GIVEN: Spec = $spec; + Spec { name, ..GIVEN } + } + + #[doc(hidden)] + pub const fn handler( + setfn: fn(&mut ::BorrowedMut<'_>, $fntype) -> Result, + ) -> impl Handler { + let c = + move |s: &mut ::BorrowedMut<'_>, + $param: &bindings::fs_parameter, + $result: &bindings::fs_parse_result| { setfn(s, $value) }; + ConcreteHandler { + setfn: c, + _p: PhantomData, + } + } + } + }; +} + +// SAFETY: This is only called when the parse result is a boolean, so it is ok to access to union +// field. +define_param_type!(flag, bool, Spec { ..DEFAULT }, |_p, r| unsafe { + r.__bindgen_anon_1.boolean +}); + +define_param_type!( + flag_no, + bool, + Spec { + flags: bindings::fs_param_neg_with_no as _, + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is a boolean, so it is ok to access to + // union field. + |_p, r| unsafe { r.__bindgen_anon_1.boolean } +); + +define_param_type!( + bool, + bool, + Spec { + type_: Some(bindings::fs_param_is_bool), + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is a boolean, so it is ok to access to + // union field. + |_p, r| unsafe { r.__bindgen_anon_1.boolean } +); + +define_param_type!( + u32, + u32, + Spec { + type_: Some(bindings::fs_param_is_u32), + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union + // field. + |_p, r| unsafe { r.__bindgen_anon_1.uint_32 } +); + +define_param_type!( + u32oct, + u32, + Spec { + type_: Some(bindings::fs_param_is_u32), + extra: 8 as _, + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union + // field. + |_p, r| unsafe { r.__bindgen_anon_1.uint_32 } +); + +define_param_type!( + u32hex, + u32, + Spec { + type_: Some(bindings::fs_param_is_u32), + extra: 16 as _, + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union + // field. + |_p, r| unsafe { r.__bindgen_anon_1.uint_32 } +); + +define_param_type!( + s32, + i32, + Spec { + type_: Some(bindings::fs_param_is_s32), + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is an i32, so it is ok to access to union + // field. + |_p, r| unsafe { r.__bindgen_anon_1.int_32 } +); + +define_param_type!( + u64, + u64, + Spec { + type_: Some(bindings::fs_param_is_u64), + extra: 16 as _, + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union + // field. + |_p, r| unsafe { r.__bindgen_anon_1.uint_64 } +); + +define_param_type!( + string, + &CStr, + Spec { + type_: Some(bindings::fs_param_is_string), + ..DEFAULT + }, + // SAFETY: This is only called when the parse result is a string, so it is ok to access to + // union field. + |p, _r| unsafe { CStr::from_char_ptr(p.__bindgen_anon_1.string) } +); + +/// Module to support `enum` parameter types. +pub mod enum_ { + use super::*; + + #[doc(hidden)] + pub const fn spec(name: &'static CStr, options: ConstantTable<'static>) -> Spec { + Spec { + name, + type_: Some(bindings::fs_param_is_enum), + extra: options.first as *const _ as _, + ..DEFAULT + } + } + + #[doc(hidden)] + pub const fn handler( + setfn: fn(&mut ::BorrowedMut<'_>, u32) -> Result, + ) -> impl Handler { + let c = move |s: &mut ::BorrowedMut<'_>, + _p: &bindings::fs_parameter, + r: &bindings::fs_parse_result| { + // SAFETY: This is only called when the parse result is an enum, so it is ok to access + // to union field. + setfn(s, unsafe { r.__bindgen_anon_1.uint_32 }) + }; + ConcreteHandler { + setfn: c, + _p: PhantomData, + } + } +} + +const ZERO_SPEC: bindings::fs_parameter_spec = bindings::fs_parameter_spec { + name: core::ptr::null(), + type_: None, + opt: 0, + flags: 0, + data: core::ptr::null(), +}; + +/// A zero-terminated parameter spec array, followed by handlers. +#[repr(C)] +pub struct SpecArray { + specs: [bindings::fs_parameter_spec; N], + sentinel: bindings::fs_parameter_spec, + handlers: [&'static dyn Handler; N], +} + +impl SpecArray { + /// Creates a new spec array. + /// + /// Users are encouraged to use the [`define_fs_params`] macro to define the + /// [`super::Context::PARAMS`] constant. + /// + /// # Safety + /// + /// The type of the elements in `handlers` must be compatible with the types in specs. For + /// example, if `specs` declares that the i-th element is a bool then the i-th handler + /// should be for a bool. + pub const unsafe fn new(specs: [Spec; N], handlers: [&'static dyn Handler; N]) -> Self { + let mut array = Self { + specs: [ZERO_SPEC; N], + sentinel: ZERO_SPEC, + handlers, + }; + let mut i = 0usize; + while i < N { + array.specs[i] = bindings::fs_parameter_spec { + name: specs[i].name.as_char_ptr(), + type_: specs[i].type_, + opt: i as _, + flags: specs[i].flags, + data: specs[i].extra, + }; + i += 1; + } + array + } + + /// Returns a [`SpecTable`] backed by `self`. + /// + /// This is used to essentially erase the array size. + pub const fn as_table(&self) -> SpecTable<'_, S> { + SpecTable { + first: &self.specs[0], + handlers: &self.handlers, + _p: PhantomData, + } + } +} + +/// A parameter spec table. +/// +/// The table is guaranteed to be zero-terminated. +/// +/// Users are encouraged to use the [`define_fs_params`] macro to define the +/// [`super::Context::PARAMS`] constant. +pub struct SpecTable<'a, S: 'static> { + pub(super) first: &'a bindings::fs_parameter_spec, + pub(super) handlers: &'a [&'static dyn Handler], + _p: PhantomData, +} + +impl SpecTable<'static, S> { + pub(super) const fn empty() -> Self { + Self { + first: &ZERO_SPEC, + handlers: &[], + _p: PhantomData, + } + } +} + +/// A zero-terminated parameter constant array. +#[repr(C)] +pub struct ConstantArray { + consts: [bindings::constant_table; N], + sentinel: bindings::constant_table, +} + +impl ConstantArray { + /// Creates a new constant array. + /// + /// Users are encouraged to use the [`define_fs_params`] macro to define the + /// [`super::Context::PARAMS`] constant. + pub const fn new(consts: [(&'static CStr, u32); N]) -> Self { + const ZERO: bindings::constant_table = bindings::constant_table { + name: core::ptr::null(), + value: 0, + }; + let mut array = Self { + consts: [ZERO; N], + sentinel: ZERO, + }; + let mut i = 0usize; + while i < N { + array.consts[i] = bindings::constant_table { + name: consts[i].0.as_char_ptr(), + value: consts[i].1 as _, + }; + i += 1; + } + array + } + + /// Returns a [`ConstantTable`] backed by `self`. + /// + /// This is used to essentially erase the array size. + pub const fn as_table(&self) -> ConstantTable<'_> { + ConstantTable { + first: &self.consts[0], + } + } +} + +/// A parameter constant table. +/// +/// The table is guaranteed to be zero-terminated. +pub struct ConstantTable<'a> { + pub(super) first: &'a bindings::constant_table, +} + +#[doc(hidden)] +pub trait Handler { + fn handle_param( + &self, + state: &mut ::BorrowedMut<'_>, + p: &bindings::fs_parameter, + r: &bindings::fs_parse_result, + ) -> Result; +} + +struct ConcreteHandler< + S: ForeignOwnable, + T: Fn( + &mut ::BorrowedMut<'_>, + &bindings::fs_parameter, + &bindings::fs_parse_result, + ) -> Result, +> { + setfn: T, + _p: PhantomData, +} + +impl< + S: ForeignOwnable, + T: Fn( + &mut ::BorrowedMut<'_>, + &bindings::fs_parameter, + &bindings::fs_parse_result, + ) -> Result, + > Handler for ConcreteHandler +{ + fn handle_param( + &self, + state: &mut ::BorrowedMut<'_>, + p: &bindings::fs_parameter, + r: &bindings::fs_parse_result, + ) -> Result { + (self.setfn)(state, p, r) + } +} + +/// Counts the number of parenthesis-delimited, comma-separated items. +/// +/// # Examples +/// +/// ``` +/// # use kernel::count_paren_items; +/// +/// assert_eq!(0, count_paren_items!()); +/// assert_eq!(1, count_paren_items!((A))); +/// assert_eq!(1, count_paren_items!((A),)); +/// assert_eq!(2, count_paren_items!((A), (B))); +/// assert_eq!(2, count_paren_items!((A), (B),)); +/// assert_eq!(3, count_paren_items!((A), (B), (C))); +/// assert_eq!(3, count_paren_items!((A), (B), (C),)); +/// ``` +#[macro_export] +macro_rules! count_paren_items { + (($($item:tt)*), $($remaining:tt)*) => { 1 + $crate::count_paren_items!($($remaining)*) }; + (($($item:tt)*)) => { 1 }; + () => { 0 }; +} + +/// Counts the number of comma-separated entries surrounded by braces. +/// +/// # Examples +/// +/// ``` +/// # use kernel::count_brace_items; +/// +/// assert_eq!(0, count_brace_items!()); +/// assert_eq!(1, count_brace_items!({A})); +/// assert_eq!(1, count_brace_items!({A},)); +/// assert_eq!(2, count_brace_items!({A}, {B})); +/// assert_eq!(2, count_brace_items!({A}, {B},)); +/// assert_eq!(3, count_brace_items!({A}, {B}, {C})); +/// assert_eq!(3, count_brace_items!({A}, {B}, {C},)); +/// ``` +#[macro_export] +macro_rules! count_brace_items { + ({$($item:tt)*}, $($remaining:tt)*) => { 1 + $crate::count_brace_items!($($remaining)*) }; + ({$($item:tt)*}) => { 1 }; + () => { 0 }; +} + +/// Defines the file system parameters of a given file system context. +/// +/// # Examples +/// ``` +/// # use kernel::prelude::*; +/// # use kernel::{c_str, fs, str::CString}; +/// +/// #[derive(Default)] +/// struct State { +/// flag: Option, +/// flag_no: Option, +/// bool_value: Option, +/// u32_value: Option, +/// i32_value: Option, +/// u64_value: Option, +/// str_value: Option, +/// enum_value: Option, +/// } +/// +/// fn set_u32(s: &mut Box, v: u32) -> Result { +/// s.u32_value = Some(v); +/// Ok(()) +/// } +/// +/// struct Example; +/// +/// #[vtable] +/// impl fs::Context for Example { +/// type Data = Box; +/// +/// kernel::define_fs_params!{Box, +/// {flag, "flag", |s, v| { s.flag = Some(v); Ok(()) } }, +/// {flag_no, "flagno", |s, v| { s.flag_no = Some(v); Ok(()) } }, +/// {bool, "bool", |s, v| { s.bool_value = Some(v); Ok(()) } }, +/// {u32, "u32", set_u32 }, +/// {u32oct, "u32oct", set_u32 }, +/// {u32hex, "u32hex", set_u32 }, +/// {s32, "s32", |s, v| { s.i32_value = Some(v); Ok(()) } }, +/// {u64, "u64", |s, v| { s.u64_value = Some(v); Ok(()) } }, +/// {string, "string", |s, v| { +/// s.str_value = Some(CString::try_from_fmt(fmt!("{v}"))?); +/// Ok(()) +/// }}, +/// {enum, "enum", [("first", 10), ("second", 20)], |s, v| { +/// s.enum_value = Some(v); +/// Ok(()) +/// }}, +/// } +/// +/// fn try_new() -> Result { +/// Ok(Box::try_new(State::default())?) +/// } +/// } +/// +/// # impl fs::Type for Example { +/// # type Context = Self; +/// # const NAME: &'static CStr = c_str!("example"); +/// # const FLAGS: i32 = 0; +/// # const MAGIC: u32 = 0x6578616d; +/// # } +/// ``` +#[macro_export] +macro_rules! define_fs_params { + ($data_type:ty, $({$($t:tt)*}),+ $(,)?) => { + const PARAMS: $crate::fs::param::SpecTable<'static, $data_type> = + { + use $crate::fs::param::{self, ConstantArray, Spec, SpecArray, Handler}; + use $crate::c_str; + const COUNT: usize = $crate::count_brace_items!($({$($t)*},)*); + const SPECS: [Spec; COUNT] = $crate::define_fs_params!(@specs $({$($t)*},)*); + const HANDLERS: [&dyn Handler<$data_type>; COUNT] = + $crate::define_fs_params!(@handlers $data_type, $({$($t)*},)*); + // SAFETY: We defined matching specs and handlers above. + const ARRAY: SpecArray = + unsafe { SpecArray::new(SPECS, HANDLERS) }; + ARRAY.as_table() + }; + }; + + (@handlers $data_type:ty, $({$($t:tt)*},)*) => { + [ $($crate::define_fs_params!(@handler $data_type, $($t)*),)* ] + }; + (@handler $data_type:ty, enum, $name:expr, $opts:expr, $closure:expr) => { + ¶m::enum_::handler::<$data_type>($closure) + }; + (@handler $data_type:ty, $type:ident, $name:expr, $closure:expr) => { + ¶m::$type::handler::<$data_type>($closure) + }; + + (@specs $({$($t:tt)*},)*) => {[ $($crate::define_fs_params!(@spec $($t)*),)* ]}; + (@spec enum, $name:expr, [$($opts:tt)*], $closure:expr) => { + { + const COUNT: usize = $crate::count_paren_items!($($opts)*); + const OPTIONS: ConstantArray = + ConstantArray::new($crate::define_fs_params!(@c_str_first $($opts)*)); + param::enum_::spec(c_str!($name), OPTIONS.as_table()) + } + }; + (@spec $type:ident, $name:expr, $closure:expr) => { param::$type::spec(c_str!($name)) }; + + (@c_str_first $(($first:expr, $second:expr)),+ $(,)?) => { + [$((c_str!($first), $second),)*] + }; +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index ea1411a25ee4..59253f5390cd 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -12,11 +12,13 @@ //! do so first instead of bypassing this crate. #![no_std] +#![feature(associated_type_defaults)] #![feature(coerce_unsized)] #![feature(dispatch_from_dyn)] #![feature(new_uninit)] #![feature(receiver_trait)] #![feature(unsize)] +#![feature(const_mut_refs)] // Ensure conditional compilation based on the kernel configuration works; // otherwise we may silently break things like initcall handling. @@ -62,6 +64,11 @@ #[doc(hidden)] pub use build_error::build_error; +/// Page size defined in terms of the `PAGE_SHIFT` macro from C. +/// +/// [`PAGE_SHIFT`]: ../../../include/asm-generic/page.h +pub const PAGE_SIZE: usize = 1 << bindings::PAGE_SHIFT; + /// Prefix to appear before log messages printed from within the `kernel` crate. const __LOG_PREFIX: &[u8] = b"rust_kernel\0"; diff --git a/samples/rust/rust_rofs.rs b/samples/rust/rust_rofs.rs index 5d0d1936459d..d81ea8fdf174 100644 --- a/samples/rust/rust_rofs.rs +++ b/samples/rust/rust_rofs.rs @@ -55,6 +55,31 @@ struct Entry { const DIR_IOPS: inode::Ops = inode::Ops::new::(); const FILE_AOPS: address_space::Ops = address_space::Ops::new::(); +#[vtable] +impl fs::Context for RoFs { + type Data = (); + + kernel::define_fs_params! {(), + {flag, "flag", |_, v| { pr_info!("flag passed-in: {v}\n"); Ok(()) } }, + {flag_no, "flagno", |_, v| { pr_info!("flagno passed-in: {v}\n"); Ok(()) } }, + {bool, "bool", |_, v| { pr_info!("bool passed-in: {v}\n"); Ok(()) } }, + {u32, "u32", |_, v| { pr_info!("u32 passed-in: {v}\n"); Ok(()) } }, + {u32oct, "u32oct", |_, v| { pr_info!("u32oct passed-in: {v}\n"); Ok(()) } }, + {u32hex, "u32hex", |_, v| { pr_info!("u32hex passed-in: {v}\n"); Ok(()) } }, + {s32, "s32", |_, v| { pr_info!("s32 passed-in: {v}\n"); Ok(()) } }, + {u64, "u64", |_, v| { pr_info!("u64 passed-in: {v}\n"); Ok(()) } }, + {string, "string", |_, v| { pr_info!("string passed-in: {v}\n"); Ok(()) } }, + {enum, "enum", [("first", 10), ("second", 20)], |_, v| { + pr_info!("enum passed-in: {v}\n"); Ok(()) } + }, + } + + fn try_new() -> Result { + pr_info!("context created!\n"); + Ok(()) + } +} + struct RoFs; impl RoFs { @@ -103,11 +128,16 @@ fn iget(sb: &sb::SuperBlock, e: &'static Entry) -> Result } impl fs::FileSystem for RoFs { + type Context = Self; type Data = (); type INodeData = &'static Entry; const NAME: &'static CStr = c_str!("rust_rofs"); - fn fill_super(sb: &mut sb::SuperBlock, _: Option) -> Result { + fn fill_super( + _data: (), + sb: &mut sb::SuperBlock, + _: Option, + ) -> Result { sb.set_magic(0x52555354); Ok(()) } From patchwork Thu May 16 19:03:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666480 Received: from aer-iport-2.cisco.com (aer-iport-2.cisco.com [173.38.203.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE4F7158A3F; Thu, 16 May 2024 19:04:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886270; cv=none; b=kv7b1ntAi6VHK/Q9junrNo9Y/1Y11HLd6xx65ljgizvY4ZilOa02XtK+UpYdpogOKRrcNKXd7z9siYOaclweQ6r3zBNk0CbjBSwrL1UElqFctJiFgCfVxIkFy7jLcm/g/ODWYUXuGqd64UmWHvAEeUFWSO81//iXtD+nOcWIaX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886270; c=relaxed/simple; bh=gaUlXe3wl+xDisP3R5K2Iyajwf5YxKCnqADsnqyc3AA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cjGki1yXGFN48nX41A9DkRdXotiYW/1dm5FIxHAHeCVYZuVlJmEuAEpUdk9TOBhE1M1IQNtbw8sdAL9OlR+/nWRBEJORvRo+n4W7Y1KSOtDwLQQFEV9tGfsgXDaRWfSNIKya/bedVwDNCzLuRu4v4FpXNdWy+ihf5qINi6DeiRU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=dUPwJ5TY; arc=none smtp.client-ip=173.38.203.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="dUPwJ5TY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=3172; q=dns/txt; s=iport; t=1715886268; x=1717095868; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IARrAtPjZ/35pawnxYHHtgxzlwcbQQF1QO5K+2KrZxI=; b=dUPwJ5TYSyd3zrKRdVr/TyawxPyId7HaqccKDALdMnwLH0SWmXvHfOk0 cAlWOt8KL5C2aQelfp5e5IJzH4R5hw0GXQJMkRPOF3ok4QBBOpMC77nTj mVKfBYeD3mQBnoFe0tKoY/g8NPBHCab9qXIKHdnhNqWz7xfRv00ZSuHMi I=; X-CSE-ConnectionGUID: qsVxvoxXTpyKGT09HZsAmA== X-CSE-MsgGUID: KUvDbz8ZSTyJr2NeFTsIAQ== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12416992" Received: from aer-iport-nat.cisco.com (HELO aer-core-9.cisco.com) ([173.38.203.22]) by aer-iport-2.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:27 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-9.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4QU3032847 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:27 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 21/22] fs: puzzlefs: add oci_root_dir and image_manifest mount parameters Date: Thu, 16 May 2024 22:03:44 +0300 Message-Id: <20240516190345.957477-22-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-9.cisco.com These parameters are passed when mounting puzzlefs using '-o' option of mount: -o oci_root_dir="/path/to/oci/dir" -o image_manifest="root_hash_of_image_manifest" For a particular manifest in the manifests array in index.json (located in the oci_root_dir), the root hash of the image manifest is found in the digest field. It would be nicer if we could pass the tag, but we don't support json deserialization. Example of mount: mount -t puzzlefs -o oci_root_dir="/home/puzzlefs_oci" -o \ image_manifest="2d6602d678140540dc7e96de652a76a8b16e8aca190bae141297bcffdcae901b" \ none /mnt Signed-off-by: Ariel Miculas --- fs/puzzlefs/puzzlefs.rs | 49 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/fs/puzzlefs/puzzlefs.rs b/fs/puzzlefs/puzzlefs.rs index f4e94568c9cc..932f31917992 100644 --- a/fs/puzzlefs/puzzlefs.rs +++ b/fs/puzzlefs/puzzlefs.rs @@ -36,6 +36,32 @@ fn mode_to_fs_type(inode: &Inode) -> Result { }) } +#[derive(Default)] +struct PuzzleFsParams { + oci_root_dir: Option, + image_manifest: Option, +} + +#[vtable] +impl fs::Context for PuzzleFsModule { + type Data = Box; + + kernel::define_fs_params! {Box, + {string, "oci_root_dir", |s, v| { + s.oci_root_dir = Some(CString::try_from_fmt(format_args!("{v}"))?); + Ok(()) + }}, + {string, "image_manifest", |s, v| { + s.image_manifest = Some(CString::try_from_fmt(format_args!("{v}"))?); + Ok(()) + }}, + } + + fn try_new() -> Result { + Ok(Box::new(PuzzleFsParams::default(), GFP_KERNEL)?) + } +} + const DIR_FOPS: file::Ops = file::Ops::new::(); const DIR_IOPS: inode::Ops = inode::Ops::new::(); const FILE_AOPS: address_space::Ops = address_space::Ops::new::(); @@ -98,24 +124,37 @@ fn iget(sb: &sb::SuperBlock, ino: u64) -> Result>> { } impl fs::FileSystem for PuzzleFsModule { + type Context = Self; type Data = Box; type INodeData = Inode; const NAME: &'static CStr = c_str!("puzzlefs"); fn fill_super( - _data: (), + data: Box, sb: &mut sb::SuperBlock, _: Option, ) -> Result> { - let puzzlefs = PuzzleFS::open( - c_str!("/home/puzzlefs_xattr"), - c_str!("ed63ace21eccceabab08d89afb75e94dae47973f82a17a172396a19ea953c8ab"), - ); + let Some(oci_root_dir) = data.oci_root_dir else { + pr_err!("missing oci_root_dir parameter!\n"); + return Err(ENOTSUPP); + }; + let Some(image_manifest) = data.image_manifest else { + pr_err!("missing image_manifest parameter!\n"); + return Err(ENOTSUPP); + }; + + let puzzlefs = PuzzleFS::open(&oci_root_dir, &image_manifest); if let Err(ref e) = puzzlefs { pr_info!("error opening puzzlefs {e}\n"); } + pr_info!( + "opened puzzlefs [{}]:[{}]\n", + &*oci_root_dir, + &*image_manifest + ); + let puzzlefs = puzzlefs?; sb.set_magic(0x7a7a7570); Ok(Box::new(puzzlefs, GFP_KERNEL)?) From patchwork Thu May 16 19:03:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ariel Miculas X-Patchwork-Id: 13666482 Received: from aer-iport-4.cisco.com (aer-iport-4.cisco.com [173.38.203.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C8C0158D77; Thu, 16 May 2024 19:04:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.38.203.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886272; cv=none; b=e+ufxdwX3I/GwA3G1hNabAlhoGE4yKSgNWKXXOEXn65/TO62O+q7K8O1Welkm+P3w5vJTYqC9xaRoX3h2oqLWYFtKtkZ0fzVe2+w8HPlG76yIYZ1SXatuRqSD0qqjilqitSsTSHhe59gyvc6V7WuS0SbwR5GMPA9Jq+vK7WnwT0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715886272; c=relaxed/simple; bh=YVkKY+DVfu3Ns5YhZFxnBhlRk3J/PwOtX93n3BmC/r0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rNKOdhjSll4kayBYjVd+RwlxhHcTp+tERECLsTX2Pb7heCjzREbiN5SgzCh+7DqAFc9iBc7nMb61gqdHTbhdx/igjjynJ1y+BZqoIGgMPbYFkEz8S9eFXPT+6bFoXab43eRmQBPc8398qs2P4K4E12jRABlzpJzH9iOrdDmqBCU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b=ZHbCJ+XJ; arc=none smtp.client-ip=173.38.203.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=cisco.com header.i=@cisco.com header.b="ZHbCJ+XJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=3251; q=dns/txt; s=iport; t=1715886271; x=1717095871; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+pfayBA377Ipl2qQGaCZtcT9bhjEsaDIsf91AaD2x7E=; b=ZHbCJ+XJHSms5kH0i4Px/dU5jPf2aFyMfpSdlDBfOX0G1R2HWtveJ3lu epg4ZTnecHPCu/rt7QHo6i/j98sxghOkaBU2w2nSHqvK8+eyFT16uUx8t i+VJ4pG/jRaLEtEKF/42xlVl3TYjFNZ+eyCwnDolqtArxV1eXARBYXW1d M=; X-CSE-ConnectionGUID: IN3ktra0TnyQzrIlWsIUSA== X-CSE-MsgGUID: MVb2X31TSLeouobFH9aTTA== X-IronPort-AV: E=Sophos;i="6.08,165,1712620800"; d="scan'208";a="12379876" Received: from aer-iport-nat.cisco.com (HELO aer-core-10.cisco.com) ([173.38.203.22]) by aer-iport-4.cisco.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2024 19:04:28 +0000 Received: from localhost (ams3-vpn-dhcp4879.cisco.com [10.61.83.14]) (authenticated bits=0) by aer-core-10.cisco.com (8.15.2/8.15.2) with ESMTPSA id 44GJ4RKW101499 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 May 2024 19:04:28 GMT From: Ariel Miculas To: rust-for-linux@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, tycho@tycho.pizza, brauner@kernel.org, viro@zeniv.linux.org.uk, ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com, shallyn@cisco.com, Ariel Miculas Subject: [RFC PATCH v3 22/22] fs: puzzlefs: implement statfs for puzzlefs Date: Thu, 16 May 2024 22:03:45 +0300 Message-Id: <20240516190345.957477-23-amiculas@cisco.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240516190345.957477-1-amiculas@cisco.com> References: <20240516190345.957477-1-amiculas@cisco.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Authenticated-User: amiculas@cisco.com X-Outbound-SMTP-Client: 10.61.83.14, ams3-vpn-dhcp4879.cisco.com X-Outbound-Node: aer-core-10.cisco.com In order to use a filesystem as a lower filesystem in an overlay, it must implement statfs. Signed-off-by: Ariel Miculas --- fs/puzzlefs/puzzle/inode.rs | 26 ++++++++++++++++++++++++-- fs/puzzlefs/puzzlefs.rs | 21 +++++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/fs/puzzlefs/puzzle/inode.rs b/fs/puzzlefs/puzzle/inode.rs index 318edbdc5163..a34f1064b632 100644 --- a/fs/puzzlefs/puzzle/inode.rs +++ b/fs/puzzlefs/puzzle/inode.rs @@ -14,6 +14,8 @@ pub(crate) struct PuzzleFS { pub(crate) oci: Image, layers: Vec, + pub(crate) total_inodes: u64, + pub(crate) total_block_size: u64, } impl PuzzleFS { @@ -22,13 +24,33 @@ pub(crate) fn open(oci_root_dir: &CStr, rootfs_path: &CStr) -> Result let oci = Image::open(vfs_mount)?; let rootfs = oci.open_rootfs_blob(rootfs_path)?; + let mut total_block_size = 0; + let mut total_inodes: u64 = 0; let mut layers = Vec::new(); for md in rootfs.metadatas.iter() { let digest = Digest::try_from(md)?; - layers.push(oci.open_metadata_blob(&digest)?, GFP_KERNEL)?; + let layer = oci.open_metadata_blob(&digest)?; + + // This may take up too much time, but we need to implement statfs if we want to use + // puzzlefs as a lower filesystem in overlayfs + let inodes = layer.get_inode_vector()?; + total_inodes += u64::from(inodes.len()); + for inode_number in 0..inodes.len() { + let inode = Inode::from_capnp(inodes.get(inode_number))?; + if let InodeMode::File { chunks } = inode.mode { + total_block_size += chunks.iter().map(|chunk| chunk.len).sum::(); + } + } + + layers.push(layer, GFP_KERNEL)?; } - Ok(PuzzleFS { oci, layers }) + Ok(PuzzleFS { + oci, + layers, + total_inodes, + total_block_size, + }) } pub(crate) fn find_inode(&self, ino: u64) -> Result { diff --git a/fs/puzzlefs/puzzlefs.rs b/fs/puzzlefs/puzzlefs.rs index 932f31917992..633f60983849 100644 --- a/fs/puzzlefs/puzzlefs.rs +++ b/fs/puzzlefs/puzzlefs.rs @@ -4,7 +4,7 @@ use kernel::fs::{ address_space, dentry, dentry::DEntry, file, file::DirEntryType, file::File, inode, - inode::INode, sb, Offset, + inode::INode, sb, Offset, Stat, }; use kernel::prelude::*; use kernel::types::{ARef, Either, Locked}; @@ -23,6 +23,10 @@ license: "GPL", } +const PUZZLEFS_BSIZE: u64 = 1 << PUZZLEFS_BSIZE_BITS; +const PUZZLEFS_BSIZE_BITS: u8 = 12; +const PUZZLEFS_MAGIC: usize = 0x7a7a7570; + fn mode_to_fs_type(inode: &Inode) -> Result { Ok(match inode.mode { InodeMode::File { .. } => DirEntryType::Reg, @@ -156,7 +160,7 @@ fn fill_super( ); let puzzlefs = puzzlefs?; - sb.set_magic(0x7a7a7570); + sb.set_magic(PUZZLEFS_MAGIC); Ok(Box::new(puzzlefs, GFP_KERNEL)?) } @@ -194,6 +198,19 @@ fn read_xattr( } Err(ENODATA) } + + fn statfs(dentry: &DEntry) -> Result { + let puzzlefs = dentry.super_block().data(); + + Ok(Stat { + magic: PUZZLEFS_MAGIC, + namelen: isize::MAX, + bsize: PUZZLEFS_BSIZE as _, + // Round total_block_size up + blocks: (puzzlefs.total_block_size + PUZZLEFS_BSIZE - 1) / PUZZLEFS_BSIZE, + files: puzzlefs.total_inodes, + }) + } } #[vtable]