putback

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 1, 2026 License: CC0-1.0 Imports: 6 Imported by: 0

README

putback

A minimal library with wrappers for common I/O interfaces, adding the ability to return read bytes back to the stream for subsequent reading.

Split example:
asciicast

Minimal hello X example:

package main

import (
	"fmt"
	"io"
	"net"

	"github.com/asciimoth/putback"
)

func main() {
	// echo "WORLD" | nc -c 127.0.0.1 3333
	l, err := net.Listen("tcp4", "127.0.0.1:3333")
	if err != nil {
		panic(err)
	}

	for {
		c, err := l.Accept()
		if err != nil {
			panic(err)
		}

		c = putback.WrapConn(c, []byte("hello "), nil)

		b, _ := io.ReadAll(c)

		fmt.Println(string(b))
	}
}

License

Files in this repository are distributed under the CC0 license.

CC0
To the extent possible under law, ASCIIMoth has waived all copyright and related or neighboring rights to putback.

Documentation

Overview

Package putback provides wrapper types around common io and net interfaces that add support for putting bytes or packets back so they can be read again.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WrapConn

func WrapConn(conn net.Conn, bytes []byte, pool BufferPool) net.Conn

WrapConn wraps a net.Conn with a put-back capable connection. Any initial bytes are made available for reading before data from the connection. If the provided connection already supports put-back, its existing buffer is reused as the parent. TCP connections are wrapped with PutBackTCPConn to preserve TCP-specific methods.

Types

type BackBuffer

type BackBuffer struct {
	Bytes   []byte // May be nil
	Pointer int
	Pool    BufferPool // May be nil
}

BackBuffer holds a byte slice that may be read from and to which bytes can be "put back" (prepended) so they will be returned by subsequent reads.

func NewBackBuffer added in v0.2.0

func NewBackBuffer(pool BufferPool, parent WithBackBuffer, bufs ...[]byte) BackBuffer

NewBackBuffer constructs a BackBuffer optionally reusing data from parent and prepending any provided bufs in front of that data. The returned BackBuffer does not take ownership of a non-nil parent; it copies slices as necessary.

func (*BackBuffer) BackBuffer added in v0.2.0

func (b *BackBuffer) BackBuffer() *BackBuffer

BackBuffer returns the receiver to satisfy the WithBackBuffer interface.

func (*BackBuffer) BytesLeft

func (b *BackBuffer) BytesLeft() int

BytesLeft returns the number of unread bytes remaining in the buffer. If the receiver or its backing slice is nil, BytesLeft returns 0. The method defensively clamps Pointer to the valid range.

func (*BackBuffer) PutBack

func (b *BackBuffer) PutBack(bytes []byte)

PutBack prepends the provided bytes so they will be returned by subsequent Read calls. If there is sufficient unused space to the left of the current Pointer the bytes are copied into that space. Otherwise a new backing buffer is allocated (or obtained from Pool) and the existing unread bytes are appended after the new data. If the pool is used the old backing slice is returned to the pool.

func (*BackBuffer) Read

func (b *BackBuffer) Read(p []byte) (n int, err error)

Read reads up to len(p) bytes from the unread portion of the buffer into p and advances the read position. Read never returns an error and is safe to call on a nil receiver. When all data is consumed the backing buffer is released to the Pool if present.

func (*BackBuffer) Wipe

func (b *BackBuffer) Wipe()

Wipe clears the buffer state. If a BufferPool is present, the backing slice is returned to the pool. Wipe is safe to call on a nil receiver.

type BackPacketBuffer

type BackPacketBuffer[T any] struct {
	Packets []Packet[T] // May be nil
	Pool    BufferPool  // May be nil
}

BackPacketBuffer stores a stack of packets that can be pushed back and later read in LIFO order. If a BufferPool is present, packet buffers are returned to the pool when the packet is discarded.

func NewBackPacketBuffer added in v0.2.0

func NewBackPacketBuffer[T any](pool BufferPool, parent WithBackPacketBuffer[T], packets ...Packet[T]) BackPacketBuffer[T]

NewBackPacketBuffer constructs a BackPacketBuffer optionally reusing packets from parent and appending the provided packets. The returned

func (*BackPacketBuffer[T]) BackPacketBuffer added in v0.2.0

func (b *BackPacketBuffer[T]) BackPacketBuffer() *BackPacketBuffer[T]

BackPacketBuffer returns the receiver to satisfy the WithBackPacketBuffer[T] interface.

func (*BackPacketBuffer[T]) PacketsLeft

func (b *BackPacketBuffer[T]) PacketsLeft() int

PacketsLeft returns the number of packets currently stored in the buffer.

func (*BackPacketBuffer[T]) PutBack

func (b *BackPacketBuffer[T]) PutBack(bytes []byte, Assoc T)

PutBack pushes a packet (buffer + associated value) onto the stack. The provided buffer slice is not copied; callers that need ownership should ensure the slice won't be modified after PutBack.

func (*BackPacketBuffer[T]) ReadFrom

func (b *BackPacketBuffer[T]) ReadFrom(p []byte) (n int, assoc T, err error)

ReadFrom pops the most recently PutBack packet and copies its buffer into p (up to len(p)). It returns the number of bytes copied and the associated value. If no packets are available it returns zero values. When a pool is present the packet buffer is returned to the pool. ReadFrom never returns a non-nil error.

func (*BackPacketBuffer[T]) Wipe

func (b *BackPacketBuffer[T]) Wipe()

Wipe clears stored packets and returns their buffers to the pool when available. Wipe is safe to call on a nil receiver.

type BufferPool

type BufferPool interface {
	// Should return byte buffer with exactly provided length and any capacity
	GetBuffer(length int) []byte
	// Putted buffer may have arbitrary length and capacity
	PutBuffer(buf []byte)
}

type Packet

type Packet[T any] struct {
	Buffer []byte
	Assoc  T
}

Packet holds a single buffer and an associated value of type T. It is used by BackPacketBuffer to store packets that can be put back and read later.

type PutBackConn

type PutBackConn struct {
	net.Conn
	Buffer BackBuffer
}

PutBackConn wraps a net.Conn with put-back support for reads.

func (*PutBackConn) Close

func (pb *PutBackConn) Close() error

Close wipes the internal buffer and then closes the underlying Conn.

func (*PutBackConn) PutBack

func (pb *PutBackConn) PutBack(bytes []byte)

PutBack prepends bytes so they will be read before the underlying Conn.

func (*PutBackConn) Read

func (pb *PutBackConn) Read(p []byte) (n int, err error)

Read reads from the internal BackBuffer first and then from the underlying Conn once the buffer is exhausted.

type PutBackPacketConn

type PutBackPacketConn struct {
	net.PacketConn
	Buffer BackPacketBuffer[net.Addr]
}

PutBackPacketConn wraps a net.PacketConn and allows received packets to be put back so they will be returned by subsequent ReadFrom calls.

func (*PutBackPacketConn) Close

func (pb *PutBackPacketConn) Close() error

Close wipes the internal packet buffer and then closes the underlying PacketConn.

func (*PutBackPacketConn) PutBack

func (pb *PutBackPacketConn) PutBack(bytes []byte, addr net.Addr)

PutBack pushes a packet back so it will be returned by the next ReadFrom.

func (*PutBackPacketConn) ReadFrom

func (pb *PutBackPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error)

ReadFrom first attempts to read a packet from the internal buffer. If none are available it delegates to the underlying PacketConn.

type PutBackReadCloser

type PutBackReadCloser struct {
	io.ReadCloser
	Buffer BackBuffer
}

PutBackReadCloser wraps an io.ReadCloser with put-back support. When closed, the internal buffer is wiped before closing the underlying ReadCloser.

func (*PutBackReadCloser) Close

func (pb *PutBackReadCloser) Close() error

Close wipes the internal buffer and then closes the underlying ReadCloser.

func (*PutBackReadCloser) PutBack

func (pb *PutBackReadCloser) PutBack(bytes []byte)

PutBack prepends bytes so they will be read before the underlying Reader.

func (*PutBackReadCloser) Read

func (pb *PutBackReadCloser) Read(p []byte) (n int, err error)

Read reads from the internal BackBuffer first and then from the underlying ReadCloser once the buffer is exhausted.

type PutBackReadWriteCloser

type PutBackReadWriteCloser struct {
	io.ReadWriteCloser
	Buffer BackBuffer
}

PutBackReadWriteCloser wraps an io.ReadWriteCloser with put-back support for reads.

func (*PutBackReadWriteCloser) Close

func (pb *PutBackReadWriteCloser) Close() error

Close wipes the internal buffer and then closes the underlying ReadCloser.

func (*PutBackReadWriteCloser) PutBack

func (pb *PutBackReadWriteCloser) PutBack(bytes []byte)

PutBack prepends bytes so they will be read before the underlying Reader.

func (*PutBackReadWriteCloser) Read

func (pb *PutBackReadWriteCloser) Read(p []byte) (n int, err error)

Read reads from the internal BackBuffer first and then from the underlying Reader once the buffer is exhausted.

type PutBackReadWriter

type PutBackReadWriter struct {
	io.ReadWriter
	Buffer BackBuffer
}

PutBackReadWriter wraps an io.ReadWriter with put-back support for reads.

func (*PutBackReadWriter) PutBack

func (pb *PutBackReadWriter) PutBack(bytes []byte)

PutBack prepends bytes so they will be read before the underlying Reader.

func (*PutBackReadWriter) Read

func (pb *PutBackReadWriter) Read(p []byte) (n int, err error)

Read reads from the internal BackBuffer first and then from the underlying Reader once the buffer is exhausted.

type PutBackReader

type PutBackReader struct {
	io.Reader
	Buffer BackBuffer
}

PutBackReader wraps an io.Reader and allows bytes to be put back so they will be returned by subsequent Read calls.

func (*PutBackReader) PutBack

func (pb *PutBackReader) PutBack(bytes []byte)

PutBack prepends bytes so they will be read before the underlying Reader.

func (*PutBackReader) Read

func (pb *PutBackReader) Read(p []byte) (n int, err error)

Read reads from the internal BackBuffer first and then from the underlying Reader once the buffer is exhausted.

type PutBackTCPConn

type PutBackTCPConn struct {
	TCPConn
	Buffer BackBuffer
}

PutBackTCPConn wraps a net.TCPConn with put-back support for reads.

func (*PutBackTCPConn) Close

func (pb *PutBackTCPConn) Close() error

Close wipes the internal buffer and then closes the underlying Conn.

func (*PutBackTCPConn) CloseRead

func (pb *PutBackTCPConn) CloseRead() error

CloseRead wipes the internal buffer and then half-closes the read side of the underlying TCPConn.

func (*PutBackTCPConn) PutBack

func (pb *PutBackTCPConn) PutBack(bytes []byte)

PutBack prepends bytes so they will be read before the underlying Conn.

func (*PutBackTCPConn) Read

func (pb *PutBackTCPConn) Read(p []byte) (n int, err error)

Read reads from the internal BackBuffer first and then from the underlying TCPConn once the buffer is exhausted.

func (*PutBackTCPConn) WriteTo

func (pb *PutBackTCPConn) WriteTo(w io.Writer) (int64, error)

WriteTo implements io.WriterTo by copying data from the connection to w.

type PutBackUDPConn

type PutBackUDPConn struct {
	UDPConn
	Buffer BackPacketBuffer[*net.UDPAddr]
}

PutBackUDPConn wraps a UDPConn and allows UDP packets to be put back and re-read. It supports the common UDP read variants provided by net.UDPConn.

func (*PutBackUDPConn) Close

func (pb *PutBackUDPConn) Close() error

Close wipes the internal packet buffer and then closes the underlying UDPConn.

func (*PutBackUDPConn) PutBack

func (pb *PutBackUDPConn) PutBack(bytes []byte, addr *net.UDPAddr)

PutBack pushes a packet back so it will be returned by the next reads.

func (*PutBackUDPConn) Read

func (pb *PutBackUDPConn) Read(p []byte) (n int, err error)

Read implements io.Reader by reading a UDP packet and discarding the source address.

func (*PutBackUDPConn) ReadFrom

func (pb *PutBackUDPConn) ReadFrom(p []byte) (n int, addr net.Addr, err error)

ReadFrom implements net.PacketConn by delegating to ReadFromUDP.

func (*PutBackUDPConn) ReadFromUDP

func (pb *PutBackUDPConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)

ReadFromUDP reads a packet from the internal buffer first and falls back to the underlying UDPConn if no buffered packets are available.

func (*PutBackUDPConn) ReadFromUDPAddrPort

func (pb *PutBackUDPConn) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)

ReadFromUDPAddrPort reads a packet returning a netip.AddrPort. Buffered packets are returned first, falling back to the underlying UDPConn.

func (*PutBackUDPConn) ReadMsgUDP

func (pb *PutBackUDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)

ReadMsgUDP is implemented in terms of ReadFromUDP. OOB data is not supported and oobn and flags are always zero.

func (*PutBackUDPConn) ReadMsgUDPAddrPort

func (pb *PutBackUDPConn) ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error)

ReadMsgUDPAddrPort is implemented in terms of ReadFromUDPAddrPort. OOB data is not supported and oobn and flags are always zero.

type TCPConn

type TCPConn interface {
	net.Conn
	ReadFrom(r io.Reader) (int64, error)
	CloseRead() error
	CloseWrite() error
	File() (f *os.File, err error)
	MultipathTCP() (bool, error)
	SetKeepAlive(keepalive bool) error
	SetKeepAliveConfig(config net.KeepAliveConfig) error
	SetKeepAlivePeriod(d time.Duration) error
	SetLinger(sec int) error
	SetNoDelay(noDelay bool) error
	SetReadBuffer(bytes int) error
	SetWriteBuffer(bytes int) error
	SyscallConn() (syscall.RawConn, error)
	WriteTo(w io.Writer) (int64, error)
}

type UDPConn

type UDPConn interface {
	net.PacketConn
	net.Conn
	File() (f *os.File, err error)
	ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
	ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)
	ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
	ReadMsgUDPAddrPort(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error)
	RemoteAddr() net.Addr
	SetWriteBuffer(bytes int) error
	SyscallConn() (syscall.RawConn, error)
	WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
	WriteMsgUDPAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error)
	WriteToUDP(b []byte, addr *net.UDPAddr) (int, error)
	WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error)
}

type WithBackBuffer added in v0.2.0

type WithBackBuffer interface {
	BackBuffer() *BackBuffer
}

type WithBackPacketBuffer added in v0.2.0

type WithBackPacketBuffer[T any] interface {
	BackPacketBuffer() *BackPacketBuffer[T]
}

Directories

Path Synopsis
examples
hello command
split command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL