iox

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2024 License: MIT Imports: 5 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewReaderFromBytes

func NewReaderFromBytes[T any](r io.Reader) func(f decoderFn) Reader[T]

NewReaderFromBytes creates a new T reader from an io.Reader and Decoder. It simply reads bytes from 'r', decodes them, and passes them along to the caller. As such, the decoder must match the encoder used to create the bytes. If 'r' is nil, an empty Reader is returned; if 'f' is nil, the decoder is set to gob.NewDecoder. Example:

// Used as io.Reader
b := bytes.NewBuffer(nil)

// Using json encoder, so the decoder has to be json in NewReaderFromBytes
json.NewEncoder(b).Encode("test1")
json.NewEncoder(b).Encode("test2")

r := NewReaderFromBytes[string](b)(
	func(r io.Reader) Decoder {
		return json.NewDecoder(r)
	},
)

t.Log(r.Read(context.Background())) // "test1" <nil>
t.Log(r.Read(context.Background())) // "test2" <nil>
t.Log(r.Read(context.Background())) // "", io.EOF

func NewReaderWithFilterFn

func NewReaderWithFilterFn[T any](r Reader[T]) func(f func(v T) bool) Reader[T]

NewReaderWithFilterFn returns a reader where filter 'f' is applied on values coming from reader 'r', removing/skipping values when f(v) == false.

func NewReaderWithMapperFn

func NewReaderWithMapperFn[T, U any](r Reader[T]) func(f func(T) U) Reader[U]

NewReaderWithMapperFn returns a reader where mapper 'f' is applied on values coming from reader 'r'.

func NewWriterFromBytes

func NewWriterFromBytes[T any](w Writer[T]) func(f decoderFn) io.Writer

NewWriterFromBytes returns an io.Writer which accepts bytes, decodes them using the given decoder, and then writes them to 'w'. If 'w' is nil, an emtpy io.Writer is returned; if 'f' is nil, the decoder is set to gob.NewDecoder. Example:

// Writes simply logs values.
vw := WriterImpl[int]{
	Impl: func(ctx context.Context, v int) error {
		t.Log(v)
		return nil
	},
}

// io.Writer
bw := NewWriterFromBytes(vw)(
	func(r io.Reader) Decoder {
		return json.NewDecoder(r)
	},
)

// Logs "9"
json.NewEncoder(bw).Encode(9)

func NewWriterFromValues

func NewWriterFromValues[T any](w io.Writer) func(f encoderFn) Writer[T]

NewWriterFromValues returns a Writer which accepts values, encodes them using the given encoder, and then writes them to 'w'. If 'w' is nil, an empty Writer is returned; if 'f' is nil, the encoder is set to gob.NewEncoder. Example:

// Defining our io.Writer to rcv the data + encoding method.
b := bytes.NewBuffer(nil)
f := func(w io.Writer) Encoder { return json.NewEncoder(w) }
w := NewWriterFromValues[int](b)(f)

// Write values, they are encoded and passed to 'b'. Err handling ignored.
w.Write(nil, 2)
w.Write(nil, 3)

// We'll use these to read what's in 'b'.
dec := json.NewDecoder(b)
val := 0

t.Log(dec.Decode(&val), val) // <nil> 2
t.Log(dec.Decode(&val), val) // <nil> 3
t.Log(dec.Decode(&val), val) // EOF 3

func NewWriterWithFilterFn

func NewWriterWithFilterFn[T any](w Writer[T]) func(f func(T) bool) Writer[T]

NewWriterWithFilterFn returns a writer which writes to 'w' if incoming values are not filtered out with 'f'. If 'w' is nil, an empty WriterImpl[T]{} is returned; if 'f' is nil, 'w' is returned. Example:

// Writes which logs values through 't.Log'.
logWriter := WriterImpl[int]{}
logWriter.Impl = func(_ context.Context, v int) error { t.Log(v); return nil }

// Writer with filter which filters out anything below 2.
w := NewWriterWithFilterFn(logWriter)(func(v int) bool { return v >= 2 })
w.Write(nil, 1) // logWriter logs: <nothing>
w.Write(nil, 2) // logWriter logs: 2
w.Write(nil, 3) // logWriter logs: 3

func NewWriterWithMapperFn

func NewWriterWithMapperFn[T, U any](w Writer[U]) func(f func(T) U) Writer[T]

NewWriterWithMapperFn returns a writer which passes values to 'f', of which the returned values are forwarded to 'w'. If either 'w' or 'f' is nil, an empty WriterImpl[T]{} is returned. Example:

// Writes which logs values through 't.Log'.
logWriter := WriterImpl[int]{}
logWriter.Impl = func(_ context.Context, v int) error { t.Log(v); return nil }

// Writer with adds +1 to each element.
w := NewWriterWithMapperFn[int](logWriter)(func(v int) int { return v + 1 })
w.Write(nil, 1) // logWriter logs: 2
w.Write(nil, 2) // logWriter logs: 3
w.Write(nil, 3) // logWriter logs: 4

func ReaderIntoBytes

func ReaderIntoBytes[T any](r Reader[T]) func(f encoderFn) io.Reader

ReaderIntoBytes creates an io.Reader from a Reader and Encoder. It simply reads values from 'r', encodes them, and passes them along to the caller. As such, when decoding values from the returned io.Reader one should use a decoder which matches the encoder passed here. If 'r' is nil, an empty (not nil) io.Reader is returned; if 'f' is nil, the encoder is set to gob.NewEncoder. Example:

vr := NewReaderFrom("test1", "test2")
br := ReaderIntoBytes(vr)(func(w io.Writer) Encoder { return json.NewEncoder(w) })

// Instantly pass it to a decoder just so we may log out the values.
dec := json.NewDecoder(br)
val := ""

t.Log(dec.Decode(&val), val) // <nil>, "test1"
t.Log(dec.Decode(&val), val) // <nil>, "test2"
t.Log(dec.Decode(&val), val) // EOF, ""

func ReaderIntoChan

func ReaderIntoChan[T any](r Reader[T]) <-chan ErrWrapped[T]

ReaderIntoChan returns a chan which is fed the contents of 'r' from a new goroutine. The error in the ErrWrapped[T] will not contain io.EOF. Example:

r := NewReaderFrom(1, 2, 3)
for ew := range ReaderIntoChan(r) {
	// Prints {<nil> 1} on 1st iteration.
	// Prints {<nil> 2} on 2nd iteration.
	// Prints {<nil> 3} on 3rd iteration.
	t.Log(ew)
}

func ReaderIntoGenerator

func ReaderIntoGenerator[T any](r Reader[T]) func() (val ErrWrapped[T], cont bool)

ReaderIntoGenerator returns a generator which reads from 'r'. The generator will stop on the first error and the ErrWrapped[T] will not contain io.EOF. Example:

r := NewReaderFrom(1, 2, 3)
g := ReaderIntoGenerator(r)

for ev, ok := g(); ok; ev, ok = g() {
	// Prints {<nil> 1} on 1st iteration.
	// Prints {<nil> 2} on 2nd iteration.
	// Prints {<nil> 3} on 3rd iteration.
	t.Log(ev)
}

func ReaderIntoMapKFn

func ReaderIntoMapKFn[K comparable, V any](r Reader[K]) func(f func(K) V) (map[K]V, error)

IntoMapKFn returns a func which creates a map[K]V using the given reader 'r'. It does so by reading all elements of 'r' and storing them as keys. Vals are defined with the given func 'f'. The error, if any, will not be io.EOF Example:

r := NewReaderFrom(1, 2, 3)
m, err := ReaderIntoMapKFn[int, int](r)(
	func(key int) (val int) {
		val = key + 1
		return
	},
)

t.Log(m, err)	// map[1:2 2:3 3:4] <nil>

func ReaderIntoMapVFn

func ReaderIntoMapVFn[K comparable, V any](r Reader[V]) func(f func(V) K) (map[K]V, error)

IntoMapVFn returns a func which creates a map[K]V using the given reader 'r'. It does so by reading all elements of 'r' and storing them as values for keys that are defined using the given func 'f'. Example:

r := NewReaderFrom(1, 2, 3)
m, err := ReaderIntoMapVFn[int, int](r)(
	func(key int) (val int) {
		val = key - 1
		return
	},
)

t.Log(m, err) // map[0:1, 1:2, 2:3] <nil>

func ReaderIntoSlice

func ReaderIntoSlice[T any](r Reader[T]) (s []T, err error)

ReaderIntoSlice reads all values from 'r' and returns them in a slice. Note that the error, if any, will not be io.EOF.

Types

type Decoder

type Decoder interface {
	Decode(e any) error
}

Decoder decodes values from binary form. It is used for converting io.Reader and io.Writer into Reader and Writer (of this pkg), see funcs for docs. Decoder uses pre-generics semantics for interoperability with pre-generics packages. Some commonly used encoders are:

  • gob.NewDecoder(bytes.NewBuffer(nil))
  • json.NewDecoder(bytes.NewBuffer(nil))

type DecoderImpl

type DecoderImpl struct {
	Impl func(d any) error
}

DecoderImpl implements Decoder with it's Decode method by deferring to 'Impl'. This is for convenience, as you may use functional implementation of Decoder without defining a new type (that's done for you here).

func (DecoderImpl) Decode

func (impl DecoderImpl) Decode(d any) error

Decode implements Decoder by deferring to the internal "Impl" func. If the internal "Impl" is not set, an io.EOF will be returned.

type Encoder

type Encoder interface {
	Encode(e any) error
}

Encoder encodes values into binary form. It is used for converting io.Reader and io.Writer into Reader and Writer (of this pkg), see funcs for docs. Encoder uses pre-generics semantics for interoperability with pre-generics packages. Some commonly used encoders are:

  • gob.NewEncoder(bytes.NewBuffer(nil))
  • json.NewEncoder(bytes.NewBuffer(nil))

type EncoderImpl

type EncoderImpl struct {
	Impl func(e any) error
}

EncoderImpl implements Encoder with it's Encode method by deferring to 'Impl'. This is for convenience, as you may use functional implementation of Encoder without defining a new type (that's done for you here).

func (EncoderImpl) Encode

func (impl EncoderImpl) Encode(e any) error

Encode implements Encoder by deferring to the internal "Impl" func. If the internal "Impl" is not set, an io.ErrClosedPipe will be returned.

type ErrWrapped

type ErrWrapped[T any] struct {
	Err error
	Val T
}

type ReadCloser

type ReadCloser[T any] interface {
	io.Closer
	Reader[T]
}

ReadCloser groups Reader with io.Closer.

type ReadCloserImpl

type ReadCloserImpl[T any] struct {
	ImplC func() error
	ImplR func(context.Context) (T, error)
}

ReadCloserImpl implements Reader and io.Closer with it's methods by deferring to ImplC (closer) and ImplR (reader). This is for convenience, as you may use a functional implementation of the interfaces wihout defining a new type.

func (ReadCloserImpl[T]) Close

func (impl ReadCloserImpl[T]) Close() (err error)

Read implements Closer by deferring to the internal "ImplC" func. If the internal "ImplC" func is nil, nothing will happen.

func (ReadCloserImpl[T]) Read

func (impl ReadCloserImpl[T]) Read(ctx context.Context) (r T, err error)

Read implements Reader by deferring to the internal "ImplR" func. If the internal "ImplR" is not set, an io.EOF will be returned.

type ReadWriteCloser

type ReadWriteCloser[T, U any] interface {
	io.Closer
	Reader[T]
	Writer[U]
}

ReadWriteCloser groups Reader[T] and Writer[U] with io.Closer.

type ReadWriteCloserImpl

type ReadWriteCloserImpl[T, U any] struct {
	ImplC func() error
	ImplR func(context.Context) (T, error)
	ImplW func(context.Context, U) error
}

ReadWriteCloserImpl implements ReadWriteCloser with its methods Read, Write and Close -- the logic of those funcs is deferred to ImplR (Read), ImplW (Write), and ImplC (Close). This is for convenience, as you may use a functional implementation of the interface without defining a new type.

func (ReadWriteCloserImpl[T, U]) Close

func (impl ReadWriteCloserImpl[T, U]) Close() (err error)

Close implements io.Close by deferring to the internal ImplC func. If the internal ImplC func is nil, nothing will happen.

func (ReadWriteCloserImpl[T, U]) Read

func (impl ReadWriteCloserImpl[T, U]) Read(ctx context.Context) (r T, err error)

Read implements Reader[T] by deferring logic to the internal ImplR func. If it's not set, an io.EOF is returned.

func (ReadWriteCloserImpl[T, U]) Write

func (impl ReadWriteCloserImpl[T, U]) Write(ctx context.Context, v U) (err error)

Write implements Writer[U] by deferring logic to the internal ImplW func. If it's not set, an io.ErrClosedPipe is returned.

type ReadWriter

type ReadWriter[T, U any] interface {
	Reader[T]
	Writer[U]
}

ReadWriter groups Reader[T] and Writer[U].

func NewReadWriterFrom

func NewReadWriterFrom[T any](vs ...T) ReadWriter[T, T]

NewReadWriterFrom returns a ReadWriter[T] which writes into- and read from an internal buffer. The buffer is initially populated with the given values. The buffer acts like a stack, and a read while the buf is empty returns io.EOF.

type ReadWriterImpl

type ReadWriterImpl[T, U any] struct {
	ImplR func(context.Context) (T, error)
	ImplW func(context.Context, U) error
}

ReadWriterImpl implements ReadWriter[T, U] with its Read and Write methods, their logic is deferred to the internal ImplR and ImplW fields (funcs). This is for convenience, as you may use a functional implementation of ReadWriter without defining a new type (that's done for you here).

func (ReadWriterImpl[T, U]) Read

func (impl ReadWriterImpl[T, U]) Read(ctx context.Context) (r T, err error)

Read implements the Reader[T] part of ReadWriter[T, U] by deferring logic to the internal ImplR func. If it's not set, an io.EOF is returned.

func (ReadWriterImpl[T, U]) Write

func (impl ReadWriterImpl[T, U]) Write(ctx context.Context, v U) (err error)

Write implements the Writer[U] part of ReadWriter[T, U] by deferring logic to the internal ImplW func. If it's not set, an io.ErrClosedPipe is returned.

type Reader

type Reader[T any] interface {
	Read(context.Context) (T, error)
}

Reader reads T, it is intended to act as a generic variant of io.Reader.

func NewReaderFrom

func NewReaderFrom[T any](vs ...T) Reader[T]

NewReaderFrom returns a Reader which yields values from the given vals.

func NewReaderWithBatching

func NewReaderWithBatching[T any](r Reader[T], size int) Reader[[]T]

NewReaderWithBatching returns a reader which batches 'r' into slices with the specified 'size'. If the size is not set (or negative), it will be set to a small number. Note that the last slice may contain values when the returned reader gives an io.EOF.

func NewReaderWithUnbatching

func NewReaderWithUnbatching[T any](r Reader[[]T]) Reader[T]

NewReaderWithUnbatching returns a reader of T from a reader of []T. Note that there is some internal buffering, so you may want to use this with caution as an unread buffer may cause value loss.

type ReaderImpl

type ReaderImpl[T any] struct {
	Impl func(context.Context) (T, error)
}

ReaderImpl implements Reader with it's Read method by deferring to 'Impl'. This is for convenience, as you may use a functional implementation of Reader without defining a new type (that's done for you here).

func (ReaderImpl[T]) Read

func (impl ReaderImpl[T]) Read(ctx context.Context) (r T, err error)

Read implements Reader by deferring to the internal "Impl" func. If the internal "Impl" is not set, an io.EOF will be returned.

type WriteCloser

type WriteCloser[T any] interface {
	io.Closer
	Writer[T]
}

WriteCloser groups Writer with io.Closer.

type WriteCloserImpl

type WriteCloserImpl[T any] struct {
	ImplC func() error
	ImplW func(context.Context, T) error
}

WriteCloserImpl implements Writer and io.Closer with its methods by deferring to ImplC (closer) and ImplW (writer). This is for convenience, as you may use a functional implementation of the interfaces without defining a new type.

func (WriteCloserImpl[T]) Close

func (impl WriteCloserImpl[T]) Close() error

Close implements io.Closer by deferring to the internal ImplC func. If the internal ImplC func is nil, nothing will happen.

func (WriteCloserImpl[T]) Write

func (impl WriteCloserImpl[T]) Write(
	ctx context.Context,
	v T,
) (
	err error,
)

Write implements Writer by deferring to the internal "ImplW" func. If the internal "ImplW" is not set, an io.ErrClosedPipe will be returned.

type Writer

type Writer[T any] interface {
	Write(context.Context, T) error
}

Writer writes T, it is intended to act as a generic variant of io.Writer. Use io.ErrClosedPipe as a signal for when writing should stop.

func NewWriterWithBatching

func NewWriterWithBatching[T any](w Writer[[]T], size int) Writer[T]

NewWriterWithBatching returns a Writer which writes into a buffer of a given size. When the buffer is full, it is written into 'w'. Note that this should be used with caution due to the internal buffer, as there may be value loss if the process exits before the buffer is filled and written to 'w', e.g if 'size' is 10 but the process exits after only writing 9 times. Example:

// Writes which logs values through 't.Log'.
logWriter := WriterImpl[[]int]{}
logWriter.Impl = func(_ context.Context, v []int) error { t.Log(v); return nil }

w := NewWriterWithBatching(logWriter, 2)
w.Write(nil, 1)
w.Write(nil, 2) // Logger logs: '[1, 2]'
w.Write(nil, 3)

func NewWriterWithUnbatching

func NewWriterWithUnbatching[T any](w Writer[T]) Writer[[]T]

NewWriterWithUnbatching returns a Writer which accepts []T on a Write call, then iterates through the slice and writes each value to 'w'. Example:

// Writes which logs values through 't.Log'.
logWriter := WriterImpl[int]{}
logWriter.Impl = func(_ context.Context, v int) error { t.Log(v); return nil }

w := NewWriterWithUnbatching(logWriter)
w.Write(nil, []int{1, 2})
// ^ logWriter logs the following lines:
//  1
//  2

type WriterImpl

type WriterImpl[T any] struct {
	Impl func(context.Context, T) error
}

WriterImpl implements Writer with its Write method by deferring to 'Impl'. This is for convenience, as you may use a functional implementation of Writer without defining a new type (that's done for you here).

func (WriterImpl[T]) Write

func (impl WriterImpl[T]) Write(
	ctx context.Context,
	v T,
) (
	err error,
)

Write implements Writer by deferring to the internal "Impl" func. If the internal "Impl" is not set, an io.ErrClosedPipe will be returned.

Jump to

Keyboard shortcuts

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