blob: 9e1a830e7e1144019777c77c8915a5c703d6f3db [file] [log] [blame]
// 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::{Context, DataHeaderValue, Encoder, DATA_HEADER_SIZE};
use bindings::mojom::{MojomEncodable, MojomPointer, MojomStruct};
/// A flag for the message header indicating that no flag has been set.
pub const MESSAGE_HEADER_NO_FLAG: u32 = 0;
/// A flag for the message header indicating that this message expects
/// a response.
pub const MESSAGE_HEADER_EXPECT_RESPONSE: u32 = 1;
/// A flag for the message header indicating that this message is
/// a response.
pub const MESSAGE_HEADER_IS_RESPONSE: u32 = 2;
const MESSAGE_HEADER_VERSIONS: [(u32, u32); 2] = [(0, 16), (1, 24)];
/// A message header object implemented as a Mojom struct.
pub struct MessageHeader {
pub version: u32,
pub name: u32,
pub flags: u32,
pub request_id: u64,
}
impl MessageHeader {
/// Create a new MessageHeader.
pub fn new(version: u32, name: u32, flags: u32) -> MessageHeader {
MessageHeader { version: version, name: name, flags: flags, request_id: 0 }
}
}
impl MojomPointer for MessageHeader {
fn header_data(&self) -> DataHeaderValue {
DataHeaderValue::Version(self.version)
}
/// Get the serialized size.
///
/// This value differs based on whether or not
/// a request_id is necessary.
fn serialized_size(&self, _context: &Context) -> usize {
let mut size = DATA_HEADER_SIZE + 8;
if self.flags != MESSAGE_HEADER_NO_FLAG {
size += 8;
}
encoding::align_default(size)
}
fn encode_value(self, encoder: &mut Encoder, context: Context) {
MojomEncodable::encode(self.name, encoder, context.clone());
MojomEncodable::encode(self.flags, encoder, context.clone());
if self.version > 0 {
MojomEncodable::encode(self.request_id, encoder, context.clone());
}
}
fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Self, ValidationError> {
let mut state = decoder.get_mut(&context);
let version = match state.decode_struct_header(&MESSAGE_HEADER_VERSIONS) {
Ok(header) => header.data(),
Err(err) => return Err(err),
};
let name = state.decode::<u32>();
let flags = state.decode::<u32>();
if flags > MESSAGE_HEADER_IS_RESPONSE {
return Err(ValidationError::MessageHeaderInvalidFlags);
}
if version == 0 {
if flags == MESSAGE_HEADER_IS_RESPONSE || flags == MESSAGE_HEADER_EXPECT_RESPONSE {
return Err(ValidationError::MessageHeaderMissingRequestId);
}
Ok(MessageHeader { version: version, name: name, flags: flags, request_id: 0 })
} else if version == 1 {
Ok(MessageHeader {
version: version,
name: name,
flags: flags,
request_id: state.decode::<u64>(),
})
} else {
return Err(ValidationError::UnexpectedStructHeader);
}
}
}
impl MojomEncodable for MessageHeader {
impl_encodable_for_pointer!();
fn compute_size(&self, context: Context) -> usize {
self.serialized_size(&context)
}
}
impl MojomStruct for MessageHeader {}