92 lines
2.0 KiB
Go
92 lines
2.0 KiB
Go
|
package client
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io"
|
||
|
|
||
|
"github.com/ipfs/go-cid"
|
||
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||
|
"github.com/ipld/go-car/util"
|
||
|
"github.com/multiformats/go-varint"
|
||
|
)
|
||
|
|
||
|
// —————————————————————————————————————————————————————————
|
||
|
//
|
||
|
// This code is temporary, and should be deleted when
|
||
|
// https://github.com/ipld/go-car/issues/196 is resolved.
|
||
|
//
|
||
|
// —————————————————————————————————————————————————————————
|
||
|
|
||
|
func init() {
|
||
|
cbor.RegisterCborType(CarHeader{})
|
||
|
}
|
||
|
|
||
|
type CarHeader struct {
|
||
|
Roots []cid.Cid
|
||
|
Version uint64
|
||
|
}
|
||
|
|
||
|
func readHeader(r io.Reader) (*CarHeader, error) {
|
||
|
hb, err := ldRead(r, false)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
var ch CarHeader
|
||
|
if err := cbor.DecodeInto(hb, &ch); err != nil {
|
||
|
return nil, fmt.Errorf("invalid header: %v", err)
|
||
|
}
|
||
|
|
||
|
return &ch, nil
|
||
|
}
|
||
|
|
||
|
func writeHeader(h *CarHeader, w io.Writer) error {
|
||
|
hb, err := cbor.DumpObject(h)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return util.LdWrite(w, hb)
|
||
|
}
|
||
|
|
||
|
func ldRead(r io.Reader, zeroLenAsEOF bool) ([]byte, error) {
|
||
|
l, err := varint.ReadUvarint(toByteReader(r))
|
||
|
if err != nil {
|
||
|
// If the length of bytes read is non-zero when the error is EOF then signal an unclean EOF.
|
||
|
if l > 0 && err == io.EOF {
|
||
|
return nil, io.ErrUnexpectedEOF
|
||
|
}
|
||
|
return nil, err
|
||
|
} else if l == 0 && zeroLenAsEOF {
|
||
|
return nil, io.EOF
|
||
|
}
|
||
|
|
||
|
buf := make([]byte, l)
|
||
|
if _, err := io.ReadFull(r, buf); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return buf, nil
|
||
|
}
|
||
|
|
||
|
type readerPlusByte struct {
|
||
|
io.Reader
|
||
|
}
|
||
|
|
||
|
func (rb readerPlusByte) ReadByte() (byte, error) {
|
||
|
return readByte(rb)
|
||
|
}
|
||
|
|
||
|
func readByte(r io.Reader) (byte, error) {
|
||
|
var p [1]byte
|
||
|
_, err := io.ReadFull(r, p[:])
|
||
|
return p[0], err
|
||
|
}
|
||
|
|
||
|
func toByteReader(r io.Reader) io.ByteReader {
|
||
|
if br, ok := r.(io.ByteReader); ok {
|
||
|
return br
|
||
|
}
|
||
|
return &readerPlusByte{r}
|
||
|
}
|