reader.mx raw

   1  // Copyright 2009 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  package strings
   6  
   7  import (
   8  	"errors"
   9  	"io"
  10  	"unicode/utf8"
  11  )
  12  
  13  // A Reader implements the [io.Reader], [io.ReaderAt], [io.ByteReader], [io.ByteScanner],
  14  // [io.RuneReader], [io.RuneScanner], [io.Seeker], and [io.WriterTo] interfaces by reading
  15  // from a string.
  16  // The zero value for Reader operates like a Reader of an empty string.
  17  type Reader struct {
  18  	s        []byte
  19  	i        int64 // current reading index
  20  	prevRune int   // index of previous rune; or < 0
  21  }
  22  
  23  // Len returns the number of bytes of the unread portion of the
  24  // string.
  25  func (r *Reader) Len() int {
  26  	if r.i >= int64(len(r.s)) {
  27  		return 0
  28  	}
  29  	return int(int64(len(r.s)) - r.i)
  30  }
  31  
  32  // Size returns the original length of the underlying string.
  33  // Size is the number of bytes available for reading via [Reader.ReadAt].
  34  // The returned value is always the same and is not affected by calls
  35  // to any other method.
  36  func (r *Reader) Size() int64 { return int64(len(r.s)) }
  37  
  38  // Read implements the [io.Reader] interface.
  39  func (r *Reader) Read(b []byte) (n int, err error) {
  40  	if r.i >= int64(len(r.s)) {
  41  		return 0, io.EOF
  42  	}
  43  	r.prevRune = -1
  44  	n = copy(b, r.s[r.i:])
  45  	r.i += int64(n)
  46  	return
  47  }
  48  
  49  // ReadAt implements the [io.ReaderAt] interface.
  50  func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
  51  	// cannot modify state - see io.ReaderAt
  52  	if off < 0 {
  53  		return 0, errors.New("strings.Reader.ReadAt: negative offset")
  54  	}
  55  	if off >= int64(len(r.s)) {
  56  		return 0, io.EOF
  57  	}
  58  	n = copy(b, r.s[off:])
  59  	if n < len(b) {
  60  		err = io.EOF
  61  	}
  62  	return
  63  }
  64  
  65  // ReadByte implements the [io.ByteReader] interface.
  66  func (r *Reader) ReadByte() (byte, error) {
  67  	r.prevRune = -1
  68  	if r.i >= int64(len(r.s)) {
  69  		return 0, io.EOF
  70  	}
  71  	b := r.s[r.i]
  72  	r.i++
  73  	return b, nil
  74  }
  75  
  76  // UnreadByte implements the [io.ByteScanner] interface.
  77  func (r *Reader) UnreadByte() error {
  78  	if r.i <= 0 {
  79  		return errors.New("strings.Reader.UnreadByte: at beginning of string")
  80  	}
  81  	r.prevRune = -1
  82  	r.i--
  83  	return nil
  84  }
  85  
  86  // ReadRune implements the [io.RuneReader] interface.
  87  func (r *Reader) ReadRune() (ch rune, size int, err error) {
  88  	if r.i >= int64(len(r.s)) {
  89  		r.prevRune = -1
  90  		return 0, 0, io.EOF
  91  	}
  92  	r.prevRune = int(r.i)
  93  	if c := r.s[r.i]; c < utf8.RuneSelf {
  94  		r.i++
  95  		return rune(c), 1, nil
  96  	}
  97  	ch, size = utf8.DecodeRuneInString(r.s[r.i:])
  98  	r.i += int64(size)
  99  	return
 100  }
 101  
 102  // UnreadRune implements the [io.RuneScanner] interface.
 103  func (r *Reader) UnreadRune() error {
 104  	if r.i <= 0 {
 105  		return errors.New("strings.Reader.UnreadRune: at beginning of string")
 106  	}
 107  	if r.prevRune < 0 {
 108  		return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
 109  	}
 110  	r.i = int64(r.prevRune)
 111  	r.prevRune = -1
 112  	return nil
 113  }
 114  
 115  // Seek implements the [io.Seeker] interface.
 116  func (r *Reader) Seek(offset int64, whence int) (int64, error) {
 117  	r.prevRune = -1
 118  	var abs int64
 119  	switch whence {
 120  	case io.SeekStart:
 121  		abs = offset
 122  	case io.SeekCurrent:
 123  		abs = r.i + offset
 124  	case io.SeekEnd:
 125  		abs = int64(len(r.s)) + offset
 126  	default:
 127  		return 0, errors.New("strings.Reader.Seek: invalid whence")
 128  	}
 129  	if abs < 0 {
 130  		return 0, errors.New("strings.Reader.Seek: negative position")
 131  	}
 132  	r.i = abs
 133  	return abs, nil
 134  }
 135  
 136  // WriteTo implements the [io.WriterTo] interface.
 137  func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
 138  	r.prevRune = -1
 139  	if r.i >= int64(len(r.s)) {
 140  		return 0, nil
 141  	}
 142  	s := r.s[r.i:]
 143  	m, err := io.WriteString(w, s)
 144  	if m > len(s) {
 145  		panic("strings.Reader.WriteTo: invalid WriteString count")
 146  	}
 147  	r.i += int64(m)
 148  	n = int64(m)
 149  	if m != len(s) && err == nil {
 150  		err = io.ErrShortWrite
 151  	}
 152  	return
 153  }
 154  
 155  // Reset resets the [Reader] to be reading from s.
 156  func (r *Reader) Reset(s []byte) { *r = Reader{s, 0, -1} }
 157  
 158  // NewReader returns a new [Reader] reading from s.
 159  // It is similar to [bytes.NewBufferString] but more efficient and non-writable.
 160  func NewReader(s []byte) *Reader { return &Reader{s, 0, -1} }
 161