Live video on the AT Protocol
1package aqio
2
3import (
4 "errors"
5 "io"
6
7 "github.com/johncgriffin/overflow"
8)
9
10// ReadWriteSeeker is an in-memory io.ReadWriteSeeker implementation
11type ReadWriteSeeker struct {
12 buf []byte
13 pos int
14}
15
16// Write implements the io.Writer interface
17func (rws *ReadWriteSeeker) Write(p []byte) (n int, err error) {
18 minCap := overflow.Addp(rws.pos, len(p))
19 if minCap > cap(rws.buf) { // Make sure buf has enough capacity:
20 buf2 := make([]byte, len(rws.buf), overflow.Addp(minCap, len(p))) // add some extra
21 copy(buf2, rws.buf)
22 rws.buf = buf2
23 }
24 if minCap > len(rws.buf) {
25 rws.buf = rws.buf[:minCap]
26 }
27 copy(rws.buf[rws.pos:], p)
28 rws.pos += len(p)
29 return len(p), nil
30}
31
32// Seek implements the io.Seeker interface
33func (rws *ReadWriteSeeker) Seek(offset int64, whence int) (int64, error) {
34 newPos, offs := 0, int(offset)
35 switch whence {
36 case io.SeekStart:
37 newPos = offs
38 case io.SeekCurrent:
39 newPos = rws.pos + offs
40 case io.SeekEnd:
41 newPos = len(rws.buf) + offs
42 }
43 if newPos < 0 {
44 return 0, errors.New("negative result pos")
45 }
46 rws.pos = newPos
47 return int64(newPos), nil
48}
49
50// Close is a no-op that implements the io.Closer interface
51func (rws *ReadWriteSeeker) Close() error {
52 return nil
53}
54
55// Read implements the io.Reader interface
56func (rws *ReadWriteSeeker) Read(b []byte) (n int, err error) {
57 if rws.pos >= len(rws.buf) {
58 return 0, io.EOF
59 }
60 n = copy(b, rws.buf[rws.pos:])
61 rws.pos += n
62 return
63}
64
65// Returns a ReadSeeker based on the current value of the buffer.
66// Don't write to it afterwards!
67func (rws *ReadWriteSeeker) ReadSeeker() io.ReadSeeker {
68 // can't fail, we're seeking to 0
69 _, _ = rws.Seek(0, io.SeekStart)
70 return rws
71}
72
73// Returns the current value of the buffer.
74// Don't write to it afterwards!
75func (rws *ReadWriteSeeker) Bytes() ([]byte, error) {
76 _, _ = rws.Seek(0, io.SeekStart)
77 bs, err := io.ReadAll(rws)
78 if err != nil {
79 return nil, err
80 }
81 return bs, nil
82}