aboutsummaryrefslogtreecommitdiff
path: root/object/store/memory/writer.go
blob: 185b082bdf41aef3c5514c2ecb75cccbdf427e74 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package memory

import (
	"fmt"
	"io"

	"lindenii.org/go/furgit/object/header"
	"lindenii.org/go/furgit/object/id"
	"lindenii.org/go/furgit/object/store"
	"lindenii.org/go/furgit/object/typ"
	"lindenii.org/go/lgo/intconv"
)

// WriteBytesContent writes one typed object content byte slice.
func (memory *Memory) WriteBytesContent(ty typ.Type, content []byte) (id.ObjectID, error) {
	raw := header.Append(nil, ty, uint64(len(content)))
	raw = append(raw, content...)

	objectID := memory.objectFormat.Sum(raw)
	memory.objects.Store(objectID, storedObject{ty: ty, content: append([]byte(nil), content...)})

	return objectID, nil
}

// WriteBytesFull writes one full serialized object byte slice as "type size\x00content".
func (memory *Memory) WriteBytesFull(raw []byte) (id.ObjectID, error) {
	ty, size, consumed, err := header.Parse(raw)
	if err != nil {
		return id.ObjectID{}, fmt.Errorf("object/store/memory: %w", err)
	}

	content := raw[consumed:]
	if uint64(len(content)) != size {
		return id.ObjectID{}, fmt.Errorf("%w: header size/content mismatch", store.ErrInvalidObject)
	}

	return memory.WriteBytesContent(ty, content)
}

// WriteReaderContent writes one typed object content stream.
func (memory *Memory) WriteReaderContent(ty typ.Type, size uint64, src io.Reader) (id.ObjectID, error) {
	limit, err := intconv.Uint64ToInt64(size)
	if err != nil {
		return id.ObjectID{}, fmt.Errorf("object/store/memory: content size: %w", err)
	}

	content, err := io.ReadAll(io.LimitReader(src, limit+1))
	if err != nil {
		return id.ObjectID{}, fmt.Errorf("object/store/memory: read content: %w", err)
	}

	switch {
	case uint64(len(content)) > size:
		return id.ObjectID{}, fmt.Errorf("%w: content longer than declared size", store.ErrInvalidObject)
	case uint64(len(content)) < size:
		return id.ObjectID{}, fmt.Errorf("%w: content shorter than declared size", store.ErrInvalidObject)
	}

	return memory.WriteBytesContent(ty, content)
}

// WriteReaderFull writes one full serialized object stream as "type size\x00content".
func (memory *Memory) WriteReaderFull(src io.Reader) (id.ObjectID, error) {
	raw, err := io.ReadAll(src)
	if err != nil {
		return id.ObjectID{}, fmt.Errorf("object/store/memory: read object: %w", err)
	}

	return memory.WriteBytesFull(raw)
}