Skip to content

Instantly share code, notes, and snippets.

@CAFxX
Created August 26, 2024 06:49
Show Gist options
  • Save CAFxX/99c56111c97cbb9f5a9364d5cb2b2ae1 to your computer and use it in GitHub Desktop.
Save CAFxX/99c56111c97cbb9f5a9364d5cb2b2ae1 to your computer and use it in GitHub Desktop.
Generic `io.Write`
package io
import (
"iter"
"math"
)
type Writable interface {
~string | ~[]byte | ~byte | ~rune | ~[]rune |
iter.Seq[byte] | iter.Seq[rune] | iter.Seq2[byte, error] | iter.Seq2[rune, error] |
any // any -> Reader, WriterTo
// missing: [...]byte, [...]rune, *[...]byte, *[...]rune
}
func Write[T Writable, W Writer](w W, b T) (n int64, err error) {
r := func(n int, err error) (int64, error) { return int64(n), err }
switch b := any(b).(type) {
case []byte:
return r(w.Write(b))
case string:
switch _w := any(w).(type) {
case StringWriter:
return r(_w.WriteString(b))
default:
return r(w.Write([]byte(b)))
}
case byte:
switch _w := any(w).(type) {
case ByteWriter:
err := _w.WriteByte(b)
if err != nil {
return 0, err
}
return 1, nil
default:
if b <= math.MaxInt8 {
if w, ok := any(w).(interface{ WriteRune(rune) (int, error) }); ok {
return r(w.WriteRune(rune(b)))
}
}
return r(w.Write([]byte{b}))
}
case rune:
if b <= math.MaxUint8 {
if w, ok := any(w).(ByteWriter); ok {
err := w.WriteByte(byte(b))
if err != nil {
return 0, err
}
return 1, nil
}
}
switch _w := any(w).(type) {
case interface{ WriteRune(rune) (int, error) }:
return r(_w.WriteRune(b))
case StringWriter:
return r(_w.WriteString(string(b)))
default:
return r(w.Write([]byte(string(b))))
}
case []rune:
switch _w := any(w).(type) {
case interface{ WriteRune(rune) (int, error) }:
for _, c := range b {
_n, _err := r(_w.WriteRune(c))
n += _n
if err != nil {
return n, _err
}
}
case StringWriter:
return r(_w.WriteString(string(b)))
default:
return r(w.Write([]byte(string(b))))
}
case iter.Seq[byte]:
switch _w := any(w).(type) {
case ByteWriter:
for c := range b {
err := _w.WriteByte(c)
if err != nil {
return n, err
}
n++
}
return
default:
for c := range b {
_, err = w.Write([]byte{c})
if err != nil {
return n, err
}
n++
}
return
}
case iter.Seq2[byte, error]:
switch _w := any(w).(type) {
case ByteWriter:
for c, err := range b {
if err != nil {
return n, err
}
err := _w.WriteByte(c)
if err != nil {
return n, err
}
n++
}
return
default:
for c, err := range b {
if err != nil {
return n, err
}
_, err = w.Write([]byte{c})
if err != nil {
return n, err
}
n++
}
return
}
case iter.Seq[rune]:
switch _w := any(w).(type) {
case interface{ WriteRune(rune) (int, error) }:
for c := range b {
_n, err := r(_w.WriteRune(c))
n += _n
if err != nil {
return n, err
}
}
return
default:
for c := range b {
_n, err := r(w.Write([]byte(string(c))))
n += _n
if err != nil {
return n, err
}
}
return
}
case iter.Seq2[rune, error]:
switch _w := any(w).(type) {
case interface{ WriteRune(rune) (int, error) }:
for c, err := range b {
if err != nil {
return n, err
}
_n, err := r(_w.WriteRune(c))
n += _n
if err != nil {
return n, err
}
}
return
default:
for c, err := range b {
if err != nil {
return n, err
}
_n, err := r(w.Write([]byte(string(c))))
n += _n
if err != nil {
return n, err
}
}
return
}
case WriterTo:
return b.WriteTo(w)
case Reader:
switch _w := any(w).(type) {
case ReaderFrom:
return _w.ReadFrom(b)
default:
return Copy(w, b)
}
default:
panic("illegal type")
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment