parent
3af2894a9e
commit
7971b66e60
@ -0,0 +1,65 @@ |
||||
package objectv1 |
||||
|
||||
import ( |
||||
"bytes" |
||||
"encoding/binary" |
||||
"encoding/gob" |
||||
"errors" |
||||
"io" |
||||
"strconv" |
||||
"time" |
||||
) |
||||
|
||||
// Package Version
|
||||
const Version = uint32(1) |
||||
|
||||
// ObjectType is the type of object stored. It is either an Object or Multipart Object.
|
||||
type ObjectType uint8 |
||||
|
||||
const ( |
||||
// Object is a full object
|
||||
Object ObjectType = iota |
||||
// MultipartObject is a collection of Objects uploaded separately that represent a large object.
|
||||
MultipartObject |
||||
) |
||||
|
||||
// Object Metadata
|
||||
type ObjectMetadata struct { |
||||
Bucket string |
||||
Key string |
||||
ErasurePart uint16 |
||||
EncodedPart uint8 |
||||
|
||||
ContentType string |
||||
Created time.Time |
||||
Length uint64 |
||||
Md5 []byte |
||||
ObjectType ObjectType |
||||
} |
||||
|
||||
func Write(target io.Writer, metadata ObjectMetadata, reader io.Reader) error { |
||||
buffer := new(bytes.Buffer) |
||||
binary.Write(buffer, binary.LittleEndian, uint32(Version)) |
||||
encoder := gob.NewEncoder(buffer) |
||||
if err := encoder.Encode(metadata); err != nil { |
||||
return err |
||||
} |
||||
reader = io.MultiReader(buffer, reader) |
||||
_, err := io.Copy(target, reader) |
||||
return err |
||||
} |
||||
|
||||
func ReadMetadata(reader io.Reader) (metadata ObjectMetadata, err error) { |
||||
versionBytes := make([]byte, 4) |
||||
if err := binary.Read(reader, binary.LittleEndian, versionBytes); err != nil { |
||||
return metadata, err |
||||
} |
||||
var version uint32 |
||||
version = binary.LittleEndian.Uint32(versionBytes) |
||||
if version != 1 { |
||||
return metadata, errors.New("Unknown Version: " + strconv.FormatUint(uint64(version), 10)) |
||||
} |
||||
decoder := gob.NewDecoder(reader) |
||||
err = decoder.Decode(&metadata) |
||||
return metadata, err |
||||
} |
@ -0,0 +1,61 @@ |
||||
package objectv1 |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"bytes" |
||||
"crypto/md5" |
||||
"encoding/binary" |
||||
"encoding/gob" |
||||
. "gopkg.in/check.v1" |
||||
"io" |
||||
"time" |
||||
) |
||||
|
||||
func Test(t *testing.T) { TestingT(t) } |
||||
|
||||
type MySuite struct{} |
||||
|
||||
var _ = Suite(&MySuite{}) |
||||
|
||||
func (s *MySuite) TestObjectV1ReadWrite(c *C) { |
||||
var buffer bytes.Buffer |
||||
|
||||
data := "Hello, World" |
||||
|
||||
hash := md5.New() |
||||
hash.Sum([]byte(data)) |
||||
sum := hash.Sum(nil) |
||||
|
||||
objectMetadata := ObjectMetadata{ |
||||
Bucket: "bucket", |
||||
Key: "key", |
||||
ErasurePart: 1, |
||||
EncodedPart: 2, |
||||
|
||||
ObjectType: Object, |
||||
Created: time.Now(), |
||||
ContentType: "application/text", |
||||
Md5: sum, |
||||
Length: uint64(len(sum)), |
||||
} |
||||
|
||||
err := Write(&buffer, objectMetadata, bytes.NewBufferString(data)) |
||||
c.Assert(err, IsNil) |
||||
|
||||
versionBuffer := make([]byte, 4) |
||||
buffer.Read(versionBuffer) |
||||
c.Assert(binary.LittleEndian.Uint32(versionBuffer), Equals, uint32(1)) |
||||
|
||||
actualMetadata := ObjectMetadata{} |
||||
decoder := gob.NewDecoder(&buffer) |
||||
decoder.Decode(&actualMetadata) |
||||
|
||||
c.Assert(actualMetadata, DeepEquals, objectMetadata) |
||||
|
||||
var actualData bytes.Buffer |
||||
|
||||
_, err = io.Copy(&actualData, &buffer) |
||||
c.Assert(err, IsNil) |
||||
c.Assert(actualData.Bytes(), DeepEquals, []byte(data)) |
||||
} |
Loading…
Reference in new issue