blob: 01af9cee935a416519069217244f06a77572138f [file] [log] [blame]
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package binary
import "fmt"
// Object is the interface to any class that wants to be encoded/decoded.
type Object interface {
// Class returns the serialize information and functionality for this type.
// The method should be valid on a nil pointer.
Class() Class
}
// ObjectCast is automatically called by the generated decoders.
func ObjectCast(obj Object) Object {
return obj
}
// UpgradeDecoder provides a decoder interface which maybe used to
// decode a stream from an old version into a newer version.
type UpgradeDecoder interface {
// New constructs a new Object that this decoder handles.
// For a frozen decoder, this would be the new version, not the frozen one, and as such the type returned may not
// match the schema this decoder was registered against.
New() Object
// DecodeTo reads into the supplied object from the supplied Decoder.
// The object must be the same concrete type that New would create, the
// implementation is allowed to panic if it is not.
DecodeTo(Decoder, Object)
}
// Class represents a struct type in the binary registry.
type Class interface {
// Encode writes the supplied object to the supplied Encoder.
// The object must be a type the Class understands, the implementation is
// allowed to panic if it is not.
Encode(Encoder, Object)
// DecodeTo reads into the supplied object from the supplied Decoder.
// The object must be a type the Class understands, the implementation is
// allowed to panic if it is not.
DecodeTo(Decoder, Object)
// Returns the type descriptor for the class.
Schema() *Entity
}
type FrozenClassBase struct{}
// FrozenClass' provides Encode() so that they satisfy the above Class
// interface, but they should never be called.
func (c *FrozenClassBase) Encode(e Encoder, o Object) {
e.SetError(fmt.Errorf(
"Attempt to encode a frozen object of type %T id %v", o, o.Class().Schema()))
}
// Generate is used to tag structures that need an auto generated Class.
// The codergen function searches packages for structs that have this type as an
// anonymous field, and then automatically generates the encoding and decoding
// functionality for those structures. For example, the following struct would
// create the Class with methods needed to encode and decode the Name and Value
// fields, and register that class.
// The embedding will also fully implement the binary.Object interface, but with
// methods that panic. This will get overridden with the generated Methods.
// This is important because it means the package is resolvable without the
// generated code, which means the types can be correctly evaluated during the
// generation process.
//
// type MyNamedValue struct {
// binary.Generate
// Name string
// Value []byte
// }
type Generate struct{}
func (Generate) Class() Class { panic("Class() not implemented") }
var _ Object = Generate{} // Verify that Generate implements Object.
// Frozen is used to tag structures that represent past versions of types
// which may appear in old capture files. Frozen must be include a "name" tag
// which identifies the name of the struct now in use. Manual upgrading is
// provided with a function of the form:
//
// func (before *FrozenStruct) upgrade(after *GenerateStruct)
//
// See binary/test/frozen.go for examples
type Frozen struct{}
func (Frozen) Class() Class { panic("Class() not implemented") }
var _ Object = Frozen{} // Verify that Frozen implements FrozenObject.