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 if len(*s) == 0 {
18 return 0, io.EOF
19 }
20 n := copy(p, *s)
21 *s = (*s)[n:]
22 return n, nil
23 }
24
25 // ReadAt satisfies the io.ReaderAt interface
26 //
27 // Care should be taken when used in conjunction with any other Read* calls as
28 // they will alter the start point of the buffer
29 func (s *LimitedBuffer) ReadAt(p []byte, off int64) (int, error) {
30 n := copy(p, (*s)[off:])
31 if n < len(p) {
32 return n, io.ErrUnexpectedEOF
33 }
34 return n, nil
35 }
36
37 // WriteTo satisfies the io.WriterTo interface
38 func (s *LimitedBuffer) WriteTo(w io.Writer) (int64, error) {
39 if len(*s) == 0 {
40 return 0, io.EOF
41 }
42 n, err := w.Write(*s)
43 *s = (*s)[n:]
44 return int64(n), err
45 }
46
47 // Write satisfies the io.Writer interface
48 func (s *LimitedBuffer) Write(p []byte) (int, error) {
49 var err error
50 if left := cap(*s) - len(*s); len(p) > left {
51 p = p[:left]
52 err = io.ErrShortBuffer
53 }
54 *s = append(*s, p...)
55 return len(p), err
56 }
57
58 // WriteAt satisfies the io.WriterAt interface
59 func (s *LimitedBuffer) WriteAt(p []byte, off int64) (int, error) {
60 if off+int64(len(p)) >= int64(cap(p)) {
61 return 0, io.ErrShortWrite
62 }
63 n := copy((*s)[off:cap(*s)], p)
64 if n < len(p) {
65 return n, io.ErrShortWrite
66 }
67 return n, nil
68 }
69
70 // WriteString writes a string to the buffer without casting to a byte slice
71 func (s *LimitedBuffer) WriteString(str string) (int, error) {
72 var err error
73 if left := cap(*s) - len(*s); len(str) > left {
74 str = str[:left]
75 err = io.ErrShortBuffer
76 }
77 *s = append(*s, str...)
78 return len(str), err
79 }
80
81 // ReadFrom satisfies the io.ReaderFrom interface
82 func (s *LimitedBuffer) ReadFrom(r io.Reader) (int64, error) {
83 var n int64
84 for len(*s) < cap(*s) {
85 m, err := r.Read((*s)[len(*s):cap(*s)])
86 *s = (*s)[:len(*s)+m]
87 n += int64(m)
88 if err != nil {
89 if err == io.EOF {
90 break
91 }
92 return n, err
93 }
94 }
95 return n, nil
96 }
97
98 // ReadByte satisfies the io.ByteReader interface
99 func (s *LimitedBuffer) ReadByte() (byte, error) {
100 if len(*s) == 0 {
101 return 0, io.EOF
102 }
103 b := (*s)[0]
104 *s = (*s)[1:]
105 return b, nil
106 }
107
108 // ReadRune satisfies the io.RuneReader interface
109 func (s *LimitedBuffer) ReadRune() (rune, int, error) {
110 if len(*s) == 0 {
111 return 0, 0, io.EOF
112 }
113 r, n := utf8.DecodeRune(*s)
114 *s = (*s)[n:]
115 return r, n, nil
116 }
117
118 // WriteByte satisfies the io.ByteWriter interface
119 func (s *LimitedBuffer) WriteByte(b byte) error {
120 if len(*s) == cap(*s) {
121 return io.EOF
122 }
123 *s = append(*s, b)
124 return nil
125 }
126
127 // Peek reads the next n bytes without advancing the position
128 func (s *LimitedBuffer) Peek(n int) ([]byte, error) {
129 if *s == nil {
130 return nil, ErrClosed
131 } else if n > len(*s) {
132 return *s, io.EOF
133 }
134 return (*s)[:n], nil
135 }
136
137 // Close satisfies the io.Closer interface
138 func (s *LimitedBuffer) Close() error {
139 *s = nil
140 return nil
141 }
142