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); |
-} |