// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file was auto-generated by the vanadium vdl tool.
// Package: watchable

package watchable

import (
	"v.io/v23/vdl"
	"v.io/v23/vom"
)

var _ = __VDLInit() // Must be first; see __VDLInit comments for details.

//////////////////////////////////////////////////
// Type definitions

// GetOp represents a store get operation.
type GetOp struct {
	Key []byte
}

func (GetOp) __VDLReflect(struct {
	Name string `vdl:"v.io/x/ref/services/syncbase/store/watchable.GetOp"`
}) {
}

func (x GetOp) VDLIsZero() bool {
	if len(x.Key) != 0 {
		return false
	}
	return true
}

func (x GetOp) VDLWrite(enc vdl.Encoder) error {
	if err := enc.StartValue(__VDLType_struct_1); err != nil {
		return err
	}
	if len(x.Key) != 0 {
		if err := enc.NextFieldValueBytes(0, __VDLType_list_2, x.Key); err != nil {
			return err
		}
	}
	if err := enc.NextField(-1); err != nil {
		return err
	}
	return enc.FinishValue()
}

func (x *GetOp) VDLRead(dec vdl.Decoder) error {
	*x = GetOp{}
	if err := dec.StartValue(__VDLType_struct_1); err != nil {
		return err
	}
	decType := dec.Type()
	for {
		index, err := dec.NextField()
		switch {
		case err != nil:
			return err
		case index == -1:
			return dec.FinishValue()
		}
		if decType != __VDLType_struct_1 {
			index = __VDLType_struct_1.FieldIndexByName(decType.Field(index).Name)
			if index == -1 {
				if err := dec.SkipValue(); err != nil {
					return err
				}
				continue
			}
		}
		switch index {
		case 0:
			if err := dec.ReadValueBytes(-1, &x.Key); err != nil {
				return err
			}
		}
	}
}

// ScanOp represents a store scan operation.
type ScanOp struct {
	Start []byte
	Limit []byte
}

func (ScanOp) __VDLReflect(struct {
	Name string `vdl:"v.io/x/ref/services/syncbase/store/watchable.ScanOp"`
}) {
}

func (x ScanOp) VDLIsZero() bool {
	if len(x.Start) != 0 {
		return false
	}
	if len(x.Limit) != 0 {
		return false
	}
	return true
}

func (x ScanOp) VDLWrite(enc vdl.Encoder) error {
	if err := enc.StartValue(__VDLType_struct_3); err != nil {
		return err
	}
	if len(x.Start) != 0 {
		if err := enc.NextFieldValueBytes(0, __VDLType_list_2, x.Start); err != nil {
			return err
		}
	}
	if len(x.Limit) != 0 {
		if err := enc.NextFieldValueBytes(1, __VDLType_list_2, x.Limit); err != nil {
			return err
		}
	}
	if err := enc.NextField(-1); err != nil {
		return err
	}
	return enc.FinishValue()
}

func (x *ScanOp) VDLRead(dec vdl.Decoder) error {
	*x = ScanOp{}
	if err := dec.StartValue(__VDLType_struct_3); err != nil {
		return err
	}
	decType := dec.Type()
	for {
		index, err := dec.NextField()
		switch {
		case err != nil:
			return err
		case index == -1:
			return dec.FinishValue()
		}
		if decType != __VDLType_struct_3 {
			index = __VDLType_struct_3.FieldIndexByName(decType.Field(index).Name)
			if index == -1 {
				if err := dec.SkipValue(); err != nil {
					return err
				}
				continue
			}
		}
		switch index {
		case 0:
			if err := dec.ReadValueBytes(-1, &x.Start); err != nil {
				return err
			}
		case 1:
			if err := dec.ReadValueBytes(-1, &x.Limit); err != nil {
				return err
			}
		}
	}
}

// PutOp represents a store put operation.  The new version is written instead
// of the value to avoid duplicating the user data in the store.  The version
// is used to access the user data of that specific mutation.
type PutOp struct {
	Key     []byte
	Version []byte
}

func (PutOp) __VDLReflect(struct {
	Name string `vdl:"v.io/x/ref/services/syncbase/store/watchable.PutOp"`
}) {
}

func (x PutOp) VDLIsZero() bool {
	if len(x.Key) != 0 {
		return false
	}
	if len(x.Version) != 0 {
		return false
	}
	return true
}

func (x PutOp) VDLWrite(enc vdl.Encoder) error {
	if err := enc.StartValue(__VDLType_struct_4); err != nil {
		return err
	}
	if len(x.Key) != 0 {
		if err := enc.NextFieldValueBytes(0, __VDLType_list_2, x.Key); err != nil {
			return err
		}
	}
	if len(x.Version) != 0 {
		if err := enc.NextFieldValueBytes(1, __VDLType_list_2, x.Version); err != nil {
			return err
		}
	}
	if err := enc.NextField(-1); err != nil {
		return err
	}
	return enc.FinishValue()
}

func (x *PutOp) VDLRead(dec vdl.Decoder) error {
	*x = PutOp{}
	if err := dec.StartValue(__VDLType_struct_4); err != nil {
		return err
	}
	decType := dec.Type()
	for {
		index, err := dec.NextField()
		switch {
		case err != nil:
			return err
		case index == -1:
			return dec.FinishValue()
		}
		if decType != __VDLType_struct_4 {
			index = __VDLType_struct_4.FieldIndexByName(decType.Field(index).Name)
			if index == -1 {
				if err := dec.SkipValue(); err != nil {
					return err
				}
				continue
			}
		}
		switch index {
		case 0:
			if err := dec.ReadValueBytes(-1, &x.Key); err != nil {
				return err
			}
		case 1:
			if err := dec.ReadValueBytes(-1, &x.Version); err != nil {
				return err
			}
		}
	}
}

// DeleteOp represents a store delete operation.
type DeleteOp struct {
	Key []byte
}

func (DeleteOp) __VDLReflect(struct {
	Name string `vdl:"v.io/x/ref/services/syncbase/store/watchable.DeleteOp"`
}) {
}

func (x DeleteOp) VDLIsZero() bool {
	if len(x.Key) != 0 {
		return false
	}
	return true
}

func (x DeleteOp) VDLWrite(enc vdl.Encoder) error {
	if err := enc.StartValue(__VDLType_struct_5); err != nil {
		return err
	}
	if len(x.Key) != 0 {
		if err := enc.NextFieldValueBytes(0, __VDLType_list_2, x.Key); err != nil {
			return err
		}
	}
	if err := enc.NextField(-1); err != nil {
		return err
	}
	return enc.FinishValue()
}

func (x *DeleteOp) VDLRead(dec vdl.Decoder) error {
	*x = DeleteOp{}
	if err := dec.StartValue(__VDLType_struct_5); err != nil {
		return err
	}
	decType := dec.Type()
	for {
		index, err := dec.NextField()
		switch {
		case err != nil:
			return err
		case index == -1:
			return dec.FinishValue()
		}
		if decType != __VDLType_struct_5 {
			index = __VDLType_struct_5.FieldIndexByName(decType.Field(index).Name)
			if index == -1 {
				if err := dec.SkipValue(); err != nil {
					return err
				}
				continue
			}
		}
		switch index {
		case 0:
			if err := dec.ReadValueBytes(-1, &x.Key); err != nil {
				return err
			}
		}
	}
}

// LogEntry represents a single store operation. This operation may have been
// part of a transaction, as signified by the Continued boolean. Read-only
// operations (and read-only transactions) are not logged.
type LogEntry struct {
	// The store operation that was performed.
	Op *vom.RawBytes
	// Time when the operation was committed in nanoseconds since the epoch.
	// Note: We don't use time.Time here because VDL's time.Time consists of
	// {Seconds int64, Nanos int32}, which is more expensive than a single int64.
	CommitTimestamp int64
	// Operation came from sync (used for echo suppression).
	// TODO(razvanm): this field is specific to syncbase. We should add a
	// generic way to add fields and use that instead.
	FromSync bool
	// If true, this entry is followed by more entries that belong to the same
	// commit as this entry.
	Continued bool
}

func (LogEntry) __VDLReflect(struct {
	Name string `vdl:"v.io/x/ref/services/syncbase/store/watchable.LogEntry"`
}) {
}

func (x LogEntry) VDLIsZero() bool {
	if x.Op != nil && !x.Op.VDLIsZero() {
		return false
	}
	if x.CommitTimestamp != 0 {
		return false
	}
	if x.FromSync {
		return false
	}
	if x.Continued {
		return false
	}
	return true
}

func (x LogEntry) VDLWrite(enc vdl.Encoder) error {
	if err := enc.StartValue(__VDLType_struct_6); err != nil {
		return err
	}
	if x.Op != nil && !x.Op.VDLIsZero() {
		if err := enc.NextField(0); err != nil {
			return err
		}
		if err := x.Op.VDLWrite(enc); err != nil {
			return err
		}
	}
	if x.CommitTimestamp != 0 {
		if err := enc.NextFieldValueInt(1, vdl.Int64Type, x.CommitTimestamp); err != nil {
			return err
		}
	}
	if x.FromSync {
		if err := enc.NextFieldValueBool(2, vdl.BoolType, x.FromSync); err != nil {
			return err
		}
	}
	if x.Continued {
		if err := enc.NextFieldValueBool(3, vdl.BoolType, x.Continued); err != nil {
			return err
		}
	}
	if err := enc.NextField(-1); err != nil {
		return err
	}
	return enc.FinishValue()
}

func (x *LogEntry) VDLRead(dec vdl.Decoder) error {
	*x = LogEntry{
		Op: vom.RawBytesOf(vdl.ZeroValue(vdl.AnyType)),
	}
	if err := dec.StartValue(__VDLType_struct_6); err != nil {
		return err
	}
	decType := dec.Type()
	for {
		index, err := dec.NextField()
		switch {
		case err != nil:
			return err
		case index == -1:
			return dec.FinishValue()
		}
		if decType != __VDLType_struct_6 {
			index = __VDLType_struct_6.FieldIndexByName(decType.Field(index).Name)
			if index == -1 {
				if err := dec.SkipValue(); err != nil {
					return err
				}
				continue
			}
		}
		switch index {
		case 0:
			x.Op = new(vom.RawBytes)
			if err := x.Op.VDLRead(dec); err != nil {
				return err
			}
		case 1:
			switch value, err := dec.ReadValueInt(64); {
			case err != nil:
				return err
			default:
				x.CommitTimestamp = value
			}
		case 2:
			switch value, err := dec.ReadValueBool(); {
			case err != nil:
				return err
			default:
				x.FromSync = value
			}
		case 3:
			switch value, err := dec.ReadValueBool(); {
			case err != nil:
				return err
			default:
				x.Continued = value
			}
		}
	}
}

// Hold type definitions in package-level variables, for better performance.
var (
	__VDLType_struct_1 *vdl.Type
	__VDLType_list_2   *vdl.Type
	__VDLType_struct_3 *vdl.Type
	__VDLType_struct_4 *vdl.Type
	__VDLType_struct_5 *vdl.Type
	__VDLType_struct_6 *vdl.Type
)

var __VDLInitCalled bool

// __VDLInit performs vdl initialization.  It is safe to call multiple times.
// If you have an init ordering issue, just insert the following line verbatim
// into your source files in this package, right after the "package foo" clause:
//
//    var _ = __VDLInit()
//
// The purpose of this function is to ensure that vdl initialization occurs in
// the right order, and very early in the init sequence.  In particular, vdl
// registration and package variable initialization needs to occur before
// functions like vdl.TypeOf will work properly.
//
// This function returns a dummy value, so that it can be used to initialize the
// first var in the file, to take advantage of Go's defined init order.
func __VDLInit() struct{} {
	if __VDLInitCalled {
		return struct{}{}
	}
	__VDLInitCalled = true

	// Register types.
	vdl.Register((*GetOp)(nil))
	vdl.Register((*ScanOp)(nil))
	vdl.Register((*PutOp)(nil))
	vdl.Register((*DeleteOp)(nil))
	vdl.Register((*LogEntry)(nil))

	// Initialize type definitions.
	__VDLType_struct_1 = vdl.TypeOf((*GetOp)(nil)).Elem()
	__VDLType_list_2 = vdl.TypeOf((*[]byte)(nil))
	__VDLType_struct_3 = vdl.TypeOf((*ScanOp)(nil)).Elem()
	__VDLType_struct_4 = vdl.TypeOf((*PutOp)(nil)).Elem()
	__VDLType_struct_5 = vdl.TypeOf((*DeleteOp)(nil)).Elem()
	__VDLType_struct_6 = vdl.TypeOf((*LogEntry)(nil)).Elem()

	return struct{}{}
}
