blob: 2cdda8adb1f8ee29011baf173192d66bc309f593 [file] [log] [blame]
// Copyright 2014 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.
part of bindings;
class MessageHeader {
static const int kSimpleMessageSize = 16;
static const int kSimpleMessageNumFields = 2;
static const int kMessageWithRequestIdSize = 24;
static const int kMessageWithRequestIdNumFields = 3;
static const int kMessageTypeOffset = DataHeader.kHeaderSize;
static const int kMessageFlagsOffset = kMessageTypeOffset + 4;
static const int kMessageRequestIdOffset = kMessageFlagsOffset + 4;
static const int kMessageExpectsResponse = 1 << 0;
static const int kMessageIsResponse = 1 << 1;
DataHeader _header;
int type;
int flags;
int requestId;
static bool mustHaveRequestId(int flags) =>
(flags & (kMessageExpectsResponse | kMessageIsResponse)) != 0;
MessageHeader(this.type) :
_header = new DataHeader(kSimpleMessageSize, kSimpleMessageNumFields),
flags = 0,
requestId = 0;
MessageHeader.withRequestId(this.type, this.flags, this.requestId) :
_header = new DataHeader(
kMessageWithRequestIdSize, kMessageWithRequestIdNumFields);
MessageHeader.fromMessage(Message message) {
var decoder = new Decoder(message);
_header = decoder.decodeDataHeader();
type = decoder.decodeUint32(kMessageTypeOffset);
flags = decoder.decodeUint32(kMessageFlagsOffset);
if (mustHaveRequestId(flags)) {
if (_header.size < kMessageWithRequestIdSize) {
throw 'Incorrect message size. Got: ${_header.size} ' +
'wanted $kMessageWithRequestIdSize';
}
requestId = decoder.decodeUint64(kMessageRequestIdOffset);
} else {
requestId = 0;
}
}
int get size => _header.size;
bool get hasRequestId => mustHaveRequestId(flags);
void encode(Encoder encoder) {
encoder.encodeDataHeader(_header);
encoder.encodeUint32(type, kMessageTypeOffset);
encoder.encodeUint32(flags, kMessageFlagsOffset);
if (hasRequestId) {
encoder.encodeUint64(requestId, kMessageRequestIdOffset);
}
}
ServiceMessage get serviceMessage => new ServiceMessage(this);
String toString() => "MessageHeader($_header, $type, $flags, $requestId)";
}
class Message {
final ByteData buffer;
final List<core.MojoHandle> handles;
Message(this.buffer, this.handles);
String toString() =>
"Message(numBytes=${buffer.lengthInBytes}, numHandles=${handles.length})";
}
class ServiceMessage extends Message {
final MessageHeader header;
Message _payload;
ServiceMessage(Message message, this.header)
: super(message.buffer, message.handles);
ServiceMessage.fromMessage(Message message)
: this(message, new MessageHeader.fromMessage(message));
Message get payload {
if (_payload == null) {
var truncatedBuffer = new ByteData.view(buffer.buffer, header.size);
_payload = new Message(truncatedBuffer, handles);
}
return _payload;
}
String toString() => "ServiceMessage($header, $_payload)";
}