cb7e06bdb9
All sync status reads now also check for failure status, using the same logic as the normal Scanner (the only difference being that for normal scanners, length is encoded as a hex string, but for sync scanners it's in binary little-endian).
93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
package wire
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/zach-klippenstein/goadb/util"
|
|
)
|
|
|
|
type SyncScanner interface {
|
|
io.Closer
|
|
StatusReader
|
|
ReadInt32() (int32, error)
|
|
ReadFileMode() (os.FileMode, error)
|
|
ReadTime() (time.Time, error)
|
|
|
|
// Reads an octet length, followed by length bytes.
|
|
ReadString() (string, error)
|
|
|
|
// Reads an octet length, and returns a reader that will read length
|
|
// bytes (see io.LimitReader). The returned reader should be fully
|
|
// read before reading anything off the Scanner again.
|
|
ReadBytes() (io.Reader, error)
|
|
}
|
|
|
|
type realSyncScanner struct {
|
|
io.Reader
|
|
}
|
|
|
|
func NewSyncScanner(r io.Reader) SyncScanner {
|
|
return &realSyncScanner{r}
|
|
}
|
|
|
|
func (s *realSyncScanner) ReadStatus(req string) (string, error) {
|
|
return readStatusFailureAsError(s.Reader, req, readInt32)
|
|
}
|
|
|
|
func (s *realSyncScanner) ReadInt32() (int32, error) {
|
|
value, err := readInt32(s.Reader)
|
|
return int32(value), util.WrapErrorf(err, util.NetworkError, "error reading int from sync scanner")
|
|
}
|
|
func (s *realSyncScanner) ReadFileMode() (os.FileMode, error) {
|
|
var value uint32
|
|
err := binary.Read(s.Reader, binary.LittleEndian, &value)
|
|
if err != nil {
|
|
return 0, util.WrapErrorf(err, util.NetworkError, "error reading filemode from sync scanner")
|
|
}
|
|
return ParseFileModeFromAdb(value), nil
|
|
|
|
}
|
|
func (s *realSyncScanner) ReadTime() (time.Time, error) {
|
|
seconds, err := s.ReadInt32()
|
|
if err != nil {
|
|
return time.Time{}, util.WrapErrorf(err, util.NetworkError, "error reading time from sync scanner")
|
|
}
|
|
|
|
return time.Unix(int64(seconds), 0).UTC(), nil
|
|
}
|
|
|
|
func (s *realSyncScanner) ReadString() (string, error) {
|
|
length, err := s.ReadInt32()
|
|
if err != nil {
|
|
return "", util.WrapErrorf(err, util.NetworkError, "error reading length from sync scanner")
|
|
}
|
|
|
|
bytes := make([]byte, length)
|
|
n, rawErr := io.ReadFull(s.Reader, bytes)
|
|
if rawErr != nil && rawErr != io.ErrUnexpectedEOF {
|
|
return "", util.WrapErrorf(rawErr, util.NetworkError, "error reading string from sync scanner")
|
|
} else if rawErr == io.ErrUnexpectedEOF {
|
|
return "", errIncompleteMessage("bytes", n, int(length))
|
|
}
|
|
|
|
return string(bytes), nil
|
|
}
|
|
func (s *realSyncScanner) ReadBytes() (io.Reader, error) {
|
|
length, err := s.ReadInt32()
|
|
if err != nil {
|
|
return nil, util.WrapErrorf(err, util.NetworkError, "error reading bytes from sync scanner")
|
|
}
|
|
|
|
return io.LimitReader(s.Reader, int64(length)), nil
|
|
}
|
|
|
|
func (s *realSyncScanner) Close() error {
|
|
if closer, ok := s.Reader.(io.Closer); ok {
|
|
return util.WrapErrorf(closer.Close(), util.NetworkError, "error closing sync scanner")
|
|
}
|
|
return nil
|
|
}
|