Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(383)

Unified Diff: mojo/public/rust/src/bindings/mojom.rs

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/public/rust/src/bindings/mod.rs ('k') | mojo/public/rust/src/bindings/run_loop.rs » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/public/rust/src/bindings/mojom.rs
diff --git a/mojo/public/rust/src/bindings/mojom.rs b/mojo/public/rust/src/bindings/mojom.rs
deleted file mode 100644
index 8401bb7ddbe3b94fa39acf702b9da000a08369e3..0000000000000000000000000000000000000000
--- a/mojo/public/rust/src/bindings/mojom.rs
+++ /dev/null
@@ -1,897 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use bindings::decoding::{Decoder, ValidationError};
-use bindings::encoding;
-use bindings::encoding::{Bits, Encoder, Context, DATA_HEADER_SIZE, DataHeader, DataHeaderValue};
-use bindings::message::MessageHeader;
-
-use std::cmp::Eq;
-use std::collections::HashMap;
-use std::hash::Hash;
-use std::mem;
-use std::panic;
-use std::ptr;
-use std::vec::Vec;
-
-use system::{MojoResult, CastHandle, Handle, UntypedHandle};
-use system::data_pipe;
-use system::message_pipe;
-use system::shared_buffer;
-use system::wait_set;
-
-/// The size of a Mojom map plus header in bytes.
-const MAP_SIZE: usize = 24;
-
-/// The sorted set of versions for a map.
-const MAP_VERSIONS: [(u32, u32); 1] = [(0, MAP_SIZE as u32)];
-
-/// The size of a Mojom union in bytes (header included).
-pub const UNION_SIZE: usize = 16;
-
-/// The size of a Mojom pointer in bits.
-pub const POINTER_BIT_SIZE: Bits = Bits(64);
-
-/// The value of a Mojom null pointer.
-pub const MOJOM_NULL_POINTER: u64 = 0;
-
-/// An enumeration of all the possible low-level Mojom types.
-pub enum MojomType {
- Simple,
- Pointer,
- Union,
- Handle,
- Interface,
-}
-
-/// Whatever implements this trait can be serialized in the Mojom format.
-pub trait MojomEncodable: Sized {
- /// Get the Mojom type.
- fn mojom_type() -> MojomType;
-
- /// Get this type's Mojom alignment.
- fn mojom_alignment() -> usize;
-
- /// The amount of space in bits the type takes up when inlined
- /// into another type at serialization time.
- fn embed_size(context: &Context) -> Bits;
-
- /// Recursively computes the size of the complete Mojom archive
- /// starting from this type.
- fn compute_size(&self, context: Context) -> usize;
-
- /// Encodes this type into the encoder given a context.
- fn encode(self, encoder: &mut Encoder, context: Context);
-
- /// Using a decoder, decodes itself out of a byte buffer.
- fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError>;
-}
-
-/// Whatever implements this trait is a Mojom pointer type which means
-/// that on encode, a pointer is inlined and the implementer is
-/// serialized elsewhere in the output buffer.
-pub trait MojomPointer: MojomEncodable {
- /// Get the DataHeader meta-data for this pointer type.
- fn header_data(&self) -> DataHeaderValue;
-
- /// Get the size of only this type when serialized.
- fn serialized_size(&self, context: &Context) -> usize;
-
- /// Encodes the actual values of the type into the encoder.
- fn encode_value(self, encoder: &mut Encoder, context: Context);
-
- /// Decodes the actual values of the type into the decoder.
- fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError>;
-
- /// Writes a pointer inlined into the current context before calling
- /// encode_value.
- fn encode_new(self, encoder: &mut Encoder, context: Context) {
- let data_size = self.serialized_size(&context);
- let data_header = DataHeader::new(data_size, self.header_data());
- let new_context = encoder.add(&data_header).unwrap();
- self.encode_value(encoder, new_context);
- }
-
- /// Reads a pointer inlined into the current context before calling
- /// decode_value.
- fn decode_new(decoder: &mut Decoder, _context: Context, pointer: u64) -> Result<Self, ValidationError> {
- match decoder.claim(pointer as usize) {
- Ok(new_context) => Self::decode_value(decoder, new_context),
- Err(err) => Err(err),
- }
- }
-}
-
-/// Whatever implements this trait is a Mojom union type which means that
-/// on encode it is inlined, but if the union is nested inside of another
-/// union type, it is treated as a pointer type.
-pub trait MojomUnion: MojomEncodable {
- /// Get the union's current tag.
- fn get_tag(&self) -> u32;
-
- /// Encode the actual value of the union.
- fn encode_value(self, encoder: &mut Encoder, context: Context);
-
- /// Decode the actual value of the union.
- fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError>;
-
- /// The embed_size for when the union acts as a pointer type.
- fn nested_embed_size() -> Bits {
- POINTER_BIT_SIZE
- }
-
- /// The encoding routine for when the union acts as a pointer type.
- fn nested_encode(self, encoder: &mut Encoder, context: Context) {
- let loc = encoder.size() as u64;
- {
- let state = encoder.get_mut(&context);
- state.encode_pointer(loc);
- }
- let tag = DataHeaderValue::UnionTag(self.get_tag());
- let data_header = DataHeader::new(UNION_SIZE, tag);
- let new_context = encoder.add(&data_header).unwrap();
- self.encode_value(encoder, new_context.set_is_union(true));
- }
-
- /// The decoding routine for when the union acts as a pointer type.
- fn nested_decode(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError> {
- let global_offset = {
- let state = decoder.get_mut(&context);
- match state.decode_pointer() {
- Some(ptr) => ptr as usize,
- None => return Err(ValidationError::IllegalPointer),
- }
- };
- if global_offset == (MOJOM_NULL_POINTER as usize) {
- return Err(ValidationError::UnexpectedNullPointer);
- }
- match decoder.claim(global_offset as usize) {
- Ok(new_context) => Self::decode_value(decoder, new_context),
- Err(err) => Err(err),
- }
- }
-
- /// The embed_size for when the union is inlined into the current context.
- fn inline_embed_size() -> Bits {
- Bits(8 * (UNION_SIZE as usize))
- }
-
- /// The encoding routine for when the union is inlined into the current context.
- fn inline_encode(self, encoder: &mut Encoder, context: Context) {
- {
- let mut state = encoder.get_mut(&context);
- state.align_to_bytes(8);
- state.encode(UNION_SIZE as u32);
- state.encode(self.get_tag());
- }
- self.encode_value(encoder, context.clone());
- {
- let mut state = encoder.get_mut(&context);
- state.align_to_bytes(8);
- state.align_to_byte();
- }
- }
-
- /// The decoding routine for when the union is inlined into the current context.
- fn inline_decode(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError> {
- {
- let mut state = decoder.get_mut(&context);
- state.align_to_byte();
- state.align_to_bytes(8);
- }
- let value = Self::decode_value(decoder, context.clone());
- {
- let mut state = decoder.get_mut(&context);
- state.align_to_byte();
- state.align_to_bytes(8);
- }
- value
- }
-}
-
-/// A marker trait that marks Mojo handles as encodable.
-pub trait MojomHandle: CastHandle + MojomEncodable {}
-
-/// Whatever implements this trait is considered to be a Mojom
-/// interface, that is, a message pipe which conforms to some
-/// messaging interface.
-///
-/// We force an underlying message pipe to be used via the pipe()
-/// and unwrap() routines.
-pub trait MojomInterface: MojomEncodable {
- /// Get the service name for this interface.
- fn service_name() -> &'static str;
-
- /// Get the version for this interface.
- fn version(&self) -> u32;
-
- /// Access the underlying message pipe for this interface.
- fn pipe(&self) -> &message_pipe::MessageEndpoint;
-
- /// Unwrap the interface into its underlying message pipe.
- fn unwrap(self) -> message_pipe::MessageEndpoint;
-}
-
-/// An error that may occur when sending data over a Mojom interface.
-#[derive(Debug)]
-pub enum MojomSendError {
- /// Failed to write to the underlying message pipe.
- FailedWrite(MojoResult),
-
- /// The version is too old to write the attempted message.
- OldVersion(u32, u32),
-}
-
-/// Whatever implements this trait is considered to be a Mojom
-/// interface that may send messages of some generic type.
-///
-/// When implementing this trait, the correct way is to specify
-/// a tighter trait bound than MojomMessage that limits the types
-/// available for sending to those that are valid messages available
-/// to the interface.
-///
-/// TODO(mknyszek): Add sending control messages
-pub trait MojomInterfaceSend<R: MojomMessage>: MojomInterface {
- /// Creates a message.
- fn create_request(&self, req_id: u64, payload: R) -> (Vec<u8>, Vec<UntypedHandle>) {
- let mut header = R::create_header();
- header.request_id = req_id;
- let header_size = header.compute_size(Default::default());
- let size = header_size + payload.compute_size(Default::default());
- let mut buffer: Vec<u8> = Vec::with_capacity(size);
- buffer.resize(size, 0);
- let handles = {
- let (header_buf, rest_buf) = buffer.split_at_mut(header_size);
- let mut handles = header.serialize(header_buf);
- handles.extend(payload.serialize(rest_buf).into_iter());
- handles
- };
- (buffer, handles)
- }
-
- /// Creates and sends a message, and returns its request ID.
- fn send_request(&self, req_id: u64, payload: R) -> Result<(), MojomSendError> {
- if self.version() < R::min_version() {
- return Err(MojomSendError::OldVersion(self.version(), R::min_version()));
- }
- let (buffer, handles) = self.create_request(req_id, payload);
- match self.pipe().write(&buffer, handles, mpflags!(Write::None)) {
- MojoResult::Okay => Ok(()),
- err => Err(MojomSendError::FailedWrite(err)),
- }
- }
-}
-
-/// An error that may occur when attempting to recieve a message over a
-/// Mojom interface.
-#[derive(Debug)]
-pub enum MojomRecvError {
- /// Failed to read from the underlying message pipe.
- FailedRead(MojoResult),
-
- /// Failed to validate the buffer during decode.
- FailedValidation(ValidationError),
-}
-
-/// Whatever implements this trait is considered to be a Mojom
-/// interface that may recieve messages for some interface.
-///
-/// When implementing this trait, specify the container "union" type
-/// which can contain any of the potential messages that may be recieved.
-/// This way, we can return that type and let the user multiplex over
-/// what message was received.
-///
-/// TODO(mknyszek): Add responding to control messages
-pub trait MojomInterfaceRecv: MojomInterface {
- type Container: MojomMessageOption;
-
- /// Tries to read a message from a pipe and decodes it.
- fn recv_response(&self) -> Result<(u64, Self::Container), MojomRecvError> {
- match self.pipe().read(mpflags!(Read::None)) {
- Ok((buffer, handles)) => {
- match Self::Container::decode_message(buffer, handles) {
- Ok((req_id, val)) => Ok((req_id, val)),
- Err(err) => Err(MojomRecvError::FailedValidation(err)),
- }
- },
- Err(err) => Err(MojomRecvError::FailedRead(err)),
- }
- }
-}
-
-/// Whatever implements this trait is considered to be a Mojom struct.
-///
-/// Mojom structs are always the root of any Mojom message. Thus, we
-/// provide convenience functions for serialization here.
-pub trait MojomStruct: MojomPointer {
- /// Given a pre-allocated buffer, the struct serializes itself.
- fn serialize(self, buffer: &mut [u8]) -> Vec<UntypedHandle> {
- let mut encoder = Encoder::new(buffer);
- self.encode_new(&mut encoder, Default::default());
- encoder.unwrap()
- }
-
- /// The struct computes its own size, allocates a buffer, and then
- /// serializes itself into that buffer.
- fn auto_serialize(self) -> (Vec<u8>, Vec<UntypedHandle>) {
- let size = self.compute_size(Default::default());
- let mut buf = Vec::with_capacity(size);
- buf.resize(size, 0);
- let handles = self.serialize(&mut buf);
- (buf, handles)
- }
-
- /// Decode the type from a byte array and a set of handles.
- fn deserialize(buffer: &[u8], handles: Vec<UntypedHandle>) -> Result<Self, ValidationError> {
- let mut decoder = Decoder::new(buffer, handles);
- Self::decode_new(&mut decoder, Default::default(), 0)
- }
-}
-
-/// Marks a MojomStruct as being capable of being sent across some
-/// Mojom interface.
-pub trait MojomMessage: MojomStruct {
- fn min_version() -> u32;
- fn create_header() -> MessageHeader;
-}
-
-/// The trait for a "container" type intended to be used in MojomInterfaceRecv.
-///
-/// This trait contains the decode logic which decodes based on the message header
-/// and returns itself: a union type which may contain any of the possible messages
-/// that may be sent across this interface.
-pub trait MojomMessageOption: Sized {
- /// Decodes the actual payload of the message.
- ///
- /// Implemented by a code generator.
- fn decode_payload(header: MessageHeader, buffer: &[u8], handles: Vec<UntypedHandle>) -> Result<Self, ValidationError>;
-
- /// Decodes the message header and then the payload, returning a new
- /// copy of itself and the request ID found in the header.
- fn decode_message(buffer: Vec<u8>, handles: Vec<UntypedHandle>) -> Result<(u64, Self), ValidationError> {
- let header = try!(MessageHeader::deserialize(&buffer[..], Vec::new()));
- let payload_buffer = &buffer[header.serialized_size(&Default::default())..];
- let req_id = header.request_id;
- let ret = try!(Self::decode_payload(header, payload_buffer, handles));
- Ok((req_id, ret))
- }
-}
-
-// ********************************************** //
-// ****** IMPLEMENTATIONS FOR COMMON TYPES ****** //
-// ********************************************** //
-
-macro_rules! impl_encodable_for_prim {
- ($($prim_type:ty),*) => {
- $(
- impl MojomEncodable for $prim_type {
- fn mojom_type() -> MojomType {
- MojomType::Simple
- }
- fn mojom_alignment() -> usize {
- mem::size_of::<$prim_type>()
- }
- fn embed_size(_context: &Context) -> Bits {
- Bits(8 * mem::size_of::<$prim_type>())
- }
- fn compute_size(&self, _context: Context) -> usize {
- 0 // Indicates that this type is inlined and it adds nothing external to the size
- }
- fn encode(self, encoder: &mut Encoder, context: Context) {
- let mut state = encoder.get_mut(&context);
- state.encode(self);
- }
- fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError> {
- let mut state = decoder.get_mut(&context);
- Ok(state.decode::<Self>())
- }
- }
- )*
- }
-}
-
-impl_encodable_for_prim!(i8, i16, i32, i64, u8, u16, u32, u64, f32, f64);
-
-impl MojomEncodable for bool {
- fn mojom_alignment() -> usize {
- panic!("Should never check_decode mojom_alignment of bools (they're bit-aligned)!");
- }
- fn mojom_type() -> MojomType {
- MojomType::Simple
- }
- fn embed_size(_context: &Context) -> Bits {
- Bits(1)
- }
- fn compute_size(&self, _context: Context) -> usize {
- 0 // Indicates that this type is inlined and it adds nothing external to the size
- }
- fn encode(self, encoder: &mut Encoder, context: Context) {
- let mut state = encoder.get_mut(&context);
- state.encode_bool(self);
- }
- fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError> {
- let mut state = decoder.get_mut(&context);
- Ok(state.decode_bool())
- }
-}
-
-// Options should be considered to represent nullability the Mojom IDL.
-// Any type wrapped in an Option type is nullable.
-
-impl<T: MojomEncodable> MojomEncodable for Option<T> {
- fn mojom_alignment() -> usize {
- T::mojom_alignment()
- }
- fn mojom_type() -> MojomType {
- T::mojom_type()
- }
- fn embed_size(context: &Context) -> Bits {
- T::embed_size(context)
- }
- fn compute_size(&self, context: Context) -> usize {
- match *self {
- Some(ref value) => value.compute_size(context),
- None => 0,
- }
- }
- fn encode(self, encoder: &mut Encoder, context: Context) {
- match self {
- Some(value) => value.encode(encoder, context),
- None => {
- let mut state = encoder.get_mut(&context);
- match T::mojom_type() {
- MojomType::Pointer => state.encode_null_pointer(),
- MojomType::Union => state.encode_null_union(),
- MojomType::Handle => state.encode_null_handle(),
- MojomType::Interface => {
- state.encode_null_handle();
- state.encode(0 as u32);
- },
- MojomType::Simple => panic!("Unexpected simple type in Option!"),
- }
- },
- }
- }
- fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError> {
- let skipped = {
- let mut state = decoder.get_mut(&context);
- match T::mojom_type() {
- MojomType::Pointer => state.skip_if_null_pointer(),
- MojomType::Union => state.skip_if_null_union(),
- MojomType::Handle => state.skip_if_null_handle(),
- MojomType::Interface => state.skip_if_null_interface(),
- MojomType::Simple => panic!("Unexpected simple type in Option!"),
- }
- };
- if skipped {
- Ok(None)
- } else {
- match T::decode(decoder, context) {
- Ok(value) => Ok(Some(value)),
- Err(err) => Err(err),
- }
- }
- }
-}
-
-macro_rules! impl_pointer_for_array {
- () => {
- fn header_data(&self) -> DataHeaderValue {
- DataHeaderValue::Elements(self.len() as u32)
- }
- fn serialized_size(&self, context: &Context) -> usize {
- DATA_HEADER_SIZE + if self.len() > 0 {
- (T::embed_size(context) * self.len()).as_bytes()
- } else {
- 0
- }
- }
- }
-}
-
-macro_rules! impl_encodable_for_array {
- () => {
- impl_encodable_for_pointer!();
- fn compute_size(&self, context: Context) -> usize {
- let mut size = encoding::align_default(self.serialized_size(&context));
- for elem in self.iter() {
- size += elem.compute_size(context.clone());
- }
- size
- }
- }
-}
-
-impl<T: MojomEncodable> MojomPointer for Vec<T> {
- impl_pointer_for_array!();
- fn encode_value(self, encoder: &mut Encoder, context: Context) {
- for elem in self.into_iter() {
- elem.encode(encoder, context.clone());
- }
- }
- fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Vec<T>, ValidationError> {
- let elems = {
- let mut state = decoder.get_mut(&context);
- match state.decode_array_header::<T>() {
- Ok(header) => header.data(),
- Err(err) => return Err(err),
- }
- };
- let mut value = Vec::with_capacity(elems as usize);
- for _ in 0..elems {
- match T::decode(decoder, context.clone()) {
- Ok(elem) => value.push(elem),
- Err(err) => return Err(err),
- }
- }
- Ok(value)
- }
-}
-
-impl<T: MojomEncodable> MojomEncodable for Vec<T> {
- impl_encodable_for_array!();
-}
-
-macro_rules! impl_encodable_for_fixed_array {
- ($($len:expr),*) => {
- $(
- impl<T: MojomEncodable> MojomPointer for [T; $len] {
- impl_pointer_for_array!();
- fn encode_value(mut self, encoder: &mut Encoder, context: Context) {
- let mut panic_error = None;
- let mut moves = 0;
- unsafe {
- // In order to move elements out of an array we need to replace the
- // value with uninitialized memory.
- for elem in self.iter_mut() {
- let owned_elem = mem::replace(elem, mem::uninitialized());
- // We need to handle if an unwinding panic happens to prevent use of
- // uninitialized memory...
- let next_context = context.clone();
- // We assert everything going into this closure is unwind safe. If anything
- // is added, PLEASE make sure it is also unwind safe...
- let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
- owned_elem.encode(encoder, next_context);
- }));
- if let Err(err) = result {
- panic_error = Some(err);
- break;
- }
- moves += 1;
- }
- if let Some(err) = panic_error {
- for i in moves..self.len() {
- ptr::drop_in_place(&mut self[i] as *mut T);
- }
- // Forget the array to prevent a drop
- mem::forget(self);
- // Continue unwinding
- panic::resume_unwind(err);
- }
- // We cannot risk drop() getting run on the array values, so we just
- // forget self.
- mem::forget(self);
- }
- }
- fn decode_value(decoder: &mut Decoder, context: Context) -> Result<[T; $len], ValidationError> {
- let elems = {
- let mut state = decoder.get_mut(&context);
- match state.decode_array_header::<T>() {
- Ok(header) => header.data(),
- Err(err) => return Err(err),
- }
- };
- if elems != $len {
- return Err(ValidationError::UnexpectedArrayHeader);
- }
- let mut array: [T; $len];
- let mut panic_error = None;
- let mut inits = 0;
- let mut error = None;
- unsafe {
- // Since we don't force Clone to be implemented on Mojom types
- // (mainly due to handles) we need to create this array as uninitialized
- // and initialize it manually.
- array = mem::uninitialized();
- for elem in &mut array[..] {
- // When a panic unwinds it may try to read and drop uninitialized
- // memory, so we need to catch this. However, we pass mutable state!
- // This could be bad as we could observe a broken invariant inside
- // of decoder and access it as usual, but we do NOT access decoder
- // here, nor do we ever unwind through one of decoder's methods.
- // Therefore, it should be safe to assert that decoder is unwind safe.
- let next_context = context.clone();
- // We assert everything going into this closure is unwind safe. If anything
- // is added, PLEASE make sure it is also unwind safe...
- let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
- T::decode(decoder, next_context)
- }));
- match result {
- Ok(non_panic_value) => match non_panic_value {
- Ok(value) => ptr::write(elem, value),
- Err(err) => {
- error = Some(err);
- break;
- },
- },
- Err(err) => {
- panic_error = Some(err);
- break;
- },
- }
- inits += 1;
- }
- if panic_error.is_some() || error.is_some() {
- // Drop everything that was initialized
- for i in 0..inits {
- ptr::drop_in_place(&mut array[i] as *mut T);
- }
- // Forget the array to prevent a drop
- mem::forget(array);
- if let Some(err) = panic_error {
- panic::resume_unwind(err);
- }
- return Err(error.take().expect("Corrupted stack?"));
- }
- }
- Ok(array)
- }
- }
- impl<T: MojomEncodable> MojomEncodable for [T; $len] {
- impl_encodable_for_array!();
- }
- )*
- }
-}
-
-// Unfortunately, we cannot be generic over the length of a fixed array
-// even though its part of the type (this will hopefully be added in the
-// future) so for now we implement encodable for only the first 33 fixed
-// size array types.
-impl_encodable_for_fixed_array!( 0, 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);
-
-impl<T: MojomEncodable> MojomPointer for Box<[T]> {
- impl_pointer_for_array!();
- fn encode_value(self, encoder: &mut Encoder, context: Context) {
- for elem in self.into_vec().into_iter() {
- elem.encode(encoder, context.clone());
- }
- }
- fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Box<[T]>, ValidationError> {
- match Vec::<T>::decode_value(decoder, context) {
- Ok(vec) => Ok(vec.into_boxed_slice()),
- Err(err) => Err(err),
- }
- }
-}
-
-impl<T: MojomEncodable> MojomEncodable for Box<[T]> {
- impl_encodable_for_array!();
-}
-
-// We can represent a Mojom string as just a Rust String type
-// since both are UTF-8.
-impl MojomPointer for String {
- fn header_data(&self) -> DataHeaderValue {
- DataHeaderValue::Elements(self.len() as u32)
- }
- fn serialized_size(&self, _context: &Context) -> usize {
- DATA_HEADER_SIZE + self.len()
- }
- fn encode_value(self, encoder: &mut Encoder, context: Context) {
- for byte in self.as_bytes() {
- byte.encode(encoder, context.clone());
- }
- }
- fn decode_value(decoder: &mut Decoder, context: Context) -> Result<String, ValidationError> {
- let mut state = decoder.get_mut(&context);
- let elems = match state.decode_array_header::<u8>() {
- Ok(header) => header.data(),
- Err(err) => return Err(err),
- };
- let mut value = Vec::with_capacity(elems as usize);
- for _ in 0..elems {
- value.push(state.decode::<u8>());
- }
- match String::from_utf8(value) {
- Ok(string) => Ok(string),
- Err(err) => panic!("Error decoding String: {}", err),
- }
- }
-}
-
-impl MojomEncodable for String {
- impl_encodable_for_pointer!();
- fn compute_size(&self, context: Context) -> usize {
- encoding::align_default(self.serialized_size(&context))
- }
-}
-
-/// Helper function to clean up duplicate code in HashMap.
-fn array_claim_and_decode_header<T: MojomEncodable>(decoder: &mut Decoder, offset: usize) -> Result<(Context, usize), ValidationError> {
- let context = match decoder.claim(offset) {
- Ok(new_context) => new_context,
- Err(err) => return Err(err),
- };
- let elems = {
- let state = decoder.get_mut(&context);
- match state.decode_array_header::<T>() {
- Ok(header) => header.data(),
- Err(err) => return Err(err),
- }
- };
- Ok((context, elems as usize))
-}
-
-impl<K: MojomEncodable + Eq + Hash, V: MojomEncodable> MojomPointer for HashMap<K, V> {
- fn header_data(&self) -> DataHeaderValue {
- DataHeaderValue::Version(0)
- }
- fn serialized_size(&self, _context: &Context) -> usize {
- MAP_SIZE
- }
- fn encode_value(self, encoder: &mut Encoder, context: Context) {
- let elems = self.len();
- let meta_value = DataHeaderValue::Elements(elems as u32);
- // We need to move values into this vector because we can't copy the keys.
- // (Handles are not copyable so MojomEncodable cannot be copyable!)
- let mut vals_vec = Vec::with_capacity(elems);
- // Key setup
- // Write a pointer to the keys array.
- let keys_loc = encoder.size() as u64;
- {
- let state = encoder.get_mut(&context);
- state.encode_pointer(keys_loc);
- }
- // Create the keys data header
- let keys_bytes = DATA_HEADER_SIZE + (K::embed_size(&context) * elems).as_bytes();
- let keys_data_header = DataHeader::new(keys_bytes, meta_value);
- // Claim space for the keys array in the encoder
- let keys_context = encoder.add(&keys_data_header).unwrap();
- // Encode keys, setup vals
- for (key, value) in self.into_iter() {
- key.encode(encoder, keys_context.clone());
- vals_vec.push(value);
- }
- // Encode vals
- vals_vec.encode(encoder, context.clone())
- }
- fn decode_value(decoder: &mut Decoder, context: Context) -> Result<HashMap<K, V>, ValidationError> {
- let (keys_offset, vals_offset) = {
- let state = decoder.get_mut(&context);
- match state.decode_struct_header(&MAP_VERSIONS) {
- Ok(_) => (),
- Err(err) => return Err(err),
- };
- // Decode the keys pointer and check for overflow
- let keys_offset = match state.decode_pointer() {
- Some(ptr) => ptr,
- None => return Err(ValidationError::IllegalPointer),
- };
- // Decode the keys pointer and check for overflow
- let vals_offset = match state.decode_pointer() {
- Some(ptr) => ptr,
- None => return Err(ValidationError::IllegalPointer),
- };
- if keys_offset == MOJOM_NULL_POINTER || vals_offset == MOJOM_NULL_POINTER {
- return Err(ValidationError::UnexpectedNullPointer);
- }
- (keys_offset as usize, vals_offset as usize)
- };
- let (keys_context, keys_elems) = match array_claim_and_decode_header::<K>(decoder, keys_offset) {
- Ok((context, elems)) => (context, elems),
- Err(err) => return Err(err),
- };
- let mut keys_vec: Vec<K> = Vec::with_capacity(keys_elems as usize);
- for _ in 0..keys_elems {
- let key = match K::decode(decoder, keys_context.clone()) {
- Ok(value) => value,
- Err(err) => return Err(err),
- };
- keys_vec.push(key);
- }
- let (vals_context, vals_elems) = match array_claim_and_decode_header::<V>(decoder, vals_offset) {
- Ok((context, elems)) => (context, elems),
- Err(err) => return Err(err),
- };
- if keys_elems != vals_elems {
- return Err(ValidationError::DifferentSizedArraysInMap);
- }
- let mut map = HashMap::with_capacity(keys_elems as usize);
- for key in keys_vec.into_iter() {
- let val = match V::decode(decoder, vals_context.clone()) {
- Ok(value) => value,
- Err(err) => return Err(err),
- };
- map.insert(key, val);
- }
- Ok(map)
- }
-}
-
-impl<K: MojomEncodable + Eq + Hash, V: MojomEncodable> MojomEncodable for HashMap<K, V> {
- impl_encodable_for_pointer!();
- fn compute_size(&self, context: Context) -> usize {
- let mut size = encoding::align_default(self.serialized_size(&context));
- // The size of the one array
- size += DATA_HEADER_SIZE;
- size += (K::embed_size(&context) * self.len()).as_bytes();
- size = encoding::align_default(size);
- // Any extra space used by the keys
- for (key, _) in self {
- size += key.compute_size(context.clone());
- }
- // Need to re-align after this for the next array
- size = encoding::align_default(size);
- // The size of the one array
- size += DATA_HEADER_SIZE;
- size += (V::embed_size(&context) * self.len()).as_bytes();
- size = encoding::align_default(size);
- // Any extra space used by the values
- for (_, value) in self {
- size += value.compute_size(context.clone());
- }
- // Align one more time at the end to keep the next object aligned.
- encoding::align_default(size)
- }
-}
-
-impl<T: MojomEncodable + CastHandle + Handle> MojomHandle for T {}
-
-macro_rules! impl_encodable_for_handle {
- ($handle_type:path) => {
- fn mojom_alignment() -> usize {
- 4
- }
- fn mojom_type() -> MojomType {
- MojomType::Handle
- }
- fn embed_size(_context: &Context) -> Bits {
- Bits(8 * mem::size_of::<u32>())
- }
- fn compute_size(&self, _context: Context) -> usize {
- 0
- }
- fn encode(self, encoder: &mut Encoder, context: Context) {
- let pos = encoder.add_handle(self.as_untyped());
- let mut state = encoder.get_mut(&context);
- state.encode(pos as i32);
- }
- fn decode(decoder: &mut Decoder, context: Context) -> Result<$handle_type, ValidationError> {
- let handle_index = {
- let mut state = decoder.get_mut(&context);
- state.decode::<i32>()
- };
- decoder.claim_handle::<$handle_type>(handle_index)
- }
- }
-}
-
-impl MojomEncodable for UntypedHandle {
- impl_encodable_for_handle!(UntypedHandle);
-}
-
-impl MojomEncodable for message_pipe::MessageEndpoint {
- impl_encodable_for_handle!(message_pipe::MessageEndpoint);
-}
-
-impl MojomEncodable for shared_buffer::SharedBuffer {
- impl_encodable_for_handle!(shared_buffer::SharedBuffer);
-}
-
-impl<T> MojomEncodable for data_pipe::Consumer<T> {
- impl_encodable_for_handle!(data_pipe::Consumer<T>);
-}
-
-impl<T> MojomEncodable for data_pipe::Producer<T> {
- impl_encodable_for_handle!(data_pipe::Producer<T>);
-}
-
-impl MojomEncodable for wait_set::WaitSet {
- impl_encodable_for_handle!(wait_set::WaitSet);
-}
« no previous file with comments | « mojo/public/rust/src/bindings/mod.rs ('k') | mojo/public/rust/src/bindings/run_loop.rs » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698