memio - readwrite.go
1 package memio
2
3 import (
4 "errors"
5 "io"
6 )
7
8 // ReadWriteMem is a combination of both the ReadMem and WriteMem types,
9 // allowing both all reads and writes to the same underlying byte slice.
10 type ReadWriteMem struct {
11 WriteMem
12 }
13
14 // OpenMem uses a byte slice for reading and writing. Implements io.Reader,
15 // io.Writer, io.Seeker, io.ReaderAt, io.ByteReader, io.WriterTo, io.WriterAt,
16 // io.ByteWriter and io.ReaderFrom.
17 func OpenMem(data *[]byte) *ReadWriteMem {
18 return &ReadWriteMem{WriteMem{data, 0}}
19 }
20
21 // Peek reads the next n bytes without advancing the position
22 func (b *ReadWriteMem) Peek(n int) ([]byte, error) {
23 if b.data == nil {
24 return nil, ErrClosed
25 } else if b.pos >= len(*b.data) {
26 return nil, io.EOF
27 } else if b.pos+n > len(*b.data) {
28 return (*b.data)[b.pos:], io.EOF
29 }
30 return (*b.data)[b.pos : b.pos+n], nil
31 }
32
33 // Read is an implementation of the io.Reader interface
34 func (b *ReadWriteMem) Read(p []byte) (int, error) {
35 if b.data == nil {
36 return 0, ErrClosed
37 } else if b.pos >= len(*b.data) {
38 return 0, io.EOF
39 }
40 n := copy(p, (*b.data)[b.pos:])
41 b.pos += n
42 return n, nil
43 }
44
45 // ReadByte is an implementation of the io.ByteReader interface
46 func (b *ReadWriteMem) ReadByte() (byte, error) {
47 if b.data == nil {
48 return 0, ErrClosed
49 } else if b.pos >= len(*b.data) {
50 return 0, io.EOF
51 }
52 c := (*b.data)[b.pos]
53 b.pos++
54 return c, nil
55 }
56
57 // UnreadByte implements the io.ByteScanner interface
58 func (b *ReadWriteMem) UnreadByte() error {
59 if b.data == nil {
60 return ErrClosed
61 }
62 if b.pos > 0 {
63 b.pos--
64 return nil
65 }
66 return ErrInvalidUnreadByte
67 }
68
69 // ReadAt is an implementation of the io.ReaderAt interface
70 func (b *ReadWriteMem) ReadAt(p []byte, off int64) (int, error) {
71 if b.data == nil {
72 return 0, ErrClosed
73 } else if off >= int64(len(*b.data)) {
74 return 0, io.EOF
75 }
76 return copy(p, (*b.data)[off:]), nil
77 }
78
79 // WriteTo is an implementation of the io.WriterTo interface
80 func (b *ReadWriteMem) WriteTo(f io.Writer) (int64, error) {
81 if b.data == nil {
82 return 0, ErrClosed
83 } else if b.pos >= len(*b.data) {
84 return 0, io.EOF
85 }
86 n, err := f.Write((*b.data)[b.pos:])
87 b.pos = len(*b.data)
88 return int64(n), err
89 }
90
91 // Errors
92 var (
93 ErrInvalidUnreadByte = errors.New("invalid UnreadByte, no bytes read")
94 )