diff options
Diffstat (limited to 'third_party/mojo/src/mojo/public/go/bindings/message.go')
-rw-r--r-- | third_party/mojo/src/mojo/public/go/bindings/message.go | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/third_party/mojo/src/mojo/public/go/bindings/message.go b/third_party/mojo/src/mojo/public/go/bindings/message.go new file mode 100644 index 0000000..786ec47 --- /dev/null +++ b/third_party/mojo/src/mojo/public/go/bindings/message.go @@ -0,0 +1,164 @@ +// Copyright 2015 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. + +package bindings + +import ( + "fmt" + + "mojo/public/go/system" +) + +const ( + // Flag for a header of a simple message. + MessageNoFlag = 0 + + // Flag for a header of a message that expected a response. + MessageExpectsResponseFlag = 1 << 0 + + // Flag for a header of a message that is a response. + MessageIsResponseFlag = 1 << 1 + + dataHeaderSize = 8 + defaultAlignment = 8 + pointerBitSize = 64 +) + +var mapHeader DataHeader + +func init() { + mapHeader = DataHeader{24, 2} +} + +// Payload is an interface implemented by a mojo struct that can encode/decode +// itself into mojo archive format. +type Payload interface { + Encode(encoder *Encoder) error + Decode(decoder *Decoder) error +} + +// DataHeader is a header for a mojo complex element. +type DataHeader struct { + Size uint32 + Elements uint32 +} + +// MessageHeader is a header information for a message. +type MessageHeader struct { + Type uint32 + Flags uint32 + RequestId uint64 +} + +func (h *MessageHeader) Encode(encoder *Encoder) error { + encoder.StartStruct(h.dataSize(), h.numFields()) + if err := encoder.WriteUint32(h.Type); err != nil { + return err + } + if err := encoder.WriteUint32(h.Flags); err != nil { + return err + } + if h.RequestId != 0 { + if err := encoder.WriteUint64(h.RequestId); err != nil { + return err + } + } + return encoder.Finish() +} + +func (h *MessageHeader) Decode(decoder *Decoder) error { + numFields, err := decoder.StartStruct() + if err != nil { + return err + } + if numFields < 2 || numFields > 3 { + return fmt.Errorf("Invalid message header: it should have 2 or 3 fileds, but has %d", numFields) + } + if h.Type, err = decoder.ReadUint32(); err != nil { + return err + } + if h.Flags, err = decoder.ReadUint32(); err != nil { + return err + } + if numFields == 3 { + if h.Flags != MessageExpectsResponseFlag && h.Flags != MessageIsResponseFlag { + return fmt.Errorf("Message header flags(%v) should be MessageExpectsResponseFlag or MessageIsResponseFlag", h.Flags) + } + if h.RequestId, err = decoder.ReadUint64(); err != nil { + return err + } + } else { + if h.Flags != MessageNoFlag { + return fmt.Errorf("Message header flags(%v) should be MessageNoFlag", h.Flags) + } + } + return decoder.Finish() +} + +func (h *MessageHeader) dataSize() uint32 { + var size uint32 + size = 2 * 4 + if h.RequestId != 0 { + size += 8 + } + return size +} + +func (h *MessageHeader) numFields() uint32 { + if h.RequestId != 0 { + return 3 + } else { + return 2 + } +} + +// Message is a a raw message to be sent/received from a message pipe handle +// which contains a message header. +type Message struct { + Header MessageHeader + Bytes []byte + Handles []system.UntypedHandle + Payload []byte +} + +func newMessage(header MessageHeader, bytes []byte, handles []system.UntypedHandle) *Message { + return &Message{header, bytes, handles, bytes[header.dataSize()+dataHeaderSize:]} +} + +// DecodePayload decodes the provided payload from the message. +func (m *Message) DecodePayload(payload Payload) error { + decoder := NewDecoder(m.Payload, m.Handles) + if err := payload.Decode(decoder); err != nil { + return err + } + return nil +} + +// EncodeMessage returns a message with provided header that has provided +// payload encoded in mojo archive format. +func EncodeMessage(header MessageHeader, payload Payload) (*Message, error) { + encoder := NewEncoder() + if err := header.Encode(encoder); err != nil { + return nil, err + } + if err := payload.Encode(encoder); err != nil { + return nil, err + } + if bytes, handles, err := encoder.Data(); err != nil { + return nil, err + } else { + return newMessage(header, bytes, handles), nil + } +} + +// ParseMessage parses message header from byte buffer with attached handles +// and returnes parsed message. +func ParseMessage(bytes []byte, handles []system.UntypedHandle) (*Message, error) { + decoder := NewDecoder(bytes, []system.UntypedHandle{}) + var header MessageHeader + if err := header.Decode(decoder); err != nil { + return nil, err + } + return newMessage(header, bytes, handles), nil +} |