1package quad 2 3import ( 4 "io" 5) 6 7// Writer is a minimal interface for quad writers. Used for quad serializers and quad stores. 8type Writer interface { 9 WriteQuad(Quad) error 10} 11 12type WriteCloser interface { 13 Writer 14 io.Closer 15} 16 17// BatchWriter is an interface for writing quads in batches. 18// 19// WriteQuads returns a number of quads that where written and an error, if any. 20type BatchWriter interface { 21 WriteQuads(buf []Quad) (int, error) 22} 23 24// Reader is a minimal interface for quad readers. Used for quad deserializers and quad iterators. 25// 26// ReadQuad reads next valid Quad. It returns io.EOF if no quads are left. 27type Reader interface { 28 ReadQuad() (Quad, error) 29} 30 31// Skipper is an interface for quad reader that can skip quads efficiently without decoding them. 32// 33// It returns io.EOF if no quads are left. 34type Skipper interface { 35 SkipQuad() error 36} 37 38type ReadCloser interface { 39 Reader 40 io.Closer 41} 42 43type ReadSkipCloser interface { 44 Reader 45 Skipper 46 io.Closer 47} 48 49// BatchReader is an interface for reading quads in batches. 50// 51// ReadQuads reads at most len(buf) quads into buf. It returns number of quads that were read and an error. 52// It returns an io.EOF if there is no more quads to read. 53type BatchReader interface { 54 ReadQuads(buf []Quad) (int, error) 55} 56 57type Quads struct { 58 s []Quad 59} 60 61func (r *Quads) WriteQuad(q Quad) error { 62 r.s = append(r.s, q) 63 return nil 64} 65 66func (r *Quads) ReadQuad() (Quad, error) { 67 if r == nil || len(r.s) == 0 { 68 return Quad{}, io.EOF 69 } 70 q := r.s[0] 71 r.s = r.s[1:] 72 if len(r.s) == 0 { 73 r.s = nil 74 } 75 return q, nil 76} 77 78// NewReader creates a quad reader from a quad slice. 79func NewReader(quads []Quad) *Quads { 80 return &Quads{s: quads} 81} 82 83// Copy will copy all quads from src to dst. It returns copied quads count and an error, if it failed. 84// 85// Copy will try to cast dst to BatchWriter and will switch to CopyBatch implementation in case of success. 86func Copy(dst Writer, src Reader) (n int, err error) { 87 if bw, ok := dst.(BatchWriter); ok { 88 return CopyBatch(bw, src, 0) 89 } 90 var q Quad 91 for { 92 q, err = src.ReadQuad() 93 if err == io.EOF { 94 err = nil 95 return 96 } else if err != nil { 97 return 98 } 99 if err = dst.WriteQuad(q); err != nil { 100 return 101 } 102 n++ 103 } 104} 105 106type batchReader struct { 107 Reader 108} 109 110func (r batchReader) ReadQuads(quads []Quad) (n int, err error) { 111 for ; n < len(quads); n++ { 112 quads[n], err = r.ReadQuad() 113 if err != nil { 114 break 115 } 116 } 117 return 118} 119 120var DefaultBatch = 10000 121 122// CopyBatch will copy all quads from src to dst in a batches of batchSize. 123// It returns copied quads count and an error, if it failed. 124// 125// If batchSize <= 0 default batch size will be used. 126func CopyBatch(dst BatchWriter, src Reader, batchSize int) (cnt int, err error) { 127 if batchSize <= 0 { 128 batchSize = DefaultBatch 129 } 130 buf := make([]Quad, batchSize) 131 bsrc, ok := src.(BatchReader) 132 if !ok { 133 bsrc = batchReader{src} 134 } 135 var n int 136 for err == nil { 137 n, err = bsrc.ReadQuads(buf) 138 if err != nil && err != io.EOF { 139 return 140 } 141 eof := err == io.EOF 142 n, err = dst.WriteQuads(buf[:n]) 143 cnt += n 144 if eof { 145 break 146 } 147 } 148 return 149} 150 151// ReadAll reads all quads from r until EOF. 152// It returns a slice with all quads that were read and an error, if any. 153func ReadAll(r Reader) (arr []Quad, err error) { 154 switch rt := r.(type) { 155 case *Quads: 156 arr = make([]Quad, len(rt.s)) 157 copy(arr, rt.s) 158 rt.s = nil 159 return 160 } 161 var q Quad 162 for { 163 q, err = r.ReadQuad() 164 if err == io.EOF { 165 return arr, nil 166 } else if err != nil { 167 return nil, err 168 } 169 arr = append(arr, q) 170 } 171} 172