Created
August 26, 2024 06:49
-
-
Save CAFxX/99c56111c97cbb9f5a9364d5cb2b2ae1 to your computer and use it in GitHub Desktop.
Generic `io.Write`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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