memio - limitedbuffer.go
1 package memio
2
3 import (
4 "io"
5 "unicode/utf8"
6 )
7
8 // LimitedBuffer grants a byte slice very straightforward IO methods, limiting
9 // writing to the capacity of the slice.
10 type LimitedBuffer []byte
11
12 // Read satisfies the io.Reader interface.
13 func (s *LimitedBuffer) Read(p []byte) (int, error) {
14 if len(p) == 0 {
15 return 0, nil
16 }
17
18 if len(*s) == 0 {
19 return 0, io.EOF
20 }
21
22 n := copy(p, *s)
23 *s = (*s)[n:]
24
25 return n, nil
26 }
27
28 // ReadAt satisfies the io.ReaderAt interface.
29 //
30 // Care should be taken when used in conjunction with any other Read* calls as
31 // they will alter the start point of the buffer.
32 func (s *LimitedBuffer) ReadAt(p []byte, off int64) (int, error) {
33 n := copy(p, (*s)[off:])
34 if n < len(p) {
35 return n, io.ErrUnexpectedEOF
36 }
37
38 return n, nil
39 }
40
41 // WriteTo satisfies the io.WriterTo interface.
42 func (s *LimitedBuffer) WriteTo(w io.Writer) (int64, error) {
43 if len(*s) == 0 {
44 return 0, io.EOF
45 }
46
47 n, err := w.Write(*s)
48 *s = (*s)[n:]
49
50 return int64(n), err
51 }
52
53 // Write satisfies the io.Writer interface.
54 func (s *LimitedBuffer) Write(p []byte) (int, error) {
55 var err error
56
57 if left := cap(*s) - len(*s); len(p) > left {
58 p = p[:left]
59 err = io.ErrShortWrite
60 }
61
62 *s = append(*s, p...)
63
64 return len(p), err
65 }
66
67 // WriteAt satisfies the io.WriterAt interface.
68 func (s *LimitedBuffer) WriteAt(p []byte, off int64) (int, error) {
69 if off+int64(len(p)) >= int64(cap(p)) {
70 return 0, io.ErrShortWrite
71 }
72
73 n := copy((*s)[off:cap(*s)], p)
74 if n < len(p) {
75 return n, io.ErrShortWrite
76 }
77
78 return n, nil
79 }
80
81 // WriteString writes a string to the buffer without casting to a byte slice.
82 func (s *LimitedBuffer) WriteString(str string) (int, error) {
83 var err error
84
85 if left := cap(*s) - len(*s); len(str) > left {
86 str = str[:left]
87 err = io.ErrShortBuffer
88 }
89
90 *s = append(*s, str...)
91
92 return len(str), err
93 }
94
95 // ReadFrom satisfies the io.ReaderFrom interface.
96 func (s *LimitedBuffer) ReadFrom(r io.Reader) (int64, error) {
97 var n int64
98
99 for len(*s) < cap(*s) {
100 m, err := r.Read((*s)[len(*s):cap(*s)])
101 *s = (*s)[:len(*s)+m]
102 n += int64(m)
103
104 if err != nil {
105 if err == io.EOF {
106 break
107 }
108
109 return n, err
110 }
111 }
112
113 return n, nil
114 }
115
116 // ReadByte satisfies the io.ByteReader interface.
117 func (s *LimitedBuffer) ReadByte() (byte, error) {
118 if len(*s) == 0 {
119 return 0, io.EOF
120 }
121
122 b := (*s)[0]
123 *s = (*s)[1:]
124
125 return b, nil
126 }
127
128 // ReadRune satisfies the io.RuneReader interface.
129 func (s *LimitedBuffer) ReadRune() (rune, int, error) {
130 if len(*s) == 0 {
131 return 0, 0, io.EOF
132 }
133
134 r, n := utf8.DecodeRune(*s)
135 *s = (*s)[n:]
136
137 return r, n, nil
138 }
139
140 // WriteByte satisfies the io.ByteWriter interface.
141 func (s *LimitedBuffer) WriteByte(b byte) error {
142 if len(*s) == cap(*s) {
143 return io.EOF
144 }
145
146 *s = append(*s, b)
147
148 return nil
149 }
150
151 // Peek reads the next n bytes without advancing the position.
152 func (s *LimitedBuffer) Peek(n int) ([]byte, error) {
153 if *s == nil {
154 return nil, ErrClosed
155 } else if n > len(*s) {
156 return *s, io.EOF
157 }
158
159 return (*s)[:n], nil
160 }
161
162 // Close satisfies the io.Closer interface.
163 func (s *LimitedBuffer) Close() error {
164 *s = nil
165
166 return nil
167 }
168