https://github.com/google/cayley
Raw File
Tip revision: 03ab36624ad88600895d6dcb9c4249192ac14a6e authored by admin on 15 February 2019, 06:52:25 UTC
kv: get badger to work
Tip revision: 03ab366
rw.go
package quad

import (
	"io"
)

// Writer is a minimal interface for quad writers. Used for quad serializers and quad stores.
type Writer interface {
	WriteQuad(Quad) error
}

type WriteCloser interface {
	Writer
	io.Closer
}

// BatchWriter is an interface for writing quads in batches.
//
// WriteQuads returns a number of quads that where written and an error, if any.
type BatchWriter interface {
	WriteQuads(buf []Quad) (int, error)
}

// Reader is a minimal interface for quad readers. Used for quad deserializers and quad iterators.
//
// ReadQuad reads next valid Quad. It returns io.EOF if no quads are left.
type Reader interface {
	ReadQuad() (Quad, error)
}

// Skipper is an interface for quad reader that can skip quads efficiently without decoding them.
//
// It returns io.EOF if no quads are left.
type Skipper interface {
	SkipQuad() error
}

type ReadCloser interface {
	Reader
	io.Closer
}

type ReadSkipCloser interface {
	Reader
	Skipper
	io.Closer
}

// BatchReader is an interface for reading quads in batches.
//
// ReadQuads reads at most len(buf) quads into buf. It returns number of quads that were read and an error.
// It returns an io.EOF if there is no more quads to read.
type BatchReader interface {
	ReadQuads(buf []Quad) (int, error)
}

type Quads struct {
	s []Quad
}

func (r *Quads) WriteQuad(q Quad) error {
	r.s = append(r.s, q)
	return nil
}

func (r *Quads) ReadQuad() (Quad, error) {
	if r == nil || len(r.s) == 0 {
		return Quad{}, io.EOF
	}
	q := r.s[0]
	r.s = r.s[1:]
	if len(r.s) == 0 {
		r.s = nil
	}
	return q, nil
}

// NewReader creates a quad reader from a quad slice.
func NewReader(quads []Quad) *Quads {
	return &Quads{s: quads}
}

// Copy will copy all quads from src to dst. It returns copied quads count and an error, if it failed.
//
// Copy will try to cast dst to BatchWriter and will switch to CopyBatch implementation in case of success.
func Copy(dst Writer, src Reader) (n int, err error) {
	if bw, ok := dst.(BatchWriter); ok {
		return CopyBatch(bw, src, 0)
	}
	var q Quad
	for {
		q, err = src.ReadQuad()
		if err == io.EOF {
			err = nil
			return
		} else if err != nil {
			return
		}
		if err = dst.WriteQuad(q); err != nil {
			return
		}
		n++
	}
}

type batchReader struct {
	Reader
}

func (r batchReader) ReadQuads(quads []Quad) (n int, err error) {
	for ; n < len(quads); n++ {
		quads[n], err = r.ReadQuad()
		if err != nil {
			break
		}
	}
	return
}

var DefaultBatch = 10000

// CopyBatch will copy all quads from src to dst in a batches of batchSize.
// It returns copied quads count and an error, if it failed.
//
// If batchSize <= 0 default batch size will be used.
func CopyBatch(dst BatchWriter, src Reader, batchSize int) (cnt int, err error) {
	if batchSize <= 0 {
		batchSize = DefaultBatch
	}
	buf := make([]Quad, batchSize)
	bsrc, ok := src.(BatchReader)
	if !ok {
		bsrc = batchReader{src}
	}
	var n int
	for err == nil {
		n, err = bsrc.ReadQuads(buf)
		if err != nil && err != io.EOF {
			return
		}
		eof := err == io.EOF
		n, err = dst.WriteQuads(buf[:n])
		cnt += n
		if eof {
			break
		}
	}
	return
}

// ReadAll reads all quads from r until EOF.
// It returns a slice with all quads that were read and an error, if any.
func ReadAll(r Reader) (arr []Quad, err error) {
	switch rt := r.(type) {
	case *Quads:
		arr = make([]Quad, len(rt.s))
		copy(arr, rt.s)
		rt.s = nil
		return
	}
	var q Quad
	for {
		q, err = r.ReadQuad()
		if err == io.EOF {
			return arr, nil
		} else if err != nil {
			return nil, err
		}
		arr = append(arr, q)
	}
}
back to top