package iox import ( `bytes` `context` `io` `sync` ) type ( /* RuneWriter matches the behavior of [bytes.Buffer.WriteRune] and [bufio.Writer.WriteRune]. (Note that this package does not have a "RuneReader"; see [io.RuneReader] instead.) */ RuneWriter interface { WriteRune(r rune) (n int, err error) } // Copier matches the signature/behavior of [io.Copy]. Implemented by [XIO]. Copier interface { Copy(dst io.Writer, src io.Reader) (written int64, err error) } // CopyBufferer matches the signature/behavior of [io.CopyBuffer]. Implemented by [XIO]. CopyBufferer interface { CopyBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err error) } // SizedCopier matches the signature/behavior of [io.CopyN]. Implemented by [XIO]. SizedCopier interface { CopyN(dst io.Writer, src io.Reader, n int64) (written int64, err error) } // SizedCopyBufferer matches the signature/behavior of [CopyBufN]. Implemented by [XIO]. SizedCopyBufferer interface { CopyBufN(dst io.Writer, src io.Reader, n int64) (written int64, err error) } // SizedCopyBufferInvoker matches the signature/behavior of [CopyBufWith]. Implemented by [XIO]. SizedCopyBufferInvoker interface { CopyBufWith(dst io.Writer, src io.Reader, bufFunc func() (b []byte)) (written int64, err error) } // DynamicSizedCopyBufferInvoker matches the signature/behavior of [CopyBufWithDynamic]. Implemented by [XIO]. DynamicSizedCopyBufferInvoker interface { CopyBufWithDynamic(dst io.Writer, src io.Reader, bufFunc func() (b []byte)) (written int64, err error) } /* Chunker is used by both [ContextReader] and [ContextWriter] to set/get the current chunk size. Chunking is inherently required to be specified in order to interrupt reads/writes/copies with a [context.Context]. Implementations *must* use a [sync.RWMutex] to get (RLock) and set (Lock) the chunk size. The chunk size *must not* be directly accessible to maintain concurrency safety assumptions. */ Chunker interface { // GetChunkLen returns the current chunk size/length in bytes. GetChunkLen() (size uint) // SetChunkLen sets the current chunk size/length in bytes. SetChunkLen(size uint) (err error) } /* ChunkReader implements a chunking reader. Third-party implementations *must* respect the chunk size locking (see [Chunker]). The Read method should read in chunks of the internal chunk size. */ ChunkReader interface { io.Reader Chunker } /* ChunkWriter implements a chunking writer. Third-party implementations *must* respect the chunk size locking (see [Chunker]). The Write method should write out in chunks of the internal chunk size. */ ChunkWriter interface { io.Writer Chunker } // ChunkReadWriter implements a chunking reader/writer. ChunkReadWriter interface { ChunkReader ChunkWriter } /* ContextSetter allows one to set an internal context. A nil context should return an error. */ ContextSetter interface { SetContext(context context.Context) (err error) } /* ContextCopier is defined to allow for consumer-provided types. See [CtxIO] for a package-provided type. The Copy method should use an internal context and chunk size (and thus wrap [CopyCtxBufN] internally on an external call to Copy, etc.). */ ContextCopier interface { Copier Chunker ContextSetter SizedCopyBufferer } /* ContextReader is primarily here to allow for consumer-provided types. See [CtxIO] for a package-provided type. The Read method should use an internal context and chunk size. The ReadWithContext method should use an internal chunk size. */ ContextReader interface { ChunkReader ContextSetter ReadWithContext(ctx context.Context, p []byte) (n int64, err error) } /* ContextWriter is primarily here to allow for consumer-provided types. See [CtxIO] for a package-provided type. The Write method should use an internal context. The WriteWithContext should use an internal chunk size. */ ContextWriter interface { ChunkWriter ContextSetter WriteWithContext(ctx context.Context, p []byte) (n int64, err error) WriteNWithContext(ctx context.Context, p []byte, n int64) (written int64, err error) } /* ContextReadWriter is primarily here to allow for consumer-provided types. See [CtxIO] for a package-provided type. */ ContextReadWriter interface { ContextReader ContextWriter } ) type ( // ChunkLocker implements [Chunker]. ChunkLocker struct { lock sync.RWMutex chunkLen uint } /* CtxIO is a type used to demonstrate "stateful" I/O introduced by this package. It implements: * [Copier] * [Chunker] * [RuneWriter] * [ChunkReader] * [ChunkWriter] * [ContextCopier] * [ContextSetter] * [ContextReader] * [ContextWriter] * [ChunkReadWriter] * [ContextReadWriter] * [SizedCopyBufferer] Unlike [XIO], it must be non-nil (see [NewCtxIO]) since it maintains state (though technically, one does not need to call [NewCtxIO] if they call [CtxIO.SetChunkLen] and [CtxIO.SetContext] before any other methods). [CtxIO.Read] and other Read methods writes to an internal buffer, and [CtxIO.Write] and other Write methods writes out from it. */ CtxIO struct { r io.Reader w io.Writer l ChunkLocker buf bytes.Buffer ctx context.Context } /* XIO is a type used to demonstrate "stateless" I/O introduced by this package. It implements: * [Copier] * [CopyBufferer] * [SizedCopier] * [SizedCopyBufferer] * [SizedCopyBufferInvoker] * [DynamicSizedCopyBufferInvoker] Unlike [CtxIO], the zero-value is ready to use since it holds no state or configuration whatsoever. A nil XIO is perfectly usable but if you want something more idiomatic, see [NewXIO]. */ XIO struct{} )