-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinram.go
158 lines (137 loc) · 3.65 KB
/
inram.go
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// v0.2.2
// Author: wunderbarb
// © Sony Pictures Entertainment, Nov 2024
package test
import (
"bytes"
"errors"
"sync"
)
var (
// ErrClosed occurs when attempting to access a closed InRAMReader or InRAMWriter.
ErrClosed = errors.New("reader or writer is closed")
)
// InRAMReader implements everything for io.Reader, io.Closer, and io.Seeker with an initial value but
// within RAM memory.
type InRAMReader struct {
bytes.Reader
closed bool
}
// InRAMWriter implements an io.Writer, io.WriterAt, and io.Closer within RAM memory.
type InRAMWriter struct {
writeAtBuffer
closed bool
currentPos int64
}
// NewInRAMReader creates a new InRAMReader with the buffer `p`.
func NewInRAMReader(p []byte) *InRAMReader {
return &InRAMReader{
Reader: *bytes.NewReader(p),
closed: false,
}
}
// NewInRAMReaderAsString creates a new InRAMReader with the string `s`.
func NewInRAMReaderAsString(s string) *InRAMReader {
return NewInRAMReader([]byte(s))
}
// Close implements the io.Closer interface.
func (irr *InRAMReader) Close() error {
if irr.closed {
return ErrClosed
}
irr.closed = true
return nil
}
// Read implements the io.Reader interface.
func (irr *InRAMReader) Read(p []byte) (int, error) {
if irr.closed {
return 0, ErrClosed
}
return irr.Reader.Read(p)
}
// Seek implements the io.Seeker interface.
func (irr *InRAMReader) Seek(offset int64, whence int) (int64, error) {
if irr.closed {
return 0, ErrClosed
}
return irr.Reader.Seek(offset, whence)
}
// NewInRAMWriter creates a new InRAMWriter.
func NewInRAMWriter() *InRAMWriter {
buf := make([]byte, 10)
return &InRAMWriter{
writeAtBuffer: *newWriteAtBuffer(buf),
closed: false,
currentPos: 0,
}
}
// Close implements the io.Closer interface.
func (irw *InRAMWriter) Close() error {
if irw.closed {
return ErrClosed
}
irw.closed = true
return nil
}
func (irw *InRAMWriter) String() string {
return string(irw.Bytes())
}
// Write implements the io.Writer interface.
func (irw *InRAMWriter) Write(p []byte) (int, error) {
if irw.closed {
return 0, ErrClosed
}
n, err := irw.WriteAt(p, irw.currentPos)
irw.currentPos += int64(n)
return n, err
}
// WriteAt implements the io.WriteAt interface.
func (irw *InRAMWriter) WriteAt(p []byte, pos int64) (int, error) {
if irw.closed {
return 0, ErrClosed
}
return irw.WriteAt(p, pos)
}
// A writeAtBuffer provides an in memory buffer supporting the io.WriterAt interface
type writeAtBuffer struct {
buf []byte
m sync.Mutex
// GrowthCoeff defines the growth rate of the internal buffer. By
// default, the growth rate is 1, where expanding the internal
// buffer will allocate only enough capacity to fit the new expected
// length.
GrowthCoeff float64
}
// newWriteAtBuffer creates a writeAtBuffer with an internal buffer
// provided by buf.
func newWriteAtBuffer(buf []byte) *writeAtBuffer {
return &writeAtBuffer{buf: buf}
}
// WriteAt writes a slice of bytes to a buffer starting at the position provided
// The number of bytes written will be returned, or error. Can overwrite previous
// written slices if the write ats overlap.
func (b *writeAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) {
pLen := len(p)
expLen := pos + int64(pLen)
b.m.Lock()
defer b.m.Unlock()
if int64(len(b.buf)) < expLen {
if int64(cap(b.buf)) < expLen {
if b.GrowthCoeff < 1 {
b.GrowthCoeff = 1
}
newBuf := make([]byte, expLen, int64(b.GrowthCoeff*float64(expLen)))
copy(newBuf, b.buf)
b.buf = newBuf
}
b.buf = b.buf[:expLen]
}
copy(b.buf[pos:], p)
return pLen, nil
}
// Bytes returns a slice of bytes written to the buffer.
func (b *writeAtBuffer) Bytes() []byte {
b.m.Lock()
defer b.m.Unlock()
return b.buf
}