// 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: logreader

// Package logreader defines interfaces for reading log files remotely.
package logreader

import (
	"io"
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/security/access"
	"v.io/v23/vdl"
)

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

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

// LogEntry is a log entry from a log file.
type LogEntry struct {
	// The offset (in bytes) where this entry starts.
	Position int64
	// The content of the log entry.
	Line string
}

func (LogEntry) __VDLReflect(struct {
	Name string `vdl:"v.io/v23/services/logreader.LogEntry"`
}) {
}

func (x LogEntry) VDLIsZero() bool {
	return x == LogEntry{}
}

func (x LogEntry) VDLWrite(enc vdl.Encoder) error {
	if err := enc.StartValue(__VDLType_struct_1); err != nil {
		return err
	}
	if x.Position != 0 {
		if err := enc.NextFieldValueInt(0, vdl.Int64Type, x.Position); err != nil {
			return err
		}
	}
	if x.Line != "" {
		if err := enc.NextFieldValueString(1, vdl.StringType, x.Line); 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{}
	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:
			switch value, err := dec.ReadValueInt(64); {
			case err != nil:
				return err
			default:
				x.Position = value
			}
		case 1:
			switch value, err := dec.ReadValueString(); {
			case err != nil:
				return err
			default:
				x.Line = value
			}
		}
	}
}

//////////////////////////////////////////////////
// Const definitions

// A special NumEntries value that indicates that all entries should be
// returned by ReadLog.
const AllEntries = int32(-1)

//////////////////////////////////////////////////
// Interface definitions

// LogFileClientMethods is the client interface
// containing LogFile methods.
//
// LogFile can be used to access log files remotely.
type LogFileClientMethods interface {
	// Size returns the number of bytes in the receiving object.
	Size(*context.T, ...rpc.CallOpt) (int64, error)
	// ReadLog receives up to numEntries log entries starting at the
	// startPos offset (in bytes) in the receiving object. Each stream chunk
	// contains one log entry.
	//
	// If follow is true, ReadLog will block and wait for more entries to
	// arrive when it reaches the end of the file.
	//
	// ReadLog returns the position where it stopped reading, i.e. the
	// position where the next entry starts. This value can be used as
	// startPos for successive calls to ReadLog.
	//
	// The returned error will be EndOfFile if and only if ReadLog reached the
	// end of the file and no log entries were returned.
	ReadLog(_ *context.T, startPos int64, numEntries int32, follow bool, _ ...rpc.CallOpt) (LogFileReadLogClientCall, error)
}

// LogFileClientStub adds universal methods to LogFileClientMethods.
type LogFileClientStub interface {
	LogFileClientMethods
	rpc.UniversalServiceMethods
}

// LogFileClient returns a client stub for LogFile.
func LogFileClient(name string) LogFileClientStub {
	return implLogFileClientStub{name}
}

type implLogFileClientStub struct {
	name string
}

func (c implLogFileClientStub) Size(ctx *context.T, opts ...rpc.CallOpt) (o0 int64, err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "Size", nil, []interface{}{&o0}, opts...)
	return
}

func (c implLogFileClientStub) ReadLog(ctx *context.T, i0 int64, i1 int32, i2 bool, opts ...rpc.CallOpt) (ocall LogFileReadLogClientCall, err error) {
	var call rpc.ClientCall
	if call, err = v23.GetClient(ctx).StartCall(ctx, c.name, "ReadLog", []interface{}{i0, i1, i2}, opts...); err != nil {
		return
	}
	ocall = &implLogFileReadLogClientCall{ClientCall: call}
	return
}

// LogFileReadLogClientStream is the client stream for LogFile.ReadLog.
type LogFileReadLogClientStream interface {
	// RecvStream returns the receiver side of the LogFile.ReadLog client stream.
	RecvStream() interface {
		// Advance stages an item so that it may be retrieved via Value.  Returns
		// true iff there is an item to retrieve.  Advance must be called before
		// Value is called.  May block if an item is not available.
		Advance() bool
		// Value returns the item that was staged by Advance.  May panic if Advance
		// returned false or was not called.  Never blocks.
		Value() LogEntry
		// Err returns any error encountered by Advance.  Never blocks.
		Err() error
	}
}

// LogFileReadLogClientCall represents the call returned from LogFile.ReadLog.
type LogFileReadLogClientCall interface {
	LogFileReadLogClientStream
	// Finish blocks until the server is done, and returns the positional return
	// values for call.
	//
	// Finish returns immediately if the call has been canceled; depending on the
	// timing the output could either be an error signaling cancelation, or the
	// valid positional return values from the server.
	//
	// Calling Finish is mandatory for releasing stream resources, unless the call
	// has been canceled or any of the other methods return an error.  Finish should
	// be called at most once.
	Finish() (int64, error)
}

type implLogFileReadLogClientCall struct {
	rpc.ClientCall
	valRecv LogEntry
	errRecv error
}

func (c *implLogFileReadLogClientCall) RecvStream() interface {
	Advance() bool
	Value() LogEntry
	Err() error
} {
	return implLogFileReadLogClientCallRecv{c}
}

type implLogFileReadLogClientCallRecv struct {
	c *implLogFileReadLogClientCall
}

func (c implLogFileReadLogClientCallRecv) Advance() bool {
	c.c.valRecv = LogEntry{}
	c.c.errRecv = c.c.Recv(&c.c.valRecv)
	return c.c.errRecv == nil
}
func (c implLogFileReadLogClientCallRecv) Value() LogEntry {
	return c.c.valRecv
}
func (c implLogFileReadLogClientCallRecv) Err() error {
	if c.c.errRecv == io.EOF {
		return nil
	}
	return c.c.errRecv
}
func (c *implLogFileReadLogClientCall) Finish() (o0 int64, err error) {
	err = c.ClientCall.Finish(&o0)
	return
}

// LogFileServerMethods is the interface a server writer
// implements for LogFile.
//
// LogFile can be used to access log files remotely.
type LogFileServerMethods interface {
	// Size returns the number of bytes in the receiving object.
	Size(*context.T, rpc.ServerCall) (int64, error)
	// ReadLog receives up to numEntries log entries starting at the
	// startPos offset (in bytes) in the receiving object. Each stream chunk
	// contains one log entry.
	//
	// If follow is true, ReadLog will block and wait for more entries to
	// arrive when it reaches the end of the file.
	//
	// ReadLog returns the position where it stopped reading, i.e. the
	// position where the next entry starts. This value can be used as
	// startPos for successive calls to ReadLog.
	//
	// The returned error will be EndOfFile if and only if ReadLog reached the
	// end of the file and no log entries were returned.
	ReadLog(_ *context.T, _ LogFileReadLogServerCall, startPos int64, numEntries int32, follow bool) (int64, error)
}

// LogFileServerStubMethods is the server interface containing
// LogFile methods, as expected by rpc.Server.
// The only difference between this interface and LogFileServerMethods
// is the streaming methods.
type LogFileServerStubMethods interface {
	// Size returns the number of bytes in the receiving object.
	Size(*context.T, rpc.ServerCall) (int64, error)
	// ReadLog receives up to numEntries log entries starting at the
	// startPos offset (in bytes) in the receiving object. Each stream chunk
	// contains one log entry.
	//
	// If follow is true, ReadLog will block and wait for more entries to
	// arrive when it reaches the end of the file.
	//
	// ReadLog returns the position where it stopped reading, i.e. the
	// position where the next entry starts. This value can be used as
	// startPos for successive calls to ReadLog.
	//
	// The returned error will be EndOfFile if and only if ReadLog reached the
	// end of the file and no log entries were returned.
	ReadLog(_ *context.T, _ *LogFileReadLogServerCallStub, startPos int64, numEntries int32, follow bool) (int64, error)
}

// LogFileServerStub adds universal methods to LogFileServerStubMethods.
type LogFileServerStub interface {
	LogFileServerStubMethods
	// Describe the LogFile interfaces.
	Describe__() []rpc.InterfaceDesc
}

// LogFileServer returns a server stub for LogFile.
// It converts an implementation of LogFileServerMethods into
// an object that may be used by rpc.Server.
func LogFileServer(impl LogFileServerMethods) LogFileServerStub {
	stub := implLogFileServerStub{
		impl: impl,
	}
	// Initialize GlobState; always check the stub itself first, to handle the
	// case where the user has the Glob method defined in their VDL source.
	if gs := rpc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := rpc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implLogFileServerStub struct {
	impl LogFileServerMethods
	gs   *rpc.GlobState
}

func (s implLogFileServerStub) Size(ctx *context.T, call rpc.ServerCall) (int64, error) {
	return s.impl.Size(ctx, call)
}

func (s implLogFileServerStub) ReadLog(ctx *context.T, call *LogFileReadLogServerCallStub, i0 int64, i1 int32, i2 bool) (int64, error) {
	return s.impl.ReadLog(ctx, call, i0, i1, i2)
}

func (s implLogFileServerStub) Globber() *rpc.GlobState {
	return s.gs
}

func (s implLogFileServerStub) Describe__() []rpc.InterfaceDesc {
	return []rpc.InterfaceDesc{LogFileDesc}
}

// LogFileDesc describes the LogFile interface.
var LogFileDesc rpc.InterfaceDesc = descLogFile

// descLogFile hides the desc to keep godoc clean.
var descLogFile = rpc.InterfaceDesc{
	Name:    "LogFile",
	PkgPath: "v.io/v23/services/logreader",
	Doc:     "// LogFile can be used to access log files remotely.",
	Methods: []rpc.MethodDesc{
		{
			Name: "Size",
			Doc:  "// Size returns the number of bytes in the receiving object.",
			OutArgs: []rpc.ArgDesc{
				{"", ``}, // int64
			},
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Debug"))},
		},
		{
			Name: "ReadLog",
			Doc:  "// ReadLog receives up to numEntries log entries starting at the\n// startPos offset (in bytes) in the receiving object. Each stream chunk\n// contains one log entry.\n//\n// If follow is true, ReadLog will block and wait for more entries to\n// arrive when it reaches the end of the file.\n//\n// ReadLog returns the position where it stopped reading, i.e. the\n// position where the next entry starts. This value can be used as\n// startPos for successive calls to ReadLog.\n//\n// The returned error will be EndOfFile if and only if ReadLog reached the\n// end of the file and no log entries were returned.",
			InArgs: []rpc.ArgDesc{
				{"startPos", ``},   // int64
				{"numEntries", ``}, // int32
				{"follow", ``},     // bool
			},
			OutArgs: []rpc.ArgDesc{
				{"", ``}, // int64
			},
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Debug"))},
		},
	},
}

// LogFileReadLogServerStream is the server stream for LogFile.ReadLog.
type LogFileReadLogServerStream interface {
	// SendStream returns the send side of the LogFile.ReadLog server stream.
	SendStream() interface {
		// Send places the item onto the output stream.  Returns errors encountered
		// while sending.  Blocks if there is no buffer space; will unblock when
		// buffer space is available.
		Send(item LogEntry) error
	}
}

// LogFileReadLogServerCall represents the context passed to LogFile.ReadLog.
type LogFileReadLogServerCall interface {
	rpc.ServerCall
	LogFileReadLogServerStream
}

// LogFileReadLogServerCallStub is a wrapper that converts rpc.StreamServerCall into
// a typesafe stub that implements LogFileReadLogServerCall.
type LogFileReadLogServerCallStub struct {
	rpc.StreamServerCall
}

// Init initializes LogFileReadLogServerCallStub from rpc.StreamServerCall.
func (s *LogFileReadLogServerCallStub) Init(call rpc.StreamServerCall) {
	s.StreamServerCall = call
}

// SendStream returns the send side of the LogFile.ReadLog server stream.
func (s *LogFileReadLogServerCallStub) SendStream() interface {
	Send(item LogEntry) error
} {
	return implLogFileReadLogServerCallSend{s}
}

type implLogFileReadLogServerCallSend struct {
	s *LogFileReadLogServerCallStub
}

func (s implLogFileReadLogServerCallSend) Send(item LogEntry) error {
	return s.s.Send(item)
}

// Hold type definitions in package-level variables, for better performance.
var (
	__VDLType_struct_1 *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((*LogEntry)(nil))

	// Initialize type definitions.
	__VDLType_struct_1 = vdl.TypeOf((*LogEntry)(nil)).Elem()

	return struct{}{}
}
