106 lines
2.0 KiB
Go
106 lines
2.0 KiB
Go
package binarystr
|
|
|
|
import (
|
|
`errors`
|
|
`io`
|
|
`strings`
|
|
)
|
|
|
|
/*
|
|
Read conforms to an [io.Reader].
|
|
It returns bitstring encoding of the data in e's read source.
|
|
|
|
(To conform to [io.Reader], this is returned as bytes - e.g. []byte(string()).)
|
|
|
|
IMPORTANT: Read will return [ErrBadNumOct] if len(b) % 8 != 0! EIGHT BYTES in b equal ONE BYTE
|
|
from e's read source! Keep this in mind and size b accordingly for your desired decoded data size!
|
|
Likewise, n will ALWAYS be len(b), but the number of bytes actually read from e's internal reader
|
|
will ALWAYS be n/8! (If for some bizarre case it isn't, err will be [BadReadErr].)
|
|
*/
|
|
func (e *Encoder) Read(b []byte) (n int, err error) {
|
|
|
|
var inN int
|
|
var s string
|
|
var buf []byte
|
|
|
|
defer func() {
|
|
if b != nil && buf != nil {
|
|
s = BytesToStr(buf)
|
|
copy(b, []byte(s))
|
|
}
|
|
}()
|
|
|
|
if len(b) == 0 {
|
|
return
|
|
}
|
|
if len(b)%8 != 0 {
|
|
err = ErrBadNumOct
|
|
return
|
|
}
|
|
|
|
buf = make([]byte, len(b)/8)
|
|
if inN, err = e.r.Read(buf); err != nil {
|
|
return
|
|
}
|
|
if inN != len(buf) {
|
|
if len(buf) > inN {
|
|
buf = buf[:inN]
|
|
}
|
|
err = &BadReadErr{
|
|
numBytes: uint64(inN),
|
|
}
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
/*
|
|
ReadString returns a bitstring-encoded [string] from the entirety of the data
|
|
in the source reader of e.
|
|
|
|
IMPORTANT: If e's source reader is a non-terminating stream (e.g. a [math/rand.Rand]),
|
|
this function will NEVER RETURN (and will likely consume all memory).
|
|
YOU HAVE BEEN WARNED.
|
|
|
|
n is the number of bytes read from e's source reader.
|
|
*/
|
|
func (e *Encoder) ReadString() (s string, n uint64, err error) {
|
|
|
|
var inN int
|
|
var buf []byte
|
|
var rErr error
|
|
var sb *strings.Builder = new(strings.Builder)
|
|
|
|
defer func() {
|
|
if sb != nil {
|
|
s = sb.String()
|
|
}
|
|
}()
|
|
|
|
for {
|
|
buf = make([]byte, bufSz)
|
|
inN, rErr = e.r.Read(buf)
|
|
n += uint64(inN)
|
|
|
|
if inN != 0 {
|
|
if inN < bufSz {
|
|
buf = buf[:inN]
|
|
}
|
|
sb.WriteString(BytesToStr(buf))
|
|
} else {
|
|
if errors.Is(rErr, io.EOF) {
|
|
rErr = nil
|
|
}
|
|
break
|
|
}
|
|
|
|
if rErr != nil {
|
|
err = rErr
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|