79 lines
1.7 KiB
Go
79 lines
1.7 KiB
Go
// Copyright (c) 2024 Tulir Asokan
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package exbytes
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// Writer is a simple byte writer that does not allow extending the buffer.
|
|
//
|
|
// Writes always go after the current len() and will fail if the slice capacity is too low.
|
|
//
|
|
// The correct way to use this is to create a slice with sufficient capacity and zero length:
|
|
//
|
|
// x := make([]byte, 0, 11)
|
|
// w := (*Writer)(&x)
|
|
// w.Write([]byte("hello"))
|
|
// w.WriteByte(' ')
|
|
// w.WriteString("world")
|
|
// fmt.Println(string(x)) // "hello world"
|
|
type Writer []byte
|
|
|
|
var ErrWriterBufferFull = errors.New("exbytes.Writer: buffer full")
|
|
|
|
var (
|
|
_ io.Writer = (*Writer)(nil)
|
|
_ io.StringWriter = (*Writer)(nil)
|
|
_ io.ByteWriter = (*Writer)(nil)
|
|
)
|
|
|
|
func (w *Writer) extendLen(n int) (int, error) {
|
|
ptr := len(*w)
|
|
if ptr+n > cap(*w) {
|
|
return 0, fmt.Errorf("%w (%d + %d > %d)", ErrWriterBufferFull, ptr, n, cap(*w))
|
|
}
|
|
*w = (*w)[:ptr+n]
|
|
return ptr, nil
|
|
}
|
|
|
|
func (w *Writer) Write(b []byte) (n int, err error) {
|
|
ptr, err := w.extendLen(len(b))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
copy((*w)[ptr:], b)
|
|
return len(b), nil
|
|
}
|
|
|
|
func (w *Writer) WriteString(s string) (n int, err error) {
|
|
ptr, err := w.extendLen(len(s))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
copy((*w)[ptr:], s)
|
|
return len(s), nil
|
|
}
|
|
|
|
func (w *Writer) WriteByte(r byte) error {
|
|
ptr, err := w.extendLen(1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
(*w)[ptr] = r
|
|
return nil
|
|
}
|
|
|
|
func (w *Writer) String() string {
|
|
if w == nil {
|
|
return "<nil>"
|
|
}
|
|
return string(*w)
|
|
}
|