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

Unified Diff: mojo/public/rust/src/bindings/decoding.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/build.rs ('k') | mojo/public/rust/src/bindings/encoding.rs » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/public/rust/src/bindings/decoding.rs
diff --git a/mojo/public/rust/src/bindings/decoding.rs b/mojo/public/rust/src/bindings/decoding.rs
deleted file mode 100644
index 81c7ee769f06c88bc45039821007bdd11880ba1a..0000000000000000000000000000000000000000
--- a/mojo/public/rust/src/bindings/decoding.rs
+++ /dev/null
@@ -1,381 +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::encoding::{Bits, Context, DataHeader, DataHeaderValue, DATA_HEADER_SIZE,
- MojomNumeric};
-use bindings::mojom::{MojomEncodable, MOJOM_NULL_POINTER, UNION_SIZE};
-use bindings::util;
-
-use std::mem;
-use std::ptr;
-use std::vec::Vec;
-
-use system;
-use system::{Handle, CastHandle, UntypedHandle};
-
-#[derive(Debug, Eq, PartialEq)]
-pub enum ValidationError {
- DifferentSizedArraysInMap,
- IllegalHandle,
- IllegalMemoryRange,
- IllegalPointer,
- MessageHeaderInvalidFlags,
- MessageHeaderMissingRequestId,
- MessageHeaderUnknownMethod,
- MisalignedObject,
- UnexpectedArrayHeader,
- UnexpectedInvalidHandle,
- UnexpectedNullPointer,
- UnexpectedNullUnion,
- UnexpectedStructHeader,
-}
-
-impl ValidationError {
- pub fn as_str(self) -> &'static str {
- match self {
- ValidationError::DifferentSizedArraysInMap => "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP",
- ValidationError::IllegalHandle => "VALIDATION_ERROR_ILLEGAL_HANDLE",
- ValidationError::IllegalMemoryRange => "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE",
- ValidationError::IllegalPointer => "VALIDATION_ERROR_ILLEGAL_POINTER",
- ValidationError::MessageHeaderInvalidFlags => "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS",
- ValidationError::MessageHeaderMissingRequestId => "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID",
- ValidationError::MessageHeaderUnknownMethod => "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD",
- ValidationError::MisalignedObject => "VALIDATION_ERROR_MISALIGNED_OBJECT",
- ValidationError::UnexpectedArrayHeader => "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER",
- ValidationError::UnexpectedInvalidHandle => "VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE",
- ValidationError::UnexpectedNullPointer => "VALIDATION_ERROR_UNEXPECTED_NULL_POINTER",
- ValidationError::UnexpectedNullUnion => "VALIDATION_ERROR_UNEXPECTED_NULL_UNION",
- ValidationError::UnexpectedStructHeader => "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER",
- }
- }
-}
-
-/// An decoding state represents the decoding logic for a single
-/// Mojom object that is NOT inlined, such as a struct or an array.
-pub struct DecodingState<'slice> {
- /// The buffer the state may write to.
- data: &'slice [u8],
-
- /// The offset of this serialized object into the overall buffer.
- global_offset: usize,
-
- /// The current offset within 'data'.
- offset: usize,
-
- /// The current bit offset within 'data'.
- bit_offset: Bits,
-}
-
-impl<'slice> DecodingState<'slice> {
- /// Create a new decoding state.
- pub fn new(buffer: &'slice [u8], offset: usize) -> DecodingState<'slice> {
- DecodingState {
- data: buffer,
- global_offset: offset,
- offset: 0,
- bit_offset: Bits(0),
- }
- }
-
- /// Align the decoding state to the next byte.
- pub fn align_to_byte(&mut self) {
- if self.bit_offset > Bits(0) {
- self.offset += 1;
- self.bit_offset = Bits(0);
- }
- }
-
- /// Align the decoding state to the next 'bytes' boundary.
- pub fn align_to_bytes(&mut self, bytes: usize) {
- if self.offset != 0 {
- self.offset = util::align_bytes(self.offset, bytes);
- }
- }
-
- /// Read a primitive from the buffer without incrementing the offset.
- fn read_in_place<T: MojomNumeric>(&mut self) -> T {
- let mut value: T = Default::default();
- debug_assert!(mem::size_of::<T>() + self.offset <= self.data.len());
- let ptr = (&self.data[self.offset..]).as_ptr();
- unsafe {
- ptr::copy_nonoverlapping(mem::transmute::<*const u8, *const T>(ptr),
- &mut value as *mut T,
- 1);
- }
- value
- }
-
- /// Read a primitive from the buffer and increment the offset.
- fn read<T: MojomNumeric>(&mut self) -> T {
- let value = self.read_in_place::<T>();
- self.bit_offset = Bits(0);
- self.offset += mem::size_of::<T>();
- value
- }
-
- /// Decode a primitive from the buffer, naturally aligning before we read.
- pub fn decode<T: MojomNumeric>(&mut self) -> T {
- self.align_to_byte();
- self.align_to_bytes(mem::size_of::<T>());
- self.read::<T>()
- }
-
- /// Decode a boolean value from the buffer as one bit.
- pub fn decode_bool(&mut self) -> bool {
- let offset = self.offset;
- // Check the bit by getting the set bit and checking if its non-zero
- let value = (self.data[offset] & self.bit_offset.as_set_bit()) > 0;
- self.bit_offset += Bits(1);
- let (bits, bytes) = self.bit_offset.as_bits_and_bytes();
- self.offset += bytes;
- self.bit_offset = bits;
- value
- }
-
- /// If we encounter a null pointer, increment past it.
- ///
- /// Returns if we skipped or not.
- pub fn skip_if_null_pointer(&mut self) -> bool {
- self.align_to_byte();
- self.align_to_bytes(8);
- let ptr = self.read_in_place::<u64>();
- if ptr == MOJOM_NULL_POINTER {
- self.offset += 8;
- }
- (ptr == MOJOM_NULL_POINTER)
- }
-
- /// If we encounter a null union, increment past it.
- ///
- /// Returns if we skipped or not.
- pub fn skip_if_null_union(&mut self) -> bool {
- self.align_to_byte();
- self.align_to_bytes(8);
- let size = self.read_in_place::<u32>();
- if size == 0 {
- self.offset += UNION_SIZE;
- }
- (size == 0)
- }
-
- /// If we encounter a null handle, increment past it.
- ///
- /// Returns if we skipped or not.
- pub fn skip_if_null_handle(&mut self) -> bool {
- self.align_to_byte();
- self.align_to_bytes(4);
- let index = self.read_in_place::<i32>();
- if index < 0 {
- self.offset += 4;
- }
- (index < 0)
- }
-
- /// If we encounter a null interface, increment past it.
- ///
- /// Returns if we skipped or not.
- pub fn skip_if_null_interface(&mut self) -> bool {
- self.align_to_byte();
- self.align_to_bytes(4);
- let index = self.read_in_place::<i32>();
- if index < 0 {
- self.offset += 8;
- }
- (index < 0)
- }
-
- /// Decode a pointer from the buffer as a global offset into the buffer.
- ///
- /// The pointer in the buffer is an offset relative to the pointer to another
- /// location in the buffer. We convert that to an absolute offset with respect
- /// to the buffer before returning. This is our defintion of a pointer.
- pub fn decode_pointer(&mut self) -> Option<u64> {
- self.align_to_byte();
- self.align_to_bytes(8);
- let current_location = (self.global_offset + self.offset) as u64;
- let offset = self.read::<u64>();
- if offset == MOJOM_NULL_POINTER {
- Some(MOJOM_NULL_POINTER)
- } else {
- offset.checked_add(current_location)
- }
- }
-
- /// A routine for decoding an array header.
- ///
- /// Must be called with offset zero (that is, it must be the first thing
- /// decoded). Performs numerous validation checks.
- pub fn decode_array_header<T>(&mut self) -> Result<DataHeader, ValidationError>
- where T: MojomEncodable
- {
- debug_assert_eq!(self.offset, 0);
- // Make sure we can read the size first...
- if self.data.len() < mem::size_of::<u32>() {
- return Err(ValidationError::UnexpectedArrayHeader);
- }
- let bytes = self.decode::<u32>();
- if (bytes as usize) < DATA_HEADER_SIZE {
- return Err(ValidationError::UnexpectedArrayHeader);
- }
- let elems = self.decode::<u32>();
- match T::embed_size(&Default::default()).checked_mul(elems as usize) {
- Some(value) => {
- if (bytes as usize) < value.as_bytes() + DATA_HEADER_SIZE {
- return Err(ValidationError::UnexpectedArrayHeader);
- }
- }
- None => return Err(ValidationError::UnexpectedArrayHeader),
- }
- Ok(DataHeader::new(bytes as usize, DataHeaderValue::Elements(elems)))
- }
-
- /// A routine for decoding an struct header.
- ///
- /// Must be called with offset zero (that is, it must be the first thing
- /// decoded). Performs numerous validation checks.
- pub fn decode_struct_header(&mut self,
- versions: &[(u32, u32)])
- -> Result<DataHeader, ValidationError> {
- debug_assert_eq!(self.offset, 0);
- // Make sure we can read the size first...
- if self.data.len() < mem::size_of::<u32>() {
- return Err(ValidationError::UnexpectedStructHeader);
- }
- let bytes = self.decode::<u32>();
- if (bytes as usize) < DATA_HEADER_SIZE {
- return Err(ValidationError::UnexpectedStructHeader);
- }
- let version = self.decode::<u32>();
- // Versioning validation: versions are generated as a sorted array of tuples, so
- // to find the version we are given by the header we use a binary search.
- match versions.binary_search_by(|val| val.0.cmp(&version)) {
- Ok(idx) => {
- let (_, size) = versions[idx];
- if bytes != size {
- return Err(ValidationError::UnexpectedStructHeader);
- }
- }
- Err(idx) => {
- if idx == 0 {
- panic!("Should be earliest version? \
- Versions: {:?}, \
- Version: {}, \
- Size: {}", versions, version, bytes);
- }
- let len = versions.len();
- let (latest_version, _) = versions[len - 1];
- let (_, size) = versions[idx - 1];
- // If this is higher than any version we know, its okay for the size to be bigger,
- // but if its a version we know about, it must match the size.
- if (version > latest_version && bytes < size) ||
- (version <= latest_version && bytes != size) {
- return Err(ValidationError::UnexpectedStructHeader);
- }
- }
- }
- Ok(DataHeader::new(bytes as usize, DataHeaderValue::Version(version)))
- }
-}
-
-/// A struct that will encode a given Mojom object and convert it into
-/// bytes and a vector of handles.
-pub struct Decoder<'slice> {
- bytes: usize,
- buffer: Option<&'slice [u8]>,
- states: Vec<DecodingState<'slice>>,
- handles: Vec<UntypedHandle>,
- handles_claimed: usize, // A length that claims all handles were claimed up to this index
- max_offset: usize, // Represents the maximum value an offset may have
-}
-
-impl<'slice> Decoder<'slice> {
- /// Create a new Decoder.
- pub fn new(buffer: &'slice [u8], handles: Vec<UntypedHandle>) -> Decoder<'slice> {
- let max_offset = buffer.len();
- Decoder {
- bytes: 0,
- buffer: Some(buffer),
- states: Vec::new(),
- handles: handles,
- handles_claimed: 0,
- max_offset: max_offset,
- }
- }
-
- /// Claim space in the buffer to start decoding some object.
- ///
- /// Creates a new decoding state for the object and returns a context.
- pub fn claim(&mut self, offset: usize) -> Result<Context, ValidationError> {
- // Check if the layout order is sane
- if offset < self.bytes {
- return Err(ValidationError::IllegalMemoryRange);
- }
- // Check for 8-byte alignment
- if offset & 7 != 0 {
- return Err(ValidationError::MisalignedObject);
- }
- // Bounds check on offset
- if offset > self.max_offset {
- return Err(ValidationError::IllegalPointer);
- }
- let mut buffer = self.buffer.take().expect("No buffer?");
- let space = offset - self.bytes;
- buffer = &buffer[space..];
- // Make sure we can even read the bytes in the header
- if buffer.len() < mem::size_of::<u32>() {
- return Err(ValidationError::IllegalMemoryRange);
- }
- // Read the number of bytes in the memory region according to the data header
- let mut read_size: u32 = 0;
- unsafe {
- ptr::copy_nonoverlapping(mem::transmute::<*const u8, *const u32>(buffer.as_ptr()),
- &mut read_size as *mut u32,
- mem::size_of::<u32>());
- }
- let size = u32::from_le(read_size) as usize;
- // Make sure the size we read is sane...
- if size > buffer.len() {
- return Err(ValidationError::IllegalMemoryRange);
- }
- // TODO(mknyszek): Check size for validation
- let (claimed, unclaimed) = buffer.split_at(size);
- self.states.push(DecodingState::new(claimed, offset));
- self.buffer = Some(unclaimed);
- self.bytes += space + size;
- Ok(Context::new(self.states.len() - 1))
- }
-
- /// Claims a handle at some particular index in the given handles array.
- ///
- /// Returns the handle with all type information in-tact.
- pub fn claim_handle<T: Handle + CastHandle>(&mut self,
- index: i32)
- -> Result<T, ValidationError> {
- let real_index = if index >= 0 {
- index as usize
- } else {
- return Err(ValidationError::UnexpectedInvalidHandle);
- };
- // If the index exceeds our number of handles or if we have already claimed that handle
- if real_index >= self.handles.len() || real_index < self.handles_claimed {
- return Err(ValidationError::IllegalHandle);
- }
- self.handles_claimed = real_index + 1;
- let raw_handle = self.handles[real_index].get_native_handle();
- unsafe {
- self.handles[real_index].invalidate();
- Ok(T::from_untyped(system::acquire(raw_handle)))
- }
- }
-
- /// Immutably borrow a decoding state via Context.
- pub fn get(&self, context: &Context) -> &DecodingState<'slice> {
- &self.states[context.id()]
- }
-
- /// Mutably borrow a decoding state via Context.
- pub fn get_mut(&mut self, context: &Context) -> &mut DecodingState<'slice> {
- &mut self.states[context.id()]
- }
-}
« no previous file with comments | « mojo/public/rust/build.rs ('k') | mojo/public/rust/src/bindings/encoding.rs » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698