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
|
// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package sif
import (
"errors"
"io"
)
// A Buffer is a variable-sized buffer of bytes that implements the sif.ReadWriter interface. The
// zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
buf []byte
pos int64
}
// NewBuffer creates and initializes a new Buffer using buf as its initial contents.
func NewBuffer(buf []byte) *Buffer {
return &Buffer{buf: buf}
}
var errNegativeOffset = errors.New("negative offset")
// ReadAt implements the io.ReaderAt interface.
func (b *Buffer) ReadAt(p []byte, off int64) (int, error) {
if off < 0 {
return 0, errNegativeOffset
}
if off >= int64(len(b.buf)) {
return 0, io.EOF
}
n := copy(p, b.buf[off:])
if n < len(p) {
return n, io.EOF
}
return n, nil
}
var errNegativePosition = errors.New("negative position")
// Write implements the io.Writer interface.
func (b *Buffer) Write(p []byte) (int, error) {
if b.pos < 0 {
return 0, errNegativePosition
}
if have, need := int64(len(b.buf))-b.pos, int64(len(p)); have < need {
b.buf = append(b.buf, make([]byte, need-have)...)
}
n := copy(b.buf[b.pos:], p)
b.pos += int64(n)
return n, nil
}
var errInvalidWhence = errors.New("invalid whence")
// Seek implements the io.Seeker interface.
func (b *Buffer) Seek(offset int64, whence int) (int64, error) {
var abs int64
switch whence {
case io.SeekStart:
abs = offset
case io.SeekCurrent:
abs = b.pos + offset
case io.SeekEnd:
abs = int64(len(b.buf)) + offset
default:
return 0, errInvalidWhence
}
if abs < 0 {
return 0, errNegativePosition
}
b.pos = abs
return abs, nil
}
var errTruncateRange = errors.New("truncation out of range")
// Truncate discards all but the first n bytes from the buffer.
func (b *Buffer) Truncate(n int64) error {
if n < 0 || n > int64(len(b.buf)) {
return errTruncateRange
}
b.buf = b.buf[:n]
return nil
}
// Bytes returns the contents of the buffer. The slice is valid for use only until the next buffer
// modification (that is, only until the next call to a method like ReadAt, Write, or Truncate).
func (b *Buffer) Bytes() []byte { return b.buf }
// Len returns the number of bytes in the buffer.
func (b *Buffer) Len() int64 { return int64(len(b.buf)) }
|