blob: b9b55ec0eaf0beff322878f92dc8905aed95f3a9 [file] [log] [blame]
giolekva892a4e22020-04-27 16:46:22 +04001package chunk
2
3import (
4 "bytes"
5 "errors"
6 "io"
7
8 "github.com/giolekva/pcloud/pfs/api"
9)
10
11type InMemoryChunk struct {
12 status api.ChunkStatus
13 payload []byte
14 committed int
15}
16
17func (c *InMemoryChunk) Stats() (ChunkInfo, error) {
18 return ChunkInfo{c.status, len(c.payload), c.committed}, nil
19}
20
21func (c *InMemoryChunk) ReaderAt() io.ReaderAt {
22 return bytes.NewReader(c.payload[:c.committed])
23}
24
25func (c *InMemoryChunk) WriterAt() io.WriterAt {
26 return &byteWriter{c}
27}
28
29type byteWriter struct {
30 c *InMemoryChunk
31}
32
33func (w *byteWriter) WriteAt(p []byte, offset int64) (n int, err error) {
34 if int(offset) > w.c.committed {
35 panic(1)
36 return 0, errors.New("Gaps are not allowed when writing in chunks")
37 }
38 if int(offset) < w.c.committed {
39 if int(offset)+len(p) <= w.c.committed {
40 if bytes.Compare(w.c.payload[int(offset):int(offset)+len(p)], p) != 0 {
41 panic(2)
42 return 0, errors.New("Can not change contents of allready committed chunk bytes")
43 }
44 panic(3)
45 return len(p), nil
46 }
47 n = w.c.committed - int(offset)
48 p = p[n:]
49 offset = int64(w.c.committed)
50 }
51 if w.c.committed+len(p) > len(w.c.payload) {
52 panic(4)
53 return 0, errors.New("In memory chunk does not have enough space available")
54 }
55 n += copy(w.c.payload[w.c.committed:], p)
56 w.c.committed += n
57 return
58}
59
60type InMemoryChunkFactory struct {
61}
62
63func (f InMemoryChunkFactory) New(size int) Chunk {
64 return &InMemoryChunk{
65 status: api.ChunkStatus_CREATED,
66 payload: make([]byte, size),
67 committed: 0}
68}