mirror of
https://github.com/syncthing/syncthing.git
synced 2024-11-17 10:58:49 -07:00
148 lines
2.7 KiB
Go
148 lines
2.7 KiB
Go
|
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
||
|
// All rights reserved. Use of this source code is governed by an MIT-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package xdr
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
"reflect"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
type Unmarshaller struct {
|
||
|
Error error
|
||
|
Data []byte
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalRaw(l int) []byte {
|
||
|
if u.Error != nil {
|
||
|
return nil
|
||
|
}
|
||
|
if len(u.Data) < l {
|
||
|
u.Error = io.ErrUnexpectedEOF
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
v := u.Data[:l]
|
||
|
u.Data = u.Data[l:]
|
||
|
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalString() string {
|
||
|
return u.UnmarshalStringMax(0)
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalStringMax(max int) string {
|
||
|
buf := u.UnmarshalBytesMax(max)
|
||
|
if len(buf) == 0 || u.Error != nil {
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
var v string
|
||
|
p := (*reflect.StringHeader)(unsafe.Pointer(&v))
|
||
|
p.Data = uintptr(unsafe.Pointer(&buf[0]))
|
||
|
p.Len = len(buf)
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalBytes() []byte {
|
||
|
return u.UnmarshalBytesMax(0)
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalBytesMax(max int) []byte {
|
||
|
if u.Error != nil {
|
||
|
return nil
|
||
|
}
|
||
|
if len(u.Data) < 4 {
|
||
|
u.Error = io.ErrUnexpectedEOF
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
l := int(u.Data[3]) | int(u.Data[2])<<8 | int(u.Data[1])<<16 | int(u.Data[0])<<24
|
||
|
if l == 0 {
|
||
|
u.Data = u.Data[4:]
|
||
|
return nil
|
||
|
}
|
||
|
if l < 0 || max > 0 && l > max {
|
||
|
// l may be negative on 32 bit builds
|
||
|
u.Error = ElementSizeExceeded("bytes field", l, max)
|
||
|
return nil
|
||
|
}
|
||
|
if len(u.Data) < l+4 {
|
||
|
u.Error = io.ErrUnexpectedEOF
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
v := u.Data[4 : 4+l]
|
||
|
u.Data = u.Data[4+l+Padding(l):]
|
||
|
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalBool() bool {
|
||
|
return u.UnmarshalUint8() != 0
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalUint8() uint8 {
|
||
|
if u.Error != nil {
|
||
|
return 0
|
||
|
}
|
||
|
if len(u.Data) < 4 {
|
||
|
u.Error = io.ErrUnexpectedEOF
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
v := uint8(u.Data[3])
|
||
|
u.Data = u.Data[4:]
|
||
|
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalUint16() uint16 {
|
||
|
if u.Error != nil {
|
||
|
return 0
|
||
|
}
|
||
|
if len(u.Data) < 4 {
|
||
|
u.Error = io.ErrUnexpectedEOF
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
v := uint16(u.Data[3]) | uint16(u.Data[2])<<8
|
||
|
u.Data = u.Data[4:]
|
||
|
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalUint32() uint32 {
|
||
|
if u.Error != nil {
|
||
|
return 0
|
||
|
}
|
||
|
if len(u.Data) < 4 {
|
||
|
u.Error = io.ErrUnexpectedEOF
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
v := uint32(u.Data[3]) | uint32(u.Data[2])<<8 | uint32(u.Data[1])<<16 | uint32(u.Data[0])<<24
|
||
|
u.Data = u.Data[4:]
|
||
|
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func (u *Unmarshaller) UnmarshalUint64() uint64 {
|
||
|
if u.Error != nil {
|
||
|
return 0
|
||
|
}
|
||
|
if len(u.Data) < 8 {
|
||
|
u.Error = io.ErrUnexpectedEOF
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
v := uint64(u.Data[7]) | uint64(u.Data[6])<<8 | uint64(u.Data[5])<<16 | uint64(u.Data[4])<<24 |
|
||
|
uint64(u.Data[3])<<32 | uint64(u.Data[2])<<40 | uint64(u.Data[1])<<48 | uint64(u.Data[0])<<56
|
||
|
u.Data = u.Data[8:]
|
||
|
|
||
|
return v
|
||
|
}
|