From 7bbf4af7acab69c407c0f1fa8c94ccd2b7a92b0a Mon Sep 17 00:00:00 2001 From: Yunxing Dai Date: Wed, 8 Oct 2014 10:44:22 -0700 Subject: [PATCH] Refactor recordio.record - Provide an interface for record so the client can provide its own implementation. - Add documentation to the exposed symbols in recordio.record - Change Appender and Fetcher to use the new interface --- db/backend.go | 5 +++-- db/recordio/appender.go | 6 +++--- db/recordio/fetcher.go | 13 ++++++------- db/recordio/io_test.go | 9 +++++---- db/recordio/record.go | 23 +++++++++++++++++++++-- db/recordio/record_test.go | 4 ++-- 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/db/backend.go b/db/backend.go index a6c17cc..2a2df2c 100644 --- a/db/backend.go +++ b/db/backend.go @@ -39,7 +39,8 @@ func newBackend() *backend { } func (b *backend) getData(offset int64) []byte { - rec, err := b.fc.Fetch(offset) + rec := &recordio.Record{Data: nil} + err := b.fc.Fetch(offset, rec) if err != nil { panic("unimplemented") } @@ -87,7 +88,7 @@ func (b *backend) Put(rev int, path Path, data []byte) { } b.rev++ - offset, err := b.ap.Append(recordio.Record{data}) + offset, err := b.ap.Append(&recordio.Record{data}) if err != nil { panic("unimplemented") } diff --git a/db/recordio/appender.go b/db/recordio/appender.go index 05bd537..67662a4 100644 --- a/db/recordio/appender.go +++ b/db/recordio/appender.go @@ -3,7 +3,7 @@ package recordio import "io" type Appender interface { - Append(Record) (int64, error) + Append(Encoder) (int64, error) } type appender struct { @@ -15,13 +15,13 @@ func NewAppender(w io.WriteSeeker) Appender { } // Not thread-safe -func (ap *appender) Append(r Record) (offset int64, err error) { +func (ap *appender) Append(r Encoder) (offset int64, err error) { offset, err = ap.w.Seek(0, 2) if err != nil { return -1, err } - err = (&r).encodeTo(ap.w) + err = r.EncodeTo(ap.w) if err != nil { return -1, err } diff --git a/db/recordio/fetcher.go b/db/recordio/fetcher.go index 930dc83..d713caa 100644 --- a/db/recordio/fetcher.go +++ b/db/recordio/fetcher.go @@ -3,7 +3,7 @@ package recordio import "io" type Fetcher interface { - Fetch(offset int64) (Record, error) + Fetch(offset int64, d Decoder) error } type fetcher struct { @@ -14,17 +14,16 @@ func NewFetcher(r io.ReadSeeker) Fetcher { return &fetcher{r} } -func (fc *fetcher) Fetch(offset int64) (Record, error) { +func (fc *fetcher) Fetch(offset int64, d Decoder) error { _, err := fc.r.Seek(offset, 0) if err != nil { - return Record{}, err + return err } - r := Record{} - err = (&r).decodeFrom(fc.r) + err = d.DecodeFrom(fc.r) if err != nil { - return Record{}, err + return err } - return r, nil + return nil } diff --git a/db/recordio/io_test.go b/db/recordio/io_test.go index 9ef9ae9..4105824 100644 --- a/db/recordio/io_test.go +++ b/db/recordio/io_test.go @@ -26,10 +26,10 @@ func TestFetch(t *testing.T) { tests := []struct { offset int64 - record Record + record *Record }{ - {-1, Record{[]byte("someData")}}, - {-1, Record{[]byte("someOtherData")}}, + {-1, &Record{[]byte("someData")}}, + {-1, &Record{[]byte("someOtherData")}}, } for i, tt := range tests { @@ -41,7 +41,8 @@ func TestFetch(t *testing.T) { } for i, tt := range tests { - recRead, err := fc.Fetch(tt.offset) + recRead := &Record{Data: nil} + err := fc.Fetch(tt.offset, recRead) if err != nil { t.Errorf("#%d: Fetch failed: %s", i, err.Error()) } diff --git a/db/recordio/record.go b/db/recordio/record.go index 33ca3fb..8f01947 100644 --- a/db/recordio/record.go +++ b/db/recordio/record.go @@ -9,11 +9,29 @@ const ( sizeOfLength = 4 ) +// Encoder is an interface implemented by an object that can +// encode itself into a binary representation with an io.Writer +type Encoder interface { + EncodeTo(wr io.Writer) error +} + +// Decoder is an interface implemented by an object that can +// decodes itself from a binary representation provided by +// an io.Reader +type Decoder interface { + DecodeFrom(rd io.Reader) error +} + +// Record is a struct that holds some binary data and can be +// encoded into/decoded from the following binary form +// [lenth of record] : 4 bytes +// [content of record] type Record struct { Data []byte } -func (r *Record) encodeTo(wr io.Writer) error { +// EncodeTo encodes a binary data in record object to an io.Writer +func (r *Record) EncodeTo(wr io.Writer) error { // Write length lBuf := make([]byte, sizeOfLength) binary.LittleEndian.PutUint32(lBuf, uint32(len(r.Data))) @@ -28,7 +46,8 @@ func (r *Record) encodeTo(wr io.Writer) error { return nil } -func (r *Record) decodeFrom(rd io.Reader) error { +// DecodeFrom decodes binary data out of io.Reader +func (r *Record) DecodeFrom(rd io.Reader) error { var length uint32 // Read length err := binary.Read(rd, binary.LittleEndian, &length) diff --git a/db/recordio/record_test.go b/db/recordio/record_test.go index c8073d8..de8dda5 100644 --- a/db/recordio/record_test.go +++ b/db/recordio/record_test.go @@ -18,11 +18,11 @@ func TestEncodeDecode(t *testing.T) { buf := new(bytes.Buffer) recordToWrite := &Record{tt.data} - if err := recordToWrite.encodeTo(buf); err != nil { + if err := recordToWrite.EncodeTo(buf); err != nil { t.Fatalf("#%d: cannot encode, err: %s", i, err) } recordToRead := new(Record) - if err := recordToRead.decodeFrom(buf); err != nil { + if err := recordToRead.DecodeFrom(buf); err != nil { t.Fatalf("#%d: cannot decode, err: %s", i, err) } if !reflect.DeepEqual(recordToRead, recordToWrite) {