| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 use bindings::decoding::{Decoder, ValidationError}; |
| 5 use bindings::encoding; | 6 use bindings::encoding; |
| 6 use bindings::encoding::{Bits, Encoder, Context, DATA_HEADER_SIZE, DataHeader, D
ataHeaderValue}; | 7 use bindings::encoding::{Bits, Encoder, Context, DATA_HEADER_SIZE, DataHeader, D
ataHeaderValue}; |
| 7 use bindings::decoding::Decoder; | |
| 8 | |
| 9 use bindings::message::MessageHeader; | 8 use bindings::message::MessageHeader; |
| 10 | 9 |
| 11 use std::cmp::Eq; | 10 use std::cmp::Eq; |
| 12 use std::collections::HashMap; | 11 use std::collections::HashMap; |
| 13 use std::hash::Hash; | 12 use std::hash::Hash; |
| 14 use std::mem; | 13 use std::mem; |
| 15 use std::panic; | 14 use std::panic; |
| 16 use std::ptr; | 15 use std::ptr; |
| 17 use std::vec::Vec; | 16 use std::vec::Vec; |
| 18 | 17 |
| 19 use system::{CastHandle, Handle, UntypedHandle}; | 18 use system::{CastHandle, Handle, UntypedHandle}; |
| 20 use system::data_pipe; | 19 use system::data_pipe; |
| 21 use system::message_pipe; | 20 use system::message_pipe; |
| 22 use system::shared_buffer; | 21 use system::shared_buffer; |
| 23 use system::wait_set; | 22 use system::wait_set; |
| 24 | 23 |
| 25 /// The size of a Mojom map plus header in bytes. | 24 /// The size of a Mojom map plus header in bytes. |
| 26 const MAP_SIZE: usize = 24; | 25 const MAP_SIZE: usize = 24; |
| 27 | 26 |
| 27 /// The sorted set of versions for a map. |
| 28 const MAP_VERSIONS: [(u32, u32); 1] = [(0, MAP_SIZE as u32)]; |
| 29 |
| 28 /// The size of a Mojom union in bytes (header included). | 30 /// The size of a Mojom union in bytes (header included). |
| 29 pub const UNION_SIZE: usize = 16; | 31 pub const UNION_SIZE: usize = 16; |
| 30 | 32 |
| 31 /// The size of a Mojom pointer in bits. | 33 /// The size of a Mojom pointer in bits. |
| 32 pub const POINTER_BIT_SIZE: Bits = Bits(64); | 34 pub const POINTER_BIT_SIZE: Bits = Bits(64); |
| 33 | 35 |
| 34 /// The value of a Mojom null pointer. | 36 /// The value of a Mojom null pointer. |
| 35 pub const MOJOM_NULL_POINTER: u64 = 0; | 37 pub const MOJOM_NULL_POINTER: u64 = 0; |
| 36 | 38 |
| 37 /// An enumeration of all the possible low-level Mojom types. | 39 /// An enumeration of all the possible low-level Mojom types. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 56 fn embed_size(context: &Context) -> Bits; | 58 fn embed_size(context: &Context) -> Bits; |
| 57 | 59 |
| 58 /// Recursively computes the size of the complete Mojom archive | 60 /// Recursively computes the size of the complete Mojom archive |
| 59 /// starting from this type. | 61 /// starting from this type. |
| 60 fn compute_size(&self, context: Context) -> usize; | 62 fn compute_size(&self, context: Context) -> usize; |
| 61 | 63 |
| 62 /// Encodes this type into the encoder given a context. | 64 /// Encodes this type into the encoder given a context. |
| 63 fn encode(self, encoder: &mut Encoder, context: Context); | 65 fn encode(self, encoder: &mut Encoder, context: Context); |
| 64 | 66 |
| 65 /// Using a decoder, decodes itself out of a byte buffer. | 67 /// Using a decoder, decodes itself out of a byte buffer. |
| 66 fn decode(decoder: &mut Decoder, context: Context) -> Self; | 68 fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, Validatio
nError>; |
| 67 } | 69 } |
| 68 | 70 |
| 69 /// Whatever implements this trait is a Mojom pointer type which means | 71 /// Whatever implements this trait is a Mojom pointer type which means |
| 70 /// that on encode, a pointer is inlined and the implementer is | 72 /// that on encode, a pointer is inlined and the implementer is |
| 71 /// serialized elsewhere in the output buffer. | 73 /// serialized elsewhere in the output buffer. |
| 72 pub trait MojomPointer: MojomEncodable { | 74 pub trait MojomPointer: MojomEncodable { |
| 73 /// Get the DataHeader meta-data for this pointer type. | 75 /// Get the DataHeader meta-data for this pointer type. |
| 74 fn header_data(&self) -> DataHeaderValue; | 76 fn header_data(&self) -> DataHeaderValue; |
| 75 | 77 |
| 76 /// Get the size of only this type when serialized. | 78 /// Get the size of only this type when serialized. |
| 77 fn serialized_size(&self, context: &Context) -> usize; | 79 fn serialized_size(&self, context: &Context) -> usize; |
| 78 | 80 |
| 79 /// Encodes the actual values of the type into the encoder. | 81 /// Encodes the actual values of the type into the encoder. |
| 80 fn encode_value(self, encoder: &mut Encoder, context: Context); | 82 fn encode_value(self, encoder: &mut Encoder, context: Context); |
| 81 | 83 |
| 82 /// Decodes the actual values of the type into the decoder. | 84 /// Decodes the actual values of the type into the decoder. |
| 83 fn decode_value(decoder: &mut Decoder, context: Context) -> Self; | 85 fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Self, Val
idationError>; |
| 84 | 86 |
| 85 /// Writes a pointer inlined into the current context before calling | 87 /// Writes a pointer inlined into the current context before calling |
| 86 /// encode_value. | 88 /// encode_value. |
| 87 fn encode_new(self, encoder: &mut Encoder, context: Context) { | 89 fn encode_new(self, encoder: &mut Encoder, context: Context) { |
| 88 let data_size = self.serialized_size(&context); | 90 let data_size = self.serialized_size(&context); |
| 89 let data_header = DataHeader::new(data_size, self.header_data()); | 91 let data_header = DataHeader::new(data_size, self.header_data()); |
| 90 let new_context = encoder.add(&data_header).unwrap(); | 92 let new_context = encoder.add(&data_header).unwrap(); |
| 91 self.encode_value(encoder, new_context); | 93 self.encode_value(encoder, new_context); |
| 92 } | 94 } |
| 93 | 95 |
| 94 /// Reads a pointer inlined into the current context before calling | 96 /// Reads a pointer inlined into the current context before calling |
| 95 /// decode_value. | 97 /// decode_value. |
| 96 fn decode_new(decoder: &mut Decoder, _context: Context, pointer: u64) -> Sel
f { | 98 fn decode_new(decoder: &mut Decoder, _context: Context, pointer: u64) -> Res
ult<Self, ValidationError> { |
| 97 let new_context = decoder.claim(pointer as usize).unwrap(); | 99 match decoder.claim(pointer as usize) { |
| 98 Self::decode_value(decoder, new_context) | 100 Ok(new_context) => Self::decode_value(decoder, new_context), |
| 101 Err(err) => Err(err), |
| 102 } |
| 99 } | 103 } |
| 100 } | 104 } |
| 101 | 105 |
| 102 /// Whatever implements this trait is a Mojom union type which means that | 106 /// Whatever implements this trait is a Mojom union type which means that |
| 103 /// on encode it is inlined, but if the union is nested inside of another | 107 /// on encode it is inlined, but if the union is nested inside of another |
| 104 /// union type, it is treated as a pointer type. | 108 /// union type, it is treated as a pointer type. |
| 105 pub trait MojomUnion: MojomEncodable { | 109 pub trait MojomUnion: MojomEncodable { |
| 106 /// Get the union's current tag. | 110 /// Get the union's current tag. |
| 107 fn get_tag(&self) -> u32; | 111 fn get_tag(&self) -> u32; |
| 108 | 112 |
| 109 /// Encode the actual value of the union. | 113 /// Encode the actual value of the union. |
| 110 fn encode_value(self, encoder: &mut Encoder, context: Context); | 114 fn encode_value(self, encoder: &mut Encoder, context: Context); |
| 111 | 115 |
| 112 /// Decode the actual value of the union. | 116 /// Decode the actual value of the union. |
| 113 fn decode_value(decoder: &mut Decoder, context: Context) -> Self; | 117 fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Self, Val
idationError>; |
| 114 | 118 |
| 115 /// The embed_size for when the union acts as a pointer type. | 119 /// The embed_size for when the union acts as a pointer type. |
| 116 fn nested_embed_size() -> Bits { | 120 fn nested_embed_size() -> Bits { |
| 117 POINTER_BIT_SIZE | 121 POINTER_BIT_SIZE |
| 118 } | 122 } |
| 119 | 123 |
| 120 /// The encoding routine for when the union acts as a pointer type. | 124 /// The encoding routine for when the union acts as a pointer type. |
| 121 fn nested_encode(self, encoder: &mut Encoder, context: Context) { | 125 fn nested_encode(self, encoder: &mut Encoder, context: Context) { |
| 122 let loc = encoder.size() as u64; | 126 let loc = encoder.size() as u64; |
| 123 { | 127 { |
| 124 let state = encoder.get_mut(&context); | 128 let state = encoder.get_mut(&context); |
| 125 state.encode_pointer(loc); | 129 state.encode_pointer(loc); |
| 126 } | 130 } |
| 127 let tag = DataHeaderValue::UnionTag(self.get_tag()); | 131 let tag = DataHeaderValue::UnionTag(self.get_tag()); |
| 128 let data_header = DataHeader::new(UNION_SIZE, tag); | 132 let data_header = DataHeader::new(UNION_SIZE, tag); |
| 129 let new_context = encoder.add(&data_header).unwrap(); | 133 let new_context = encoder.add(&data_header).unwrap(); |
| 130 self.encode_value(encoder, new_context.set_is_union(true)); | 134 self.encode_value(encoder, new_context.set_is_union(true)); |
| 131 } | 135 } |
| 132 | 136 |
| 133 /// The decoding routine for when the union acts as a pointer type. | 137 /// The decoding routine for when the union acts as a pointer type. |
| 134 fn nested_decode(decoder: &mut Decoder, context: Context) -> Self { | 138 fn nested_decode(decoder: &mut Decoder, context: Context) -> Result<Self, Va
lidationError> { |
| 135 let global_offset = { | 139 let global_offset = { |
| 136 let state = decoder.get_mut(&context); | 140 let state = decoder.get_mut(&context); |
| 137 state.decode_pointer() as usize | 141 match state.decode_pointer() { |
| 142 Some(ptr) => ptr as usize, |
| 143 None => return Err(ValidationError::IllegalPointer), |
| 144 } |
| 138 }; | 145 }; |
| 139 let new_context = decoder.claim(global_offset).unwrap(); | 146 if global_offset == (MOJOM_NULL_POINTER as usize) { |
| 140 Self::decode_value(decoder, new_context) | 147 return Err(ValidationError::UnexpectedNullPointer); |
| 148 } |
| 149 match decoder.claim(global_offset as usize) { |
| 150 Ok(new_context) => Self::decode_value(decoder, new_context), |
| 151 Err(err) => Err(err), |
| 152 } |
| 141 } | 153 } |
| 142 | 154 |
| 143 /// The embed_size for when the union is inlined into the current context. | 155 /// The embed_size for when the union is inlined into the current context. |
| 144 fn inline_embed_size() -> Bits { | 156 fn inline_embed_size() -> Bits { |
| 145 Bits(8 * (UNION_SIZE as usize)) | 157 Bits(8 * (UNION_SIZE as usize)) |
| 146 } | 158 } |
| 147 | 159 |
| 148 /// The encoding routine for when the union is inlined into the current cont
ext. | 160 /// The encoding routine for when the union is inlined into the current cont
ext. |
| 149 fn inline_encode(self, encoder: &mut Encoder, context: Context) { | 161 fn inline_encode(self, encoder: &mut Encoder, context: Context) { |
| 150 { | 162 { |
| 151 let mut state = encoder.get_mut(&context); | 163 let mut state = encoder.get_mut(&context); |
| 152 state.align_to_bytes(8); | 164 state.align_to_bytes(8); |
| 153 state.encode(UNION_SIZE as u32); | 165 state.encode(UNION_SIZE as u32); |
| 154 state.encode(self.get_tag()); | 166 state.encode(self.get_tag()); |
| 155 } | 167 } |
| 156 self.encode_value(encoder, context.clone()); | 168 self.encode_value(encoder, context.clone()); |
| 157 { | 169 { |
| 158 let mut state = encoder.get_mut(&context); | 170 let mut state = encoder.get_mut(&context); |
| 159 state.align_to_bytes(8); | 171 state.align_to_bytes(8); |
| 160 state.align_to_byte(); | 172 state.align_to_byte(); |
| 161 } | 173 } |
| 162 } | 174 } |
| 163 | 175 |
| 164 /// The decoding routine for when the union is inlined into the current cont
ext. | 176 /// The decoding routine for when the union is inlined into the current cont
ext. |
| 165 fn inline_decode(decoder: &mut Decoder, context: Context) -> Self { | 177 fn inline_decode(decoder: &mut Decoder, context: Context) -> Result<Self, Va
lidationError> { |
| 166 { | 178 { |
| 167 let mut state = decoder.get_mut(&context); | 179 let mut state = decoder.get_mut(&context); |
| 168 state.align_to_byte(); | 180 state.align_to_byte(); |
| 169 state.align_to_bytes(8); | 181 state.align_to_bytes(8); |
| 170 } | 182 } |
| 171 let value = Self::decode_value(decoder, context.clone()); | 183 let value = Self::decode_value(decoder, context.clone()); |
| 172 { | 184 { |
| 173 let mut state = decoder.get_mut(&context); | 185 let mut state = decoder.get_mut(&context); |
| 174 state.align_to_byte(); | 186 state.align_to_byte(); |
| 175 state.align_to_bytes(8); | 187 state.align_to_bytes(8); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 /// interface that may recieve messages for some interface. | 249 /// interface that may recieve messages for some interface. |
| 238 /// | 250 /// |
| 239 /// When implementing this trait, specify the container "union" type | 251 /// When implementing this trait, specify the container "union" type |
| 240 /// which can contain any of the potential messages that may be recieved. | 252 /// which can contain any of the potential messages that may be recieved. |
| 241 /// This way, we can return that type and let the user multiplex over | 253 /// This way, we can return that type and let the user multiplex over |
| 242 /// what message was received. | 254 /// what message was received. |
| 243 pub trait MojomInterfaceRecv: MojomInterface { | 255 pub trait MojomInterfaceRecv: MojomInterface { |
| 244 type Container: MojomMessageOption; | 256 type Container: MojomMessageOption; |
| 245 | 257 |
| 246 /// Tries to read a message from a pipe and decodes it. | 258 /// Tries to read a message from a pipe and decodes it. |
| 247 fn recv_response(&self) -> Self::Container { | 259 fn recv_response(&self) -> Result<Self::Container, ValidationError> { |
| 248 // TODO(mknyszek): Actually handle errors with reading | 260 // TODO(mknyszek): Actually handle errors with reading |
| 249 let (buffer, handles) = self.pipe().read(mpflags!(Read::None)).unwrap(); | 261 let (buffer, handles) = self.pipe().read(mpflags!(Read::None)).unwrap(); |
| 250 Self::Container::decode_message(buffer, handles) | 262 Self::Container::decode_message(buffer, handles) |
| 251 } | 263 } |
| 252 } | 264 } |
| 253 | 265 |
| 254 /// Whatever implements this trait is considered to be a Mojom struct. | 266 /// Whatever implements this trait is considered to be a Mojom struct. |
| 255 /// | 267 /// |
| 256 /// Mojom structs are always the root of any Mojom message. Thus, we | 268 /// Mojom structs are always the root of any Mojom message. Thus, we |
| 257 /// provide convenience functions for serialization here. | 269 /// provide convenience functions for serialization here. |
| 258 pub trait MojomStruct: MojomPointer { | 270 pub trait MojomStruct: MojomPointer { |
| 259 /// Given a pre-allocated buffer, the struct serializes itself. | 271 /// Given a pre-allocated buffer, the struct serializes itself. |
| 260 fn serialize(self, buffer: &mut [u8]) -> Vec<UntypedHandle> { | 272 fn serialize(self, buffer: &mut [u8]) -> Vec<UntypedHandle> { |
| 261 let mut encoder = Encoder::new(buffer); | 273 let mut encoder = Encoder::new(buffer); |
| 262 self.encode_new(&mut encoder, Default::default()); | 274 self.encode_new(&mut encoder, Default::default()); |
| 263 encoder.unwrap() | 275 encoder.unwrap() |
| 264 } | 276 } |
| 265 | 277 |
| 266 /// The struct computes its own size, allocates a buffer, and then | 278 /// The struct computes its own size, allocates a buffer, and then |
| 267 /// serializes itself into that buffer. | 279 /// serializes itself into that buffer. |
| 268 fn auto_serialize(self) -> (Vec<u8>, Vec<UntypedHandle>) { | 280 fn auto_serialize(self) -> (Vec<u8>, Vec<UntypedHandle>) { |
| 269 let size = self.compute_size(Default::default()); | 281 let size = self.compute_size(Default::default()); |
| 270 let mut buf = Vec::with_capacity(size); | 282 let mut buf = Vec::with_capacity(size); |
| 271 buf.resize(size, 0); | 283 buf.resize(size, 0); |
| 272 let handles = self.serialize(&mut buf); | 284 let handles = self.serialize(&mut buf); |
| 273 (buf, handles) | 285 (buf, handles) |
| 274 } | 286 } |
| 275 | 287 |
| 276 /// Decode the type from a byte array and a set of handles. | 288 /// Decode the type from a byte array and a set of handles. |
| 277 fn deserialize(buffer: &[u8], handles: Vec<UntypedHandle>) -> Self { | 289 fn deserialize(buffer: &[u8], handles: Vec<UntypedHandle>) -> Result<Self, V
alidationError> { |
| 278 let mut decoder = Decoder::new(buffer, handles); | 290 let mut decoder = Decoder::new(buffer, handles); |
| 279 Self::decode_new(&mut decoder, Default::default(), 0) | 291 Self::decode_new(&mut decoder, Default::default(), 0) |
| 280 } | 292 } |
| 281 } | 293 } |
| 282 | 294 |
| 283 /// Marks a MojomStruct as being capable of being sent across some | 295 /// Marks a MojomStruct as being capable of being sent across some |
| 284 /// Mojom interface. | 296 /// Mojom interface. |
| 285 pub trait MojomMessage: MojomStruct { | 297 pub trait MojomMessage: MojomStruct { |
| 286 fn create_header() -> MessageHeader; | 298 fn create_header() -> MessageHeader; |
| 287 } | 299 } |
| 288 | 300 |
| 289 /// The trait for a "container" type intended to be used in MojomInterfaceRecv. | 301 /// The trait for a "container" type intended to be used in MojomInterfaceRecv. |
| 290 /// | 302 /// |
| 291 /// This trait contains the decode logic which decodes based on the message head
er | 303 /// This trait contains the decode logic which decodes based on the message head
er |
| 292 /// and returns itself: a union type which may contain any of the possible messa
ges | 304 /// and returns itself: a union type which may contain any of the possible messa
ges |
| 293 /// that may be sent across this interface. | 305 /// that may be sent across this interface. |
| 294 pub trait MojomMessageOption: Sized { | 306 pub trait MojomMessageOption: Sized { |
| 295 /// Decodes the actual payload of the message. | 307 /// Decodes the actual payload of the message. |
| 296 /// | 308 /// |
| 297 /// Implemented by a code generator. | 309 /// Implemented by a code generator. |
| 298 fn decode_payload(name: u32, buffer: &[u8], handles: Vec<UntypedHandle>) ->
Self; | 310 fn decode_payload(header: MessageHeader, buffer: &[u8], handles: Vec<Untyped
Handle>) -> Result<Self, ValidationError>; |
| 299 | 311 |
| 300 /// Decodes the message header and then the payload, returning a new | 312 /// Decodes the message header and then the payload, returning a new |
| 301 /// copy of itself. | 313 /// copy of itself. |
| 302 fn decode_message(mut buffer: Vec<u8>, handles: Vec<UntypedHandle>) -> Self
{ | 314 fn decode_message(buffer: Vec<u8>, handles: Vec<UntypedHandle>) -> Result<Se
lf, ValidationError> { |
| 303 let header = MessageHeader::deserialize(&buffer[..], Vec::new()); | 315 let header = match MessageHeader::deserialize(&buffer[..], Vec::new()) { |
| 304 let payload_buffer = &mut buffer[header.serialized_size(&Default::defaul
t())..]; | 316 Ok(header) => header, |
| 305 Self::decode_payload(header.name, payload_buffer, handles) | 317 Err(err) => return Err(err), |
| 318 }; |
| 319 let payload_buffer = &buffer[header.serialized_size(&Default::default())
..]; |
| 320 Self::decode_payload(header, payload_buffer, handles) |
| 306 } | 321 } |
| 307 } | 322 } |
| 308 | 323 |
| 309 // ********************************************** // | 324 // ********************************************** // |
| 310 // ****** IMPLEMENTATIONS FOR COMMON TYPES ****** // | 325 // ****** IMPLEMENTATIONS FOR COMMON TYPES ****** // |
| 311 // ********************************************** // | 326 // ********************************************** // |
| 312 | 327 |
| 313 macro_rules! impl_encodable_for_prim { | 328 macro_rules! impl_encodable_for_prim { |
| 314 ($($prim_type:ty),*) => { | 329 ($($prim_type:ty),*) => { |
| 315 $( | 330 $( |
| 316 impl MojomEncodable for $prim_type { | 331 impl MojomEncodable for $prim_type { |
| 317 fn mojom_type() -> MojomType { | 332 fn mojom_type() -> MojomType { |
| 318 MojomType::Simple | 333 MojomType::Simple |
| 319 } | 334 } |
| 320 fn mojom_alignment() -> usize { | 335 fn mojom_alignment() -> usize { |
| 321 mem::size_of::<$prim_type>() | 336 mem::size_of::<$prim_type>() |
| 322 } | 337 } |
| 323 fn embed_size(_context: &Context) -> Bits { | 338 fn embed_size(_context: &Context) -> Bits { |
| 324 Bits(8 * mem::size_of::<$prim_type>()) | 339 Bits(8 * mem::size_of::<$prim_type>()) |
| 325 } | 340 } |
| 326 fn compute_size(&self, _context: Context) -> usize { | 341 fn compute_size(&self, _context: Context) -> usize { |
| 327 0 // Indicates that this type is inlined and it adds nothing ext
ernal to the size | 342 0 // Indicates that this type is inlined and it adds nothing ext
ernal to the size |
| 328 } | 343 } |
| 329 fn encode(self, encoder: &mut Encoder, context: Context) { | 344 fn encode(self, encoder: &mut Encoder, context: Context) { |
| 330 let mut state = encoder.get_mut(&context); | 345 let mut state = encoder.get_mut(&context); |
| 331 state.encode(self); | 346 state.encode(self); |
| 332 } | 347 } |
| 333 fn decode(decoder: &mut Decoder, context: Context) -> Self { | 348 fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, V
alidationError> { |
| 334 let mut state = decoder.get_mut(&context); | 349 let mut state = decoder.get_mut(&context); |
| 335 state.decode::<Self>() | 350 Ok(state.decode::<Self>()) |
| 336 } | 351 } |
| 337 } | 352 } |
| 338 )* | 353 )* |
| 339 } | 354 } |
| 340 } | 355 } |
| 341 | 356 |
| 342 impl_encodable_for_prim!(i8, i16, i32, i64, u8, u16, u32, u64, f32, f64); | 357 impl_encodable_for_prim!(i8, i16, i32, i64, u8, u16, u32, u64, f32, f64); |
| 343 | 358 |
| 344 impl MojomEncodable for bool { | 359 impl MojomEncodable for bool { |
| 345 fn mojom_alignment() -> usize { | 360 fn mojom_alignment() -> usize { |
| 346 panic!("Should never check mojom_alignment of bools (they're bit-aligned
)!"); | 361 panic!("Should never check_decode mojom_alignment of bools (they're bit-
aligned)!"); |
| 347 } | 362 } |
| 348 fn mojom_type() -> MojomType { | 363 fn mojom_type() -> MojomType { |
| 349 MojomType::Simple | 364 MojomType::Simple |
| 350 } | 365 } |
| 351 fn embed_size(_context: &Context) -> Bits { | 366 fn embed_size(_context: &Context) -> Bits { |
| 352 Bits(1) | 367 Bits(1) |
| 353 } | 368 } |
| 354 fn compute_size(&self, _context: Context) -> usize { | 369 fn compute_size(&self, _context: Context) -> usize { |
| 355 0 // Indicates that this type is inlined and it adds nothing external to
the size | 370 0 // Indicates that this type is inlined and it adds nothing external to
the size |
| 356 } | 371 } |
| 357 fn encode(self, encoder: &mut Encoder, context: Context) { | 372 fn encode(self, encoder: &mut Encoder, context: Context) { |
| 358 let mut state = encoder.get_mut(&context); | 373 let mut state = encoder.get_mut(&context); |
| 359 state.encode_bool(self); | 374 state.encode_bool(self); |
| 360 } | 375 } |
| 361 fn decode(decoder: &mut Decoder, context: Context) -> Self { | 376 fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, Validatio
nError> { |
| 362 let mut state = decoder.get_mut(&context); | 377 let mut state = decoder.get_mut(&context); |
| 363 state.decode_bool() | 378 Ok(state.decode_bool()) |
| 364 } | 379 } |
| 365 } | 380 } |
| 366 | 381 |
| 367 // Options should be considered to represent nullability the Mojom IDL. | 382 // Options should be considered to represent nullability the Mojom IDL. |
| 368 // Any type wrapped in an Option type is nullable. | 383 // Any type wrapped in an Option type is nullable. |
| 369 | 384 |
| 370 impl<T: MojomEncodable> MojomEncodable for Option<T> { | 385 impl<T: MojomEncodable> MojomEncodable for Option<T> { |
| 371 fn mojom_alignment() -> usize { | 386 fn mojom_alignment() -> usize { |
| 372 T::mojom_alignment() | 387 T::mojom_alignment() |
| 373 } | 388 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 394 MojomType::Handle => state.encode_null_handle(), | 409 MojomType::Handle => state.encode_null_handle(), |
| 395 MojomType::Interface => { | 410 MojomType::Interface => { |
| 396 state.encode_null_handle(); | 411 state.encode_null_handle(); |
| 397 state.encode(0 as u32); | 412 state.encode(0 as u32); |
| 398 }, | 413 }, |
| 399 MojomType::Simple => panic!("Unexpected simple type in Optio
n!"), | 414 MojomType::Simple => panic!("Unexpected simple type in Optio
n!"), |
| 400 } | 415 } |
| 401 }, | 416 }, |
| 402 } | 417 } |
| 403 } | 418 } |
| 404 fn decode(decoder: &mut Decoder, context: Context) -> Self { | 419 fn decode(decoder: &mut Decoder, context: Context) -> Result<Self, Validatio
nError> { |
| 405 let skipped = { | 420 let skipped = { |
| 406 let mut state = decoder.get_mut(&context); | 421 let mut state = decoder.get_mut(&context); |
| 407 match T::mojom_type() { | 422 match T::mojom_type() { |
| 408 MojomType::Pointer => state.skip_if_null_pointer(), | 423 MojomType::Pointer => state.skip_if_null_pointer(), |
| 409 MojomType::Union => state.skip_if_null_union(), | 424 MojomType::Union => state.skip_if_null_union(), |
| 410 MojomType::Handle => state.skip_if_null_handle(), | 425 MojomType::Handle => state.skip_if_null_handle(), |
| 411 MojomType::Interface => state.skip_if_null_interface(), | 426 MojomType::Interface => state.skip_if_null_interface(), |
| 412 MojomType::Simple => panic!("Unexpected simple type in Option!")
, | 427 MojomType::Simple => panic!("Unexpected simple type in Option!")
, |
| 413 } | 428 } |
| 414 }; | 429 }; |
| 415 if skipped { | 430 if skipped { |
| 416 None | 431 Ok(None) |
| 417 } else { | 432 } else { |
| 418 Some(T::decode(decoder, context)) | 433 match T::decode(decoder, context) { |
| 434 Ok(value) => Ok(Some(value)), |
| 435 Err(err) => Err(err), |
| 436 } |
| 419 } | 437 } |
| 420 } | 438 } |
| 421 } | 439 } |
| 422 | 440 |
| 423 macro_rules! impl_pointer_for_array { | 441 macro_rules! impl_pointer_for_array { |
| 424 () => { | 442 () => { |
| 425 fn header_data(&self) -> DataHeaderValue { | 443 fn header_data(&self) -> DataHeaderValue { |
| 426 DataHeaderValue::Elements(self.len() as u32) | 444 DataHeaderValue::Elements(self.len() as u32) |
| 427 } | 445 } |
| 428 fn serialized_size(&self, context: &Context) -> usize { | 446 fn serialized_size(&self, context: &Context) -> usize { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 448 } | 466 } |
| 449 } | 467 } |
| 450 | 468 |
| 451 impl<T: MojomEncodable> MojomPointer for Vec<T> { | 469 impl<T: MojomEncodable> MojomPointer for Vec<T> { |
| 452 impl_pointer_for_array!(); | 470 impl_pointer_for_array!(); |
| 453 fn encode_value(self, encoder: &mut Encoder, context: Context) { | 471 fn encode_value(self, encoder: &mut Encoder, context: Context) { |
| 454 for elem in self.into_iter() { | 472 for elem in self.into_iter() { |
| 455 elem.encode(encoder, context.clone()); | 473 elem.encode(encoder, context.clone()); |
| 456 } | 474 } |
| 457 } | 475 } |
| 458 fn decode_value(decoder: &mut Decoder, context: Context) -> Vec<T> { | 476 fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Vec<T>, V
alidationError> { |
| 459 // TODO(mknyszek): Verify elems, bytes, and T::embed_size match | 477 let elems = { |
| 460 let (_bytes, elems) = { | |
| 461 let mut state = decoder.get_mut(&context); | 478 let mut state = decoder.get_mut(&context); |
| 462 (state.decode::<u32>(), state.decode::<u32>()) | 479 match state.decode_array_header::<T>() { |
| 480 Ok(header) => header.data(), |
| 481 Err(err) => return Err(err), |
| 482 } |
| 463 }; | 483 }; |
| 464 let mut value = Vec::with_capacity(elems as usize); | 484 let mut value = Vec::with_capacity(elems as usize); |
| 465 // TODO(mknyszek): Don't trust elems blindly | |
| 466 for _ in 0..elems { | 485 for _ in 0..elems { |
| 467 value.push(T::decode(decoder, context.clone())); | 486 match T::decode(decoder, context.clone()) { |
| 487 Ok(elem) => value.push(elem), |
| 488 Err(err) => return Err(err), |
| 489 } |
| 468 } | 490 } |
| 469 value | 491 Ok(value) |
| 470 } | 492 } |
| 471 } | 493 } |
| 472 | 494 |
| 473 impl<T: MojomEncodable> MojomEncodable for Vec<T> { | 495 impl<T: MojomEncodable> MojomEncodable for Vec<T> { |
| 474 impl_encodable_for_array!(); | 496 impl_encodable_for_array!(); |
| 475 } | 497 } |
| 476 | 498 |
| 477 macro_rules! impl_encodable_for_fixed_array { | 499 macro_rules! impl_encodable_for_fixed_array { |
| 478 ($($len:expr),*) => { | 500 ($($len:expr),*) => { |
| 479 $( | 501 $( |
| 480 impl<T: MojomEncodable> MojomPointer for [T; $len] { | 502 impl<T: MojomEncodable> MojomPointer for [T; $len] { |
| 481 impl_pointer_for_array!(); | 503 impl_pointer_for_array!(); |
| 482 fn encode_value(mut self, encoder: &mut Encoder, context: Context) { | 504 fn encode_value(mut self, encoder: &mut Encoder, context: Context) { |
| 483 let mut panic_err = None; | 505 let mut panic_error = None; |
| 484 let mut moves = 0; | 506 let mut moves = 0; |
| 485 unsafe { | 507 unsafe { |
| 486 // In order to move elements out of an array we need to repl
ace the | 508 // In order to move elements out of an array we need to repl
ace the |
| 487 // value with uninitialized memory. | 509 // value with uninitialized memory. |
| 488 for elem in self.iter_mut() { | 510 for elem in self.iter_mut() { |
| 489 let owned_elem = mem::replace(elem, mem::uninitialized()
); | 511 let owned_elem = mem::replace(elem, mem::uninitialized()
); |
| 490 // We need to handle if an unwinding panic happens to pr
event use of | 512 // We need to handle if an unwinding panic happens to pr
event use of |
| 491 // uninitialized memory... | 513 // uninitialized memory... |
| 492 let next_context = context.clone(); | 514 let next_context = context.clone(); |
| 493 // We assert everything going into this closure is unwin
d safe. If anything | 515 // We assert everything going into this closure is unwin
d safe. If anything |
| 494 // is added, PLEASE make sure it is also unwind safe... | 516 // is added, PLEASE make sure it is also unwind safe... |
| 495 let result = panic::catch_unwind(panic::AssertUnwindSafe
(|| { | 517 let result = panic::catch_unwind(panic::AssertUnwindSafe
(|| { |
| 496 owned_elem.encode(encoder, next_context); | 518 owned_elem.encode(encoder, next_context); |
| 497 })); | 519 })); |
| 498 if let Err(err) = result { | 520 if let Err(err) = result { |
| 499 panic_err = Some(err); | 521 panic_error = Some(err); |
| 500 break; | 522 break; |
| 501 } | 523 } |
| 502 moves += 1; | 524 moves += 1; |
| 503 } | 525 } |
| 504 if let Some(err) = panic_err { | 526 if let Some(err) = panic_error { |
| 505 for i in moves..self.len() { | 527 for i in moves..self.len() { |
| 506 ptr::drop_in_place(&mut self[i] as *mut T); | 528 ptr::drop_in_place(&mut self[i] as *mut T); |
| 507 } | 529 } |
| 508 // Forget the array to prevent a drop | 530 // Forget the array to prevent a drop |
| 509 mem::forget(self); | 531 mem::forget(self); |
| 510 // Continue unwinding | 532 // Continue unwinding |
| 511 panic::resume_unwind(err); | 533 panic::resume_unwind(err); |
| 512 } | 534 } |
| 513 // We cannot risk drop() getting run on the array values, so
we just | 535 // We cannot risk drop() getting run on the array values, so
we just |
| 514 // forget self. | 536 // forget self. |
| 515 mem::forget(self); | 537 mem::forget(self); |
| 516 } | 538 } |
| 517 } | 539 } |
| 518 fn decode_value(mut decoder: &mut Decoder, context: Context) -> [T;
$len] { | 540 fn decode_value(decoder: &mut Decoder, context: Context) -> Result<[
T; $len], ValidationError> { |
| 519 // TODO(mknyszek): Verify elems, bytes, and T::embed_size match | 541 let elems = { |
| 520 let (_bytes, elems) = { | |
| 521 let mut state = decoder.get_mut(&context); | 542 let mut state = decoder.get_mut(&context); |
| 522 (state.decode::<u32>(), state.decode::<u32>()) | 543 match state.decode_array_header::<T>() { |
| 544 Ok(header) => header.data(), |
| 545 Err(err) => return Err(err), |
| 546 } |
| 523 }; | 547 }; |
| 524 assert_eq!(elems, $len); | 548 if elems != $len { |
| 549 return Err(ValidationError::UnexpectedArrayHeader); |
| 550 } |
| 525 let mut array: [T; $len]; | 551 let mut array: [T; $len]; |
| 526 let mut panic_err = None; | 552 let mut panic_error = None; |
| 527 let mut inits = 0; | 553 let mut inits = 0; |
| 554 let mut error = None; |
| 528 unsafe { | 555 unsafe { |
| 529 // Since we don't force Clone to be implemented on Mojom typ
es | 556 // Since we don't force Clone to be implemented on Mojom typ
es |
| 530 // (mainly due to handles) we need to create this array as u
ninitialized | 557 // (mainly due to handles) we need to create this array as u
ninitialized |
| 531 // and initialize it manually. | 558 // and initialize it manually. |
| 532 array = mem::uninitialized(); | 559 array = mem::uninitialized(); |
| 533 for elem in &mut array[..] { | 560 for elem in &mut array[..] { |
| 534 // When a panic unwinds it may try to read and drop unin
itialized | 561 // When a panic unwinds it may try to read and drop unin
itialized |
| 535 // memory, so we need to catch this. However, we pass mu
table state! | 562 // memory, so we need to catch this. However, we pass mu
table state! |
| 536 // This could be bad as we could observe a broken invari
ant inside | 563 // This could be bad as we could observe a broken invari
ant inside |
| 537 // of decoder and access it as usual, but we do NOT acce
ss decoder | 564 // of decoder and access it as usual, but we do NOT acce
ss decoder |
| 538 // here, nor do we ever unwind through one of decoder's
methods. | 565 // here, nor do we ever unwind through one of decoder's
methods. |
| 539 // Therefore, it should be safe to assert that decoder i
s unwind safe. | 566 // Therefore, it should be safe to assert that decoder i
s unwind safe. |
| 540 let next_context = context.clone(); | 567 let next_context = context.clone(); |
| 541 // We assert everything going into this closure is unwin
d safe. If anything | 568 // We assert everything going into this closure is unwin
d safe. If anything |
| 542 // is added, PLEASE make sure it is also unwind safe... | 569 // is added, PLEASE make sure it is also unwind safe... |
| 543 let result = panic::catch_unwind(panic::AssertUnwindSafe
(|| { | 570 let result = panic::catch_unwind(panic::AssertUnwindSafe
(|| { |
| 544 T::decode(decoder, next_context) | 571 T::decode(decoder, next_context) |
| 545 })); | 572 })); |
| 546 match result { | 573 match result { |
| 547 Ok(value) => ptr::write(elem, value), | 574 Ok(non_panic_value) => match non_panic_value { |
| 575 Ok(value) => ptr::write(elem, value), |
| 576 Err(err) => { |
| 577 error = Some(err); |
| 578 break; |
| 579 }, |
| 580 }, |
| 548 Err(err) => { | 581 Err(err) => { |
| 549 panic_err = Some(err); | 582 panic_error = Some(err); |
| 550 break; | 583 break; |
| 551 }, | 584 }, |
| 552 } | 585 } |
| 553 inits += 1; | 586 inits += 1; |
| 554 } | 587 } |
| 555 if let Some(err) = panic_err { | 588 if panic_error.is_some() || error.is_some() { |
| 556 // Drop everything that was initialized | 589 // Drop everything that was initialized |
| 557 for i in 0..inits { | 590 for i in 0..inits { |
| 558 ptr::drop_in_place(&mut array[i] as *mut T); | 591 ptr::drop_in_place(&mut array[i] as *mut T); |
| 559 } | 592 } |
| 560 // Forget the array to prevent a drop | 593 // Forget the array to prevent a drop |
| 561 mem::forget(array); | 594 mem::forget(array); |
| 562 // Continue unwinding | 595 if let Some(err) = panic_error { |
| 563 panic::resume_unwind(err); | 596 panic::resume_unwind(err); |
| 597 } |
| 598 return Err(error.take().expect("Corrupted stack?")); |
| 564 } | 599 } |
| 565 } | 600 } |
| 566 array | 601 Ok(array) |
| 567 } | 602 } |
| 568 } | 603 } |
| 569 impl<T: MojomEncodable> MojomEncodable for [T; $len] { | 604 impl<T: MojomEncodable> MojomEncodable for [T; $len] { |
| 570 impl_encodable_for_array!(); | 605 impl_encodable_for_array!(); |
| 571 } | 606 } |
| 572 )* | 607 )* |
| 573 } | 608 } |
| 574 } | 609 } |
| 575 | 610 |
| 576 // Unfortunately, we cannot be generic over the length of a fixed array | 611 // Unfortunately, we cannot be generic over the length of a fixed array |
| 577 // even though its part of the type (this will hopefully be added in the | 612 // even though its part of the type (this will hopefully be added in the |
| 578 // future) so for now we implement encodable for only the first 33 fixed | 613 // future) so for now we implement encodable for only the first 33 fixed |
| 579 // size array types. | 614 // size array types. |
| 580 impl_encodable_for_fixed_array!( 0, 1, 2, 3, 4, 5, 6, 7, | 615 impl_encodable_for_fixed_array!( 0, 1, 2, 3, 4, 5, 6, 7, |
| 581 8, 9, 10, 11, 12, 13, 14, 15, | 616 8, 9, 10, 11, 12, 13, 14, 15, |
| 582 16, 17, 18, 19, 20, 21, 22, 23, | 617 16, 17, 18, 19, 20, 21, 22, 23, |
| 583 24, 25, 26, 27, 28, 29, 30, 31, | 618 24, 25, 26, 27, 28, 29, 30, 31, |
| 584 32); | 619 32); |
| 585 | 620 |
| 586 impl<T: MojomEncodable> MojomPointer for Box<[T]> { | 621 impl<T: MojomEncodable> MojomPointer for Box<[T]> { |
| 587 impl_pointer_for_array!(); | 622 impl_pointer_for_array!(); |
| 588 fn encode_value(self, encoder: &mut Encoder, context: Context) { | 623 fn encode_value(self, encoder: &mut Encoder, context: Context) { |
| 589 for elem in self.into_vec().into_iter() { | 624 for elem in self.into_vec().into_iter() { |
| 590 elem.encode(encoder, context.clone()); | 625 elem.encode(encoder, context.clone()); |
| 591 } | 626 } |
| 592 } | 627 } |
| 593 fn decode_value(decoder: &mut Decoder, context: Context) -> Box<[T]> { | 628 fn decode_value(decoder: &mut Decoder, context: Context) -> Result<Box<[T]>,
ValidationError> { |
| 594 Vec::<T>::decode_value(decoder, context).into_boxed_slice() | 629 match Vec::<T>::decode_value(decoder, context) { |
| 630 Ok(vec) => Ok(vec.into_boxed_slice()), |
| 631 Err(err) => Err(err), |
| 632 } |
| 595 } | 633 } |
| 596 } | 634 } |
| 597 | 635 |
| 598 impl<T: MojomEncodable> MojomEncodable for Box<[T]> { | 636 impl<T: MojomEncodable> MojomEncodable for Box<[T]> { |
| 599 impl_encodable_for_array!(); | 637 impl_encodable_for_array!(); |
| 600 } | 638 } |
| 601 | 639 |
| 602 // We can represent a Mojom string as just a Rust String type | 640 // We can represent a Mojom string as just a Rust String type |
| 603 // since both are UTF-8. | 641 // since both are UTF-8. |
| 604 impl MojomPointer for String { | 642 impl MojomPointer for String { |
| 605 fn header_data(&self) -> DataHeaderValue { | 643 fn header_data(&self) -> DataHeaderValue { |
| 606 DataHeaderValue::Elements(self.len() as u32) | 644 DataHeaderValue::Elements(self.len() as u32) |
| 607 } | 645 } |
| 608 fn serialized_size(&self, _context: &Context) -> usize { | 646 fn serialized_size(&self, _context: &Context) -> usize { |
| 609 DATA_HEADER_SIZE + self.len() | 647 DATA_HEADER_SIZE + self.len() |
| 610 } | 648 } |
| 611 fn encode_value(self, encoder: &mut Encoder, context: Context) { | 649 fn encode_value(self, encoder: &mut Encoder, context: Context) { |
| 612 for byte in self.as_bytes() { | 650 for byte in self.as_bytes() { |
| 613 byte.encode(encoder, context.clone()); | 651 byte.encode(encoder, context.clone()); |
| 614 } | 652 } |
| 615 } | 653 } |
| 616 fn decode_value(decoder: &mut Decoder, context: Context) -> String { | 654 fn decode_value(decoder: &mut Decoder, context: Context) -> Result<String, V
alidationError> { |
| 617 let mut state = decoder.get_mut(&context); | 655 let mut state = decoder.get_mut(&context); |
| 618 // TODO(mknyszek): Verify elems, bytes, and T::embed_size match | 656 let elems = match state.decode_array_header::<u8>() { |
| 619 let _bytes = state.decode::<u32>(); | 657 Ok(header) => header.data(), |
| 620 let elems = state.decode::<u32>(); | 658 Err(err) => return Err(err), |
| 659 }; |
| 621 let mut value = Vec::with_capacity(elems as usize); | 660 let mut value = Vec::with_capacity(elems as usize); |
| 622 // TODO(mknyszek): Don't trust elems blindly | |
| 623 for _ in 0..elems { | 661 for _ in 0..elems { |
| 624 value.push(state.decode::<u8>()); | 662 value.push(state.decode::<u8>()); |
| 625 } | 663 } |
| 626 match String::from_utf8(value) { | 664 match String::from_utf8(value) { |
| 627 Ok(string) => string, | 665 Ok(string) => Ok(string), |
| 628 // TODO(mknyszek): Don't panic and return an error | |
| 629 Err(err) => panic!("Error decoding String: {}", err), | 666 Err(err) => panic!("Error decoding String: {}", err), |
| 630 } | 667 } |
| 631 } | 668 } |
| 632 } | 669 } |
| 633 | 670 |
| 634 impl MojomEncodable for String { | 671 impl MojomEncodable for String { |
| 635 impl_encodable_for_pointer!(); | 672 impl_encodable_for_pointer!(); |
| 636 fn compute_size(&self, context: Context) -> usize { | 673 fn compute_size(&self, context: Context) -> usize { |
| 637 encoding::align_default(self.serialized_size(&context)) | 674 encoding::align_default(self.serialized_size(&context)) |
| 638 } | 675 } |
| 639 } | 676 } |
| 640 | 677 |
| 678 /// Helper function to clean up duplicate code in HashMap. |
| 679 fn array_claim_and_decode_header<T: MojomEncodable>(decoder: &mut Decoder, offse
t: usize) -> Result<(Context, usize), ValidationError> { |
| 680 let context = match decoder.claim(offset) { |
| 681 Ok(new_context) => new_context, |
| 682 Err(err) => return Err(err), |
| 683 }; |
| 684 let elems = { |
| 685 let state = decoder.get_mut(&context); |
| 686 match state.decode_array_header::<T>() { |
| 687 Ok(header) => header.data(), |
| 688 Err(err) => return Err(err), |
| 689 } |
| 690 }; |
| 691 Ok((context, elems as usize)) |
| 692 } |
| 693 |
| 641 impl<K: MojomEncodable + Eq + Hash, V: MojomEncodable> MojomPointer for HashMap<
K, V> { | 694 impl<K: MojomEncodable + Eq + Hash, V: MojomEncodable> MojomPointer for HashMap<
K, V> { |
| 642 fn header_data(&self) -> DataHeaderValue { | 695 fn header_data(&self) -> DataHeaderValue { |
| 643 DataHeaderValue::Version(0) | 696 DataHeaderValue::Version(0) |
| 644 } | 697 } |
| 645 fn serialized_size(&self, _context: &Context) -> usize { | 698 fn serialized_size(&self, _context: &Context) -> usize { |
| 646 MAP_SIZE | 699 MAP_SIZE |
| 647 } | 700 } |
| 648 fn encode_value(self, encoder: &mut Encoder, context: Context) { | 701 fn encode_value(self, encoder: &mut Encoder, context: Context) { |
| 649 let elems = self.len(); | 702 let elems = self.len(); |
| 650 let meta_value = DataHeaderValue::Elements(elems as u32); | 703 let meta_value = DataHeaderValue::Elements(elems as u32); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 664 // Claim space for the keys array in the encoder | 717 // Claim space for the keys array in the encoder |
| 665 let keys_context = encoder.add(&keys_data_header).unwrap(); | 718 let keys_context = encoder.add(&keys_data_header).unwrap(); |
| 666 // Encode keys, setup vals | 719 // Encode keys, setup vals |
| 667 for (key, value) in self.into_iter() { | 720 for (key, value) in self.into_iter() { |
| 668 key.encode(encoder, keys_context.clone()); | 721 key.encode(encoder, keys_context.clone()); |
| 669 vals_vec.push(value); | 722 vals_vec.push(value); |
| 670 } | 723 } |
| 671 // Encode vals | 724 // Encode vals |
| 672 vals_vec.encode(encoder, context.clone()) | 725 vals_vec.encode(encoder, context.clone()) |
| 673 } | 726 } |
| 674 fn decode_value(decoder: &mut Decoder, context: Context) -> HashMap<K, V> { | 727 fn decode_value(decoder: &mut Decoder, context: Context) -> Result<HashMap<K
, V>, ValidationError> { |
| 675 // TODO(mknyszek): Verify elems, bytes, and T::embed_size match | |
| 676 let (keys_offset, vals_offset) = { | 728 let (keys_offset, vals_offset) = { |
| 677 let mut state = decoder.get_mut(&context); | 729 let state = decoder.get_mut(&context); |
| 678 let _bytes = state.decode::<u32>(); | 730 match state.decode_struct_header(&MAP_VERSIONS) { |
| 679 let _version = state.decode::<u32>(); | 731 Ok(_) => (), |
| 680 let keys_offset = state.decode_pointer() as usize; | 732 Err(err) => return Err(err), |
| 681 let vals_offset = state.decode_pointer() as usize; | 733 }; |
| 682 (keys_offset, vals_offset) | 734 // Decode the keys pointer and check for overflow |
| 735 let keys_offset = match state.decode_pointer() { |
| 736 Some(ptr) => ptr, |
| 737 None => return Err(ValidationError::IllegalPointer), |
| 738 }; |
| 739 // Decode the keys pointer and check for overflow |
| 740 let vals_offset = match state.decode_pointer() { |
| 741 Some(ptr) => ptr, |
| 742 None => return Err(ValidationError::IllegalPointer), |
| 743 }; |
| 744 if keys_offset == MOJOM_NULL_POINTER || vals_offset == MOJOM_NULL_PO
INTER { |
| 745 return Err(ValidationError::UnexpectedNullPointer); |
| 746 } |
| 747 (keys_offset as usize, vals_offset as usize) |
| 683 }; | 748 }; |
| 684 let keys_context = decoder.claim(keys_offset).unwrap(); | 749 let (keys_context, keys_elems) = match array_claim_and_decode_header::<K
>(decoder, keys_offset) { |
| 685 let keys_elems = { | 750 Ok((context, elems)) => (context, elems), |
| 686 let state = decoder.get_mut(&keys_context); | 751 Err(err) => return Err(err), |
| 687 let _size_keys = state.decode::<u32>(); | |
| 688 state.decode::<u32>() | |
| 689 }; | 752 }; |
| 690 let mut keys_vec: Vec<K> = Vec::with_capacity(keys_elems as usize); | 753 let mut keys_vec: Vec<K> = Vec::with_capacity(keys_elems as usize); |
| 691 for _ in 0..keys_elems { | 754 for _ in 0..keys_elems { |
| 692 let key = K::decode(decoder, keys_context.clone()); | 755 let key = match K::decode(decoder, keys_context.clone()) { |
| 756 Ok(value) => value, |
| 757 Err(err) => return Err(err), |
| 758 }; |
| 693 keys_vec.push(key); | 759 keys_vec.push(key); |
| 694 } | 760 } |
| 695 let vals_context = decoder.claim(vals_offset).unwrap(); | 761 let (vals_context, vals_elems) = match array_claim_and_decode_header::<V
>(decoder, vals_offset) { |
| 696 let vals_elems = { | 762 Ok((context, elems)) => (context, elems), |
| 697 let state = decoder.get_mut(&vals_context); | 763 Err(err) => return Err(err), |
| 698 let _size_vals = state.decode::<u32>(); | |
| 699 state.decode::<u32>() | |
| 700 }; | 764 }; |
| 701 // TODO(mknyszek): Do a validation error instead | 765 if keys_elems != vals_elems { |
| 702 assert_eq!(keys_elems, vals_elems); | 766 return Err(ValidationError::DifferentSizedArraysInMap); |
| 703 // TODO(mknyszek): Don't trust elems blindly | 767 } |
| 704 let mut map = HashMap::with_capacity(keys_elems as usize); | 768 let mut map = HashMap::with_capacity(keys_elems as usize); |
| 705 for key in keys_vec.into_iter() { | 769 for key in keys_vec.into_iter() { |
| 706 let val = V::decode(decoder, vals_context.clone()); | 770 let val = match V::decode(decoder, vals_context.clone()) { |
| 771 Ok(value) => value, |
| 772 Err(err) => return Err(err), |
| 773 }; |
| 707 map.insert(key, val); | 774 map.insert(key, val); |
| 708 } | 775 } |
| 709 map | 776 Ok(map) |
| 710 } | 777 } |
| 711 } | 778 } |
| 712 | 779 |
| 713 impl<K: MojomEncodable + Eq + Hash, V: MojomEncodable> MojomEncodable for HashMa
p<K, V> { | 780 impl<K: MojomEncodable + Eq + Hash, V: MojomEncodable> MojomEncodable for HashMa
p<K, V> { |
| 714 impl_encodable_for_pointer!(); | 781 impl_encodable_for_pointer!(); |
| 715 fn compute_size(&self, context: Context) -> usize { | 782 fn compute_size(&self, context: Context) -> usize { |
| 716 let mut size = encoding::align_default(self.serialized_size(&context)); | 783 let mut size = encoding::align_default(self.serialized_size(&context)); |
| 717 // The size of the one array | 784 // The size of the one array |
| 718 size += DATA_HEADER_SIZE; | 785 size += DATA_HEADER_SIZE; |
| 719 size += (K::embed_size(&context) * self.len()).as_bytes(); | 786 size += (K::embed_size(&context) * self.len()).as_bytes(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 Bits(8 * mem::size_of::<u32>()) | 818 Bits(8 * mem::size_of::<u32>()) |
| 752 } | 819 } |
| 753 fn compute_size(&self, _context: Context) -> usize { | 820 fn compute_size(&self, _context: Context) -> usize { |
| 754 0 | 821 0 |
| 755 } | 822 } |
| 756 fn encode(self, encoder: &mut Encoder, context: Context) { | 823 fn encode(self, encoder: &mut Encoder, context: Context) { |
| 757 let pos = encoder.add_handle(self.as_untyped()); | 824 let pos = encoder.add_handle(self.as_untyped()); |
| 758 let mut state = encoder.get_mut(&context); | 825 let mut state = encoder.get_mut(&context); |
| 759 state.encode(pos as i32); | 826 state.encode(pos as i32); |
| 760 } | 827 } |
| 761 fn decode(decoder: &mut Decoder, context: Context) -> $handle_type { | 828 fn decode(decoder: &mut Decoder, context: Context) -> Result<$handle_typ
e, ValidationError> { |
| 762 // TODO(mknyszek): Verify handle index | |
| 763 let handle_index = { | 829 let handle_index = { |
| 764 let mut state = decoder.get_mut(&context); | 830 let mut state = decoder.get_mut(&context); |
| 765 state.decode::<i32>() | 831 state.decode::<i32>() |
| 766 }; | 832 }; |
| 767 decoder.claim_handle::<$handle_type>(handle_index) | 833 decoder.claim_handle::<$handle_type>(handle_index) |
| 768 } | 834 } |
| 769 } | 835 } |
| 770 } | 836 } |
| 771 | 837 |
| 772 impl MojomEncodable for UntypedHandle { | 838 impl MojomEncodable for UntypedHandle { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 785 impl_encodable_for_handle!(data_pipe::Consumer<T>); | 851 impl_encodable_for_handle!(data_pipe::Consumer<T>); |
| 786 } | 852 } |
| 787 | 853 |
| 788 impl<T> MojomEncodable for data_pipe::Producer<T> { | 854 impl<T> MojomEncodable for data_pipe::Producer<T> { |
| 789 impl_encodable_for_handle!(data_pipe::Producer<T>); | 855 impl_encodable_for_handle!(data_pipe::Producer<T>); |
| 790 } | 856 } |
| 791 | 857 |
| 792 impl MojomEncodable for wait_set::WaitSet { | 858 impl MojomEncodable for wait_set::WaitSet { |
| 793 impl_encodable_for_handle!(wait_set::WaitSet); | 859 impl_encodable_for_handle!(wait_set::WaitSet); |
| 794 } | 860 } |
| OLD | NEW |