Update module lib/pq to v1.6.0 (#572)
Update module lib/pq to v1.6.0 Reviewed-on: https://kolaente.dev/vikunja/api/pulls/572
This commit is contained in:
413
vendor/github.com/jcmturner/rpc/v2/ndr/arrays.go
generated
vendored
Normal file
413
vendor/github.com/jcmturner/rpc/v2/ndr/arrays.go
generated
vendored
Normal file
@ -0,0 +1,413 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// intFromTag returns an int that is a value in a struct tag key/value pair
|
||||
func intFromTag(tag reflect.StructTag, key string) (int, error) {
|
||||
ndrTag := parseTags(tag)
|
||||
d := 1
|
||||
if n, ok := ndrTag.Map[key]; ok {
|
||||
i, err := strconv.Atoi(n)
|
||||
if err != nil {
|
||||
return d, fmt.Errorf("invalid dimensions tag [%s]: %v", n, err)
|
||||
}
|
||||
d = i
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// parseDimensions returns the a slice of the size of each dimension and type of the member at the deepest level.
|
||||
func parseDimensions(v reflect.Value) (l []int, tb reflect.Type) {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
t := v.Type()
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Kind() != reflect.Array && t.Kind() != reflect.Slice {
|
||||
return
|
||||
}
|
||||
l = append(l, v.Len())
|
||||
if t.Elem().Kind() == reflect.Array || t.Elem().Kind() == reflect.Slice {
|
||||
// contains array or slice
|
||||
var m []int
|
||||
m, tb = parseDimensions(v.Index(0))
|
||||
l = append(l, m...)
|
||||
} else {
|
||||
tb = t.Elem()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// sliceDimensions returns the count of dimensions a slice has.
|
||||
func sliceDimensions(t reflect.Type) (d int, tb reflect.Type) {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Kind() == reflect.Slice {
|
||||
d++
|
||||
var n int
|
||||
n, tb = sliceDimensions(t.Elem())
|
||||
d += n
|
||||
} else {
|
||||
tb = t
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// makeSubSlices is a deep recursive creation/initialisation of multi-dimensional slices.
|
||||
// Takes the reflect.Value of the 1st dimension and a slice of the lengths of the sub dimensions
|
||||
func makeSubSlices(v reflect.Value, l []int) {
|
||||
ty := v.Type().Elem()
|
||||
if ty.Kind() != reflect.Slice {
|
||||
return
|
||||
}
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
s := reflect.MakeSlice(ty, l[0], l[0])
|
||||
v.Index(i).Set(s)
|
||||
// Are there more sub dimensions?
|
||||
if len(l) > 1 {
|
||||
makeSubSlices(v.Index(i), l[1:])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// multiDimensionalIndexPermutations returns all the permutations of the indexes of a multi-dimensional slice.
|
||||
// The input is a slice of integers that indicates the max size/length of each dimension
|
||||
func multiDimensionalIndexPermutations(l []int) (ps [][]int) {
|
||||
z := make([]int, len(l), len(l)) // The zeros permutation
|
||||
ps = append(ps, z)
|
||||
// for each dimension, in reverse
|
||||
for i := len(l) - 1; i >= 0; i-- {
|
||||
ws := make([][]int, len(ps))
|
||||
copy(ws, ps)
|
||||
//create a permutation for each of the iterations of the current dimension
|
||||
for j := 1; j <= l[i]-1; j++ {
|
||||
// For each existing permutation
|
||||
for _, p := range ws {
|
||||
np := make([]int, len(p), len(p))
|
||||
copy(np, p)
|
||||
np[i] = j
|
||||
ps = append(ps, np)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// precedingMax reads off the next conformant max value
|
||||
func (dec *Decoder) precedingMax() uint32 {
|
||||
m := dec.conformantMax[0]
|
||||
dec.conformantMax = dec.conformantMax[1:]
|
||||
return m
|
||||
}
|
||||
|
||||
// fillFixedArray establishes if the fixed array is uni or multi dimensional and then fills it.
|
||||
func (dec *Decoder) fillFixedArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
l, t := parseDimensions(v)
|
||||
if t.Kind() == reflect.String {
|
||||
tag = reflect.StructTag(subStringArrayTag)
|
||||
}
|
||||
if len(l) < 1 {
|
||||
return errors.New("could not establish dimensions of fixed array")
|
||||
}
|
||||
if len(l) == 1 {
|
||||
err := dec.fillUniDimensionalFixedArray(v, tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill uni-dimensional fixed array: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Fixed array is multidimensional
|
||||
ps := multiDimensionalIndexPermutations(l[:len(l)-1])
|
||||
for _, p := range ps {
|
||||
// Get current multi-dimensional index to fill
|
||||
a := v
|
||||
for _, i := range p {
|
||||
a = a.Index(i)
|
||||
}
|
||||
// fill with the last dimension array
|
||||
err := dec.fillUniDimensionalFixedArray(a, tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill dimension %v of multi-dimensional fixed array: %v", p, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readUniDimensionalFixedArray reads an array (not slice) from the byte stream.
|
||||
func (dec *Decoder) fillUniDimensionalFixedArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
err := dec.fill(v.Index(i), tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill index %d of fixed array: %v", i, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillConformantArray establishes if the conformant array is uni or multi dimensional and then fills the slice.
|
||||
func (dec *Decoder) fillConformantArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
d, _ := sliceDimensions(v.Type())
|
||||
if d > 1 {
|
||||
err := dec.fillMultiDimensionalConformantArray(v, d, tag, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := dec.fillUniDimensionalConformantArray(v, tag, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillUniDimensionalConformantArray fills the uni-dimensional slice value.
|
||||
func (dec *Decoder) fillUniDimensionalConformantArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
m := dec.precedingMax()
|
||||
n := int(m)
|
||||
a := reflect.MakeSlice(v.Type(), n, n)
|
||||
for i := 0; i < n; i++ {
|
||||
err := dec.fill(a.Index(i), tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill index %d of uni-dimensional conformant array: %v", i, err)
|
||||
}
|
||||
}
|
||||
v.Set(a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillMultiDimensionalConformantArray fills the multi-dimensional slice value provided from conformant array data.
|
||||
// The number of dimensions must be specified. This must be less than or equal to the dimensions in the slice for this
|
||||
// method not to panic.
|
||||
func (dec *Decoder) fillMultiDimensionalConformantArray(v reflect.Value, d int, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
// Read the max size of each dimensions from the ndr stream
|
||||
l := make([]int, d, d)
|
||||
for i := range l {
|
||||
l[i] = int(dec.precedingMax())
|
||||
}
|
||||
// Initialise size of slices
|
||||
// Initialise the size of the 1st dimension
|
||||
ty := v.Type()
|
||||
v.Set(reflect.MakeSlice(ty, l[0], l[0]))
|
||||
// Initialise the size of the other dimensions recursively
|
||||
makeSubSlices(v, l[1:])
|
||||
|
||||
// Get all permutations of the indexes and go through each and fill
|
||||
ps := multiDimensionalIndexPermutations(l)
|
||||
for _, p := range ps {
|
||||
// Get current multi-dimensional index to fill
|
||||
a := v
|
||||
for _, i := range p {
|
||||
a = a.Index(i)
|
||||
}
|
||||
err := dec.fill(a, tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill index %v of slice: %v", p, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillVaryingArray establishes if the varying array is uni or multi dimensional and then fills the slice.
|
||||
func (dec *Decoder) fillVaryingArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
d, t := sliceDimensions(v.Type())
|
||||
if d > 1 {
|
||||
err := dec.fillMultiDimensionalVaryingArray(v, t, d, tag, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := dec.fillUniDimensionalVaryingArray(v, tag, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillUniDimensionalVaryingArray fills the uni-dimensional slice value.
|
||||
func (dec *Decoder) fillUniDimensionalVaryingArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
o, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read offset of uni-dimensional varying array: %v", err)
|
||||
}
|
||||
s, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not establish actual count of uni-dimensional varying array: %v", err)
|
||||
}
|
||||
t := v.Type()
|
||||
// Total size of the array is the offset in the index being passed plus the actual count of elements being passed.
|
||||
n := int(s + o)
|
||||
a := reflect.MakeSlice(t, n, n)
|
||||
// Populate the array starting at the offset specified
|
||||
for i := int(o); i < n; i++ {
|
||||
err := dec.fill(a.Index(i), tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill index %d of uni-dimensional varying array: %v", i, err)
|
||||
}
|
||||
}
|
||||
v.Set(a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillMultiDimensionalVaryingArray fills the multi-dimensional slice value provided from varying array data.
|
||||
// The number of dimensions must be specified. This must be less than or equal to the dimensions in the slice for this
|
||||
// method not to panic.
|
||||
func (dec *Decoder) fillMultiDimensionalVaryingArray(v reflect.Value, t reflect.Type, d int, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
// Read the offset and actual count of each dimensions from the ndr stream
|
||||
o := make([]int, d, d)
|
||||
l := make([]int, d, d)
|
||||
for i := range l {
|
||||
off, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read offset of dimension %d: %v", i+1, err)
|
||||
}
|
||||
o[i] = int(off)
|
||||
s, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read size of dimension %d: %v", i+1, err)
|
||||
}
|
||||
l[i] = int(s) + int(off)
|
||||
}
|
||||
// Initialise size of slices
|
||||
// Initialise the size of the 1st dimension
|
||||
ty := v.Type()
|
||||
v.Set(reflect.MakeSlice(ty, l[0], l[0]))
|
||||
// Initialise the size of the other dimensions recursively
|
||||
makeSubSlices(v, l[1:])
|
||||
|
||||
// Get all permutations of the indexes and go through each and fill
|
||||
ps := multiDimensionalIndexPermutations(l)
|
||||
for _, p := range ps {
|
||||
// Get current multi-dimensional index to fill
|
||||
a := v
|
||||
var os bool // should this permutation be skipped due to the offset of any of the dimensions?
|
||||
for i, j := range p {
|
||||
if j < o[i] {
|
||||
os = true
|
||||
break
|
||||
}
|
||||
a = a.Index(j)
|
||||
}
|
||||
if os {
|
||||
// This permutation should be skipped as it is less than the offset for one of the dimensions.
|
||||
continue
|
||||
}
|
||||
err := dec.fill(a, tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill index %v of slice: %v", p, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillConformantVaryingArray establishes if the varying array is uni or multi dimensional and then fills the slice.
|
||||
func (dec *Decoder) fillConformantVaryingArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
d, t := sliceDimensions(v.Type())
|
||||
if d > 1 {
|
||||
err := dec.fillMultiDimensionalConformantVaryingArray(v, t, d, tag, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := dec.fillUniDimensionalConformantVaryingArray(v, tag, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillUniDimensionalConformantVaryingArray fills the uni-dimensional slice value.
|
||||
func (dec *Decoder) fillUniDimensionalConformantVaryingArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
m := dec.precedingMax()
|
||||
o, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read offset of uni-dimensional conformant varying array: %v", err)
|
||||
}
|
||||
s, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not establish actual count of uni-dimensional conformant varying array: %v", err)
|
||||
}
|
||||
if m < o+s {
|
||||
return errors.New("max count is less than the offset plus actual count")
|
||||
}
|
||||
t := v.Type()
|
||||
n := int(s)
|
||||
a := reflect.MakeSlice(t, n, n)
|
||||
for i := int(o); i < n; i++ {
|
||||
err := dec.fill(a.Index(i), tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill index %d of uni-dimensional conformant varying array: %v", i, err)
|
||||
}
|
||||
}
|
||||
v.Set(a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillMultiDimensionalConformantVaryingArray fills the multi-dimensional slice value provided from conformant varying array data.
|
||||
// The number of dimensions must be specified. This must be less than or equal to the dimensions in the slice for this
|
||||
// method not to panic.
|
||||
func (dec *Decoder) fillMultiDimensionalConformantVaryingArray(v reflect.Value, t reflect.Type, d int, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
// Read the offset and actual count of each dimensions from the ndr stream
|
||||
m := make([]int, d, d)
|
||||
for i := range m {
|
||||
m[i] = int(dec.precedingMax())
|
||||
}
|
||||
o := make([]int, d, d)
|
||||
l := make([]int, d, d)
|
||||
for i := range l {
|
||||
off, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read offset of dimension %d: %v", i+1, err)
|
||||
}
|
||||
o[i] = int(off)
|
||||
s, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read actual count of dimension %d: %v", i+1, err)
|
||||
}
|
||||
if m[i] < int(s)+int(off) {
|
||||
m[i] = int(s) + int(off)
|
||||
}
|
||||
l[i] = int(s)
|
||||
}
|
||||
// Initialise size of slices
|
||||
// Initialise the size of the 1st dimension
|
||||
ty := v.Type()
|
||||
v.Set(reflect.MakeSlice(ty, m[0], m[0]))
|
||||
// Initialise the size of the other dimensions recursively
|
||||
makeSubSlices(v, m[1:])
|
||||
|
||||
// Get all permutations of the indexes and go through each and fill
|
||||
ps := multiDimensionalIndexPermutations(m)
|
||||
for _, p := range ps {
|
||||
// Get current multi-dimensional index to fill
|
||||
a := v
|
||||
var os bool // should this permutation be skipped due to the offset of any of the dimensions or max is higher than the actual count being passed
|
||||
for i, j := range p {
|
||||
if j < o[i] || j >= l[i] {
|
||||
os = true
|
||||
break
|
||||
}
|
||||
a = a.Index(j)
|
||||
}
|
||||
if os {
|
||||
// This permutation should be skipped as it is less than the offset for one of the dimensions.
|
||||
continue
|
||||
}
|
||||
err := dec.fill(a, tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill index %v of slice: %v", p, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
393
vendor/github.com/jcmturner/rpc/v2/ndr/decoder.go
generated
vendored
Normal file
393
vendor/github.com/jcmturner/rpc/v2/ndr/decoder.go
generated
vendored
Normal file
@ -0,0 +1,393 @@
|
||||
// Package ndr provides the ability to unmarshal NDR encoded byte steams into Go data structures
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Struct tag values
|
||||
const (
|
||||
TagConformant = "conformant"
|
||||
TagVarying = "varying"
|
||||
TagPointer = "pointer"
|
||||
TagPipe = "pipe"
|
||||
)
|
||||
|
||||
// Decoder unmarshals NDR byte stream data into a Go struct representation
|
||||
type Decoder struct {
|
||||
r *bufio.Reader // source of the data
|
||||
size int // initial size of bytes in buffer
|
||||
ch CommonHeader // NDR common header
|
||||
ph PrivateHeader // NDR private header
|
||||
conformantMax []uint32 // conformant max values that were moved to the beginning of the structure
|
||||
s interface{} // pointer to the structure being populated
|
||||
current []string // keeps track of the current field being populated
|
||||
}
|
||||
|
||||
type deferedPtr struct {
|
||||
v reflect.Value
|
||||
tag reflect.StructTag
|
||||
}
|
||||
|
||||
// NewDecoder creates a new instance of a NDR Decoder.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
dec := new(Decoder)
|
||||
dec.r = bufio.NewReader(r)
|
||||
dec.r.Peek(int(commonHeaderBytes)) // For some reason an operation is needed on the buffer to initialise it so Buffered() != 0
|
||||
dec.size = dec.r.Buffered()
|
||||
return dec
|
||||
}
|
||||
|
||||
// Decode unmarshals the NDR encoded bytes into the pointer of a struct provided.
|
||||
func (dec *Decoder) Decode(s interface{}) error {
|
||||
dec.s = s
|
||||
err := dec.readCommonHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dec.readPrivateHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = dec.r.Discard(4) //The next 4 bytes are an RPC unique pointer referent. We just skip these.
|
||||
if err != nil {
|
||||
return Errorf("unable to process byte stream: %v", err)
|
||||
}
|
||||
|
||||
return dec.process(s, reflect.StructTag(""))
|
||||
}
|
||||
|
||||
func (dec *Decoder) process(s interface{}, tag reflect.StructTag) error {
|
||||
// Scan for conformant fields as their max counts are moved to the beginning
|
||||
// http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagfcjh_37
|
||||
err := dec.scanConformantArrays(s, tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Recursively fill the struct fields
|
||||
var localDef []deferedPtr
|
||||
err = dec.fill(s, tag, &localDef)
|
||||
if err != nil {
|
||||
return Errorf("could not decode: %v", err)
|
||||
}
|
||||
// Read any deferred referents associated with pointers
|
||||
for _, p := range localDef {
|
||||
err = dec.process(p.v, p.tag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not decode deferred referent: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// scanConformantArrays scans the structure for embedded conformant fields and captures the maximum element counts for
|
||||
// dimensions of the array that are moved to the beginning of the structure.
|
||||
func (dec *Decoder) scanConformantArrays(s interface{}, tag reflect.StructTag) error {
|
||||
err := dec.conformantScan(s, tag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to scan for embedded conformant arrays: %v", err)
|
||||
}
|
||||
for i := range dec.conformantMax {
|
||||
dec.conformantMax[i], err = dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read preceding conformant max count index %d: %v", i, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// conformantScan inspects the structure's fields for whether they are conformant.
|
||||
func (dec *Decoder) conformantScan(s interface{}, tag reflect.StructTag) error {
|
||||
ndrTag := parseTags(tag)
|
||||
if ndrTag.HasValue(TagPointer) {
|
||||
return nil
|
||||
}
|
||||
v := getReflectValue(s)
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
err := dec.conformantScan(v.Field(i), v.Type().Field(i).Tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case reflect.String:
|
||||
if !ndrTag.HasValue(TagConformant) {
|
||||
break
|
||||
}
|
||||
dec.conformantMax = append(dec.conformantMax, uint32(0))
|
||||
case reflect.Slice:
|
||||
if !ndrTag.HasValue(TagConformant) {
|
||||
break
|
||||
}
|
||||
d, t := sliceDimensions(v.Type())
|
||||
for i := 0; i < d; i++ {
|
||||
dec.conformantMax = append(dec.conformantMax, uint32(0))
|
||||
}
|
||||
// For string arrays there is a common max for the strings within the array.
|
||||
if t.Kind() == reflect.String {
|
||||
dec.conformantMax = append(dec.conformantMax, uint32(0))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) isPointer(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) (bool, error) {
|
||||
// Pointer so defer filling the referent
|
||||
ndrTag := parseTags(tag)
|
||||
if ndrTag.HasValue(TagPointer) {
|
||||
p, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("could not read pointer: %v", err)
|
||||
}
|
||||
ndrTag.delete(TagPointer)
|
||||
if p != 0 {
|
||||
// if pointer is not zero add to the deferred items at end of stream
|
||||
*def = append(*def, deferedPtr{v, ndrTag.StructTag()})
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func getReflectValue(s interface{}) (v reflect.Value) {
|
||||
if r, ok := s.(reflect.Value); ok {
|
||||
v = r
|
||||
} else {
|
||||
if reflect.ValueOf(s).Kind() == reflect.Ptr {
|
||||
v = reflect.ValueOf(s).Elem()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// fill populates fields with values from the NDR byte stream.
|
||||
func (dec *Decoder) fill(s interface{}, tag reflect.StructTag, localDef *[]deferedPtr) error {
|
||||
v := getReflectValue(s)
|
||||
|
||||
//// Pointer so defer filling the referent
|
||||
ptr, err := dec.isPointer(v, tag, localDef)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not process struct field(%s): %v", strings.Join(dec.current, "/"), err)
|
||||
}
|
||||
if ptr {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Populate the value from the byte stream
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
dec.current = append(dec.current, v.Type().Name()) //Track the current field being filled
|
||||
// in case struct is a union, track this and the selected union field for efficiency
|
||||
var unionTag reflect.Value
|
||||
var unionField string // field to fill if struct is a union
|
||||
// Go through each field in the struct and recursively fill
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fieldName := v.Type().Field(i).Name
|
||||
dec.current = append(dec.current, fieldName) //Track the current field being filled
|
||||
//fmt.Fprintf(os.Stderr, "DEBUG Decoding: %s\n", strings.Join(dec.current, "/"))
|
||||
structTag := v.Type().Field(i).Tag
|
||||
ndrTag := parseTags(structTag)
|
||||
|
||||
// Union handling
|
||||
if !unionTag.IsValid() {
|
||||
// Is this field a union tag?
|
||||
unionTag = dec.isUnion(v.Field(i), structTag)
|
||||
} else {
|
||||
// What is the selected field value of the union if we don't already know
|
||||
if unionField == "" {
|
||||
unionField, err = unionSelectedField(v, unionTag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not determine selected union value field for %s with discriminat"+
|
||||
" tag %s: %v", v.Type().Name(), unionTag, err)
|
||||
}
|
||||
}
|
||||
if ndrTag.HasValue(TagUnionField) && fieldName != unionField {
|
||||
// is a union and this field has not been selected so will skip it.
|
||||
dec.current = dec.current[:len(dec.current)-1] //This field has been skipped so remove it from the current field tracker
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Check if field is a pointer
|
||||
if v.Field(i).Type().Implements(reflect.TypeOf(new(RawBytes)).Elem()) &&
|
||||
v.Field(i).Type().Kind() == reflect.Slice && v.Field(i).Type().Elem().Kind() == reflect.Uint8 {
|
||||
//field is for rawbytes
|
||||
structTag, err = addSizeToTag(v, v.Field(i), structTag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get rawbytes field(%s) size: %v", strings.Join(dec.current, "/"), err)
|
||||
}
|
||||
ptr, err := dec.isPointer(v.Field(i), structTag, localDef)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not process struct field(%s): %v", strings.Join(dec.current, "/"), err)
|
||||
}
|
||||
if !ptr {
|
||||
err := dec.readRawBytes(v.Field(i), structTag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill raw bytes struct field(%s): %v", strings.Join(dec.current, "/"), err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := dec.fill(v.Field(i), structTag, localDef)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill struct field(%s): %v", strings.Join(dec.current, "/"), err)
|
||||
}
|
||||
}
|
||||
dec.current = dec.current[:len(dec.current)-1] //This field has been filled so remove it from the current field tracker
|
||||
}
|
||||
dec.current = dec.current[:len(dec.current)-1] //This field has been filled so remove it from the current field tracker
|
||||
case reflect.Bool:
|
||||
i, err := dec.readBool()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Uint8:
|
||||
i, err := dec.readUint8()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Uint16:
|
||||
i, err := dec.readUint16()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Uint32:
|
||||
i, err := dec.readUint32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Uint64:
|
||||
i, err := dec.readUint64()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Int8:
|
||||
i, err := dec.readInt8()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Int16:
|
||||
i, err := dec.readInt16()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Int32:
|
||||
i, err := dec.readInt32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Int64:
|
||||
i, err := dec.readInt64()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %s: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.String:
|
||||
ndrTag := parseTags(tag)
|
||||
conformant := ndrTag.HasValue(TagConformant)
|
||||
// strings are always varying so this is assumed without an explicit tag
|
||||
var s string
|
||||
var err error
|
||||
if conformant {
|
||||
s, err = dec.readConformantVaryingString(localDef)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill with conformant varying string: %v", err)
|
||||
}
|
||||
} else {
|
||||
s, err = dec.readVaryingString(localDef)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill with varying string: %v", err)
|
||||
}
|
||||
}
|
||||
v.Set(reflect.ValueOf(s))
|
||||
case reflect.Float32:
|
||||
i, err := dec.readFloat32()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %v: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Float64:
|
||||
i, err := dec.readFloat64()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill %v: %v", v.Type().Name(), err)
|
||||
}
|
||||
v.Set(reflect.ValueOf(i))
|
||||
case reflect.Array:
|
||||
err := dec.fillFixedArray(v, tag, localDef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case reflect.Slice:
|
||||
if v.Type().Implements(reflect.TypeOf(new(RawBytes)).Elem()) && v.Type().Elem().Kind() == reflect.Uint8 {
|
||||
//field is for rawbytes
|
||||
err := dec.readRawBytes(v, tag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill raw bytes struct field(%s): %v", strings.Join(dec.current, "/"), err)
|
||||
}
|
||||
break
|
||||
}
|
||||
ndrTag := parseTags(tag)
|
||||
conformant := ndrTag.HasValue(TagConformant)
|
||||
varying := ndrTag.HasValue(TagVarying)
|
||||
if ndrTag.HasValue(TagPipe) {
|
||||
err := dec.fillPipe(v, tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
_, t := sliceDimensions(v.Type())
|
||||
if t.Kind() == reflect.String && !ndrTag.HasValue(subStringArrayValue) {
|
||||
// String array
|
||||
err := dec.readStringsArray(v, tag, localDef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
// varying is assumed as fixed arrays use the Go array type rather than slice
|
||||
if conformant && varying {
|
||||
err := dec.fillConformantVaryingArray(v, tag, localDef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if !conformant && varying {
|
||||
err := dec.fillVaryingArray(v, tag, localDef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
//default to conformant and not varying
|
||||
err := dec.fillConformantArray(v, tag, localDef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupported type")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readBytes returns a number of bytes from the NDR byte stream.
|
||||
func (dec *Decoder) readBytes(n int) ([]byte, error) {
|
||||
//TODO make this take an int64 as input to allow for larger values on all systems?
|
||||
b := make([]byte, n, n)
|
||||
m, err := dec.r.Read(b)
|
||||
if err != nil || m != n {
|
||||
return b, fmt.Errorf("error reading bytes from stream: %v", err)
|
||||
}
|
||||
return b, nil
|
||||
}
|
18
vendor/github.com/jcmturner/rpc/v2/ndr/error.go
generated
vendored
Normal file
18
vendor/github.com/jcmturner/rpc/v2/ndr/error.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
package ndr
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Malformed implements the error interface for malformed NDR encoding errors.
|
||||
type Malformed struct {
|
||||
EText string
|
||||
}
|
||||
|
||||
// Error implements the error interface on the Malformed struct.
|
||||
func (e Malformed) Error() string {
|
||||
return fmt.Sprintf("malformed NDR stream: %s", e.EText)
|
||||
}
|
||||
|
||||
// Errorf formats an error message into a malformed NDR error.
|
||||
func Errorf(format string, a ...interface{}) Malformed {
|
||||
return Malformed{EText: fmt.Sprintf(format, a...)}
|
||||
}
|
116
vendor/github.com/jcmturner/rpc/v2/ndr/header.go
generated
vendored
Normal file
116
vendor/github.com/jcmturner/rpc/v2/ndr/header.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/*
|
||||
Serialization Version 1
|
||||
https://msdn.microsoft.com/en-us/library/cc243563.aspx
|
||||
|
||||
Common Header - https://msdn.microsoft.com/en-us/library/cc243890.aspx
|
||||
8 bytes in total:
|
||||
- First byte - Version: Must equal 1
|
||||
- Second byte - 1st 4 bits: Endianess (0=Big; 1=Little); 2nd 4 bits: Character Encoding (0=ASCII; 1=EBCDIC)
|
||||
- 3rd - Floating point representation (This does not seem to be the case in examples for Microsoft test sources)
|
||||
- 4th - Common Header Length: Must equal 8
|
||||
- 5th - 8th - Filler: MUST be set to 0xcccccccc on marshaling, and SHOULD be ignored during unmarshaling.
|
||||
|
||||
Private Header - https://msdn.microsoft.com/en-us/library/cc243919.aspx
|
||||
8 bytes in total:
|
||||
- First 4 bytes - Indicates the length of a serialized top-level type in the octet stream. It MUST include the padding length and exclude the header itself.
|
||||
- Second 4 bytes - Filler: MUST be set to 0 (zero) during marshaling, and SHOULD be ignored during unmarshaling.
|
||||
*/
|
||||
|
||||
const (
|
||||
protocolVersion uint8 = 1
|
||||
commonHeaderBytes uint16 = 8
|
||||
bigEndian = 0
|
||||
littleEndian = 1
|
||||
ascii uint8 = 0
|
||||
ebcdic uint8 = 1
|
||||
ieee uint8 = 0
|
||||
vax uint8 = 1
|
||||
cray uint8 = 2
|
||||
ibm uint8 = 3
|
||||
)
|
||||
|
||||
// CommonHeader implements the NDR common header: https://msdn.microsoft.com/en-us/library/cc243889.aspx
|
||||
type CommonHeader struct {
|
||||
Version uint8
|
||||
Endianness binary.ByteOrder
|
||||
CharacterEncoding uint8
|
||||
FloatRepresentation uint8
|
||||
HeaderLength uint16
|
||||
Filler []byte
|
||||
}
|
||||
|
||||
// PrivateHeader implements the NDR private header: https://msdn.microsoft.com/en-us/library/cc243919.aspx
|
||||
type PrivateHeader struct {
|
||||
ObjectBufferLength uint32
|
||||
Filler []byte
|
||||
}
|
||||
|
||||
func (dec *Decoder) readCommonHeader() error {
|
||||
// Version
|
||||
vb, err := dec.r.ReadByte()
|
||||
if err != nil {
|
||||
return Malformed{EText: "could not read first byte of common header for version"}
|
||||
}
|
||||
dec.ch.Version = uint8(vb)
|
||||
if dec.ch.Version != protocolVersion {
|
||||
return Malformed{EText: fmt.Sprintf("byte stream does not indicate a RPC Type serialization of version %v", protocolVersion)}
|
||||
}
|
||||
// Read Endianness & Character Encoding
|
||||
eb, err := dec.r.ReadByte()
|
||||
if err != nil {
|
||||
return Malformed{EText: "could not read second byte of common header for endianness"}
|
||||
}
|
||||
endian := int(eb >> 4 & 0xF)
|
||||
if endian != 0 && endian != 1 {
|
||||
return Malformed{EText: "common header does not indicate a valid endianness"}
|
||||
}
|
||||
dec.ch.CharacterEncoding = uint8(vb & 0xF)
|
||||
if dec.ch.CharacterEncoding != 0 && dec.ch.CharacterEncoding != 1 {
|
||||
return Malformed{EText: "common header does not indicate a valid character encoding"}
|
||||
}
|
||||
switch endian {
|
||||
case littleEndian:
|
||||
dec.ch.Endianness = binary.LittleEndian
|
||||
case bigEndian:
|
||||
dec.ch.Endianness = binary.BigEndian
|
||||
}
|
||||
// Common header length
|
||||
lb, err := dec.readBytes(2)
|
||||
if err != nil {
|
||||
return Malformed{EText: fmt.Sprintf("could not read common header length: %v", err)}
|
||||
}
|
||||
dec.ch.HeaderLength = dec.ch.Endianness.Uint16(lb)
|
||||
if dec.ch.HeaderLength != commonHeaderBytes {
|
||||
return Malformed{EText: "common header does not indicate a valid length"}
|
||||
}
|
||||
// Filler bytes
|
||||
dec.ch.Filler, err = dec.readBytes(4)
|
||||
if err != nil {
|
||||
return Malformed{EText: fmt.Sprintf("could not read common header filler: %v", err)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readPrivateHeader() error {
|
||||
// The next 8 bytes after the common header comprise the RPC type marshalling private header for constructed types.
|
||||
err := binary.Read(dec.r, dec.ch.Endianness, &dec.ph.ObjectBufferLength)
|
||||
if err != nil {
|
||||
return Malformed{EText: "could not read private header object buffer length"}
|
||||
}
|
||||
if dec.ph.ObjectBufferLength%8 != 0 {
|
||||
return Malformed{EText: "object buffer length not a multiple of 8"}
|
||||
}
|
||||
// Filler bytes
|
||||
dec.ph.Filler, err = dec.readBytes(4)
|
||||
if err != nil {
|
||||
return Malformed{EText: fmt.Sprintf("could not read private header filler: %v", err)}
|
||||
}
|
||||
return nil
|
||||
}
|
31
vendor/github.com/jcmturner/rpc/v2/ndr/pipe.go
generated
vendored
Normal file
31
vendor/github.com/jcmturner/rpc/v2/ndr/pipe.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func (dec *Decoder) fillPipe(v reflect.Value, tag reflect.StructTag) error {
|
||||
s, err := dec.readUint32() // read element count of first chunk
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a := reflect.MakeSlice(v.Type(), 0, 0)
|
||||
c := reflect.MakeSlice(v.Type(), int(s), int(s))
|
||||
for s != 0 {
|
||||
for i := 0; i < int(s); i++ {
|
||||
err := dec.fill(c.Index(i), tag, &[]deferedPtr{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fill element %d of pipe: %v", i, err)
|
||||
}
|
||||
}
|
||||
s, err = dec.readUint32() // read element count of first chunk
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a = reflect.AppendSlice(a, c)
|
||||
c = reflect.MakeSlice(v.Type(), int(s), int(s))
|
||||
}
|
||||
v.Set(a)
|
||||
return nil
|
||||
}
|
211
vendor/github.com/jcmturner/rpc/v2/ndr/primitives.go
generated
vendored
Normal file
211
vendor/github.com/jcmturner/rpc/v2/ndr/primitives.go
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Byte sizes of primitive types
|
||||
const (
|
||||
SizeBool = 1
|
||||
SizeChar = 1
|
||||
SizeUint8 = 1
|
||||
SizeUint16 = 2
|
||||
SizeUint32 = 4
|
||||
SizeUint64 = 8
|
||||
SizeEnum = 2
|
||||
SizeSingle = 4
|
||||
SizeDouble = 8
|
||||
SizePtr = 4
|
||||
)
|
||||
|
||||
// Bool is an NDR Boolean which is a logical quantity that assumes one of two values: TRUE or FALSE.
|
||||
// NDR represents a Boolean as one octet.
|
||||
// It represents a value of FALSE as a zero octet, an octet in which every bit is reset.
|
||||
// It represents a value of TRUE as a non-zero octet, an octet in which one or more bits are set.
|
||||
|
||||
// Char is an NDR character.
|
||||
// NDR represents a character as one octet.
|
||||
// Characters have two representation formats: ASCII and EBCDIC.
|
||||
|
||||
// USmall is an unsigned 8 bit integer
|
||||
|
||||
// UShort is an unsigned 16 bit integer
|
||||
|
||||
// ULong is an unsigned 32 bit integer
|
||||
|
||||
// UHyper is an unsigned 64 bit integer
|
||||
|
||||
// Small is an signed 8 bit integer
|
||||
|
||||
// Short is an signed 16 bit integer
|
||||
|
||||
// Long is an signed 32 bit integer
|
||||
|
||||
// Hyper is an signed 64 bit integer
|
||||
|
||||
// Enum is the NDR representation of enumerated types as signed short integers (2 octets)
|
||||
|
||||
// Single is an NDR defined single-precision floating-point data type
|
||||
|
||||
// Double is an NDR defined double-precision floating-point data type
|
||||
|
||||
// readBool reads a byte representing a boolean.
|
||||
// NDR represents a Boolean as one octet.
|
||||
// It represents a value of FALSE as a zero octet, an octet in which every bit is reset.
|
||||
// It represents a value of TRUE as a non-zero octet, an octet in which one or more bits are set.
|
||||
func (dec *Decoder) readBool() (bool, error) {
|
||||
i, err := dec.readUint8()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if i != 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// readChar reads bytes representing a 8bit ASCII integer cast to a rune.
|
||||
func (dec *Decoder) readChar() (rune, error) {
|
||||
var r rune
|
||||
a, err := dec.readUint8()
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
return rune(a), nil
|
||||
}
|
||||
|
||||
// readUint8 reads bytes representing a 8bit unsigned integer.
|
||||
func (dec *Decoder) readUint8() (uint8, error) {
|
||||
b, err := dec.r.ReadByte()
|
||||
if err != nil {
|
||||
return uint8(0), err
|
||||
}
|
||||
return uint8(b), nil
|
||||
}
|
||||
|
||||
// readUint16 reads bytes representing a 16bit unsigned integer.
|
||||
func (dec *Decoder) readUint16() (uint16, error) {
|
||||
dec.ensureAlignment(SizeUint16)
|
||||
b, err := dec.readBytes(SizeUint16)
|
||||
if err != nil {
|
||||
return uint16(0), err
|
||||
}
|
||||
return dec.ch.Endianness.Uint16(b), nil
|
||||
}
|
||||
|
||||
// readUint32 reads bytes representing a 32bit unsigned integer.
|
||||
func (dec *Decoder) readUint32() (uint32, error) {
|
||||
dec.ensureAlignment(SizeUint32)
|
||||
b, err := dec.readBytes(SizeUint32)
|
||||
if err != nil {
|
||||
return uint32(0), err
|
||||
}
|
||||
return dec.ch.Endianness.Uint32(b), nil
|
||||
}
|
||||
|
||||
// readUint32 reads bytes representing a 32bit unsigned integer.
|
||||
func (dec *Decoder) readUint64() (uint64, error) {
|
||||
dec.ensureAlignment(SizeUint64)
|
||||
b, err := dec.readBytes(SizeUint64)
|
||||
if err != nil {
|
||||
return uint64(0), err
|
||||
}
|
||||
return dec.ch.Endianness.Uint64(b), nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readInt8() (int8, error) {
|
||||
dec.ensureAlignment(SizeUint8)
|
||||
b, err := dec.readBytes(SizeUint8)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var i int8
|
||||
buf := bytes.NewReader(b)
|
||||
err = binary.Read(buf, dec.ch.Endianness, &i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readInt16() (int16, error) {
|
||||
dec.ensureAlignment(SizeUint16)
|
||||
b, err := dec.readBytes(SizeUint16)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var i int16
|
||||
buf := bytes.NewReader(b)
|
||||
err = binary.Read(buf, dec.ch.Endianness, &i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readInt32() (int32, error) {
|
||||
dec.ensureAlignment(SizeUint32)
|
||||
b, err := dec.readBytes(SizeUint32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var i int32
|
||||
buf := bytes.NewReader(b)
|
||||
err = binary.Read(buf, dec.ch.Endianness, &i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readInt64() (int64, error) {
|
||||
dec.ensureAlignment(SizeUint64)
|
||||
b, err := dec.readBytes(SizeUint64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var i int64
|
||||
buf := bytes.NewReader(b)
|
||||
err = binary.Read(buf, dec.ch.Endianness, &i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/IEEE_754-1985
|
||||
func (dec *Decoder) readFloat32() (f float32, err error) {
|
||||
dec.ensureAlignment(SizeSingle)
|
||||
b, err := dec.readBytes(SizeSingle)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bits := dec.ch.Endianness.Uint32(b)
|
||||
f = math.Float32frombits(bits)
|
||||
return
|
||||
}
|
||||
|
||||
func (dec *Decoder) readFloat64() (f float64, err error) {
|
||||
dec.ensureAlignment(SizeDouble)
|
||||
b, err := dec.readBytes(SizeDouble)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bits := dec.ch.Endianness.Uint64(b)
|
||||
f = math.Float64frombits(bits)
|
||||
return
|
||||
}
|
||||
|
||||
// NDR enforces NDR alignment of primitive data; that is, any primitive of size n octets is aligned at a octet stream
|
||||
// index that is a multiple of n. (In this version of NDR, n is one of {1, 2, 4, 8}.) An octet stream index indicates
|
||||
// the number of an octet in an octet stream when octets are numbered, beginning with 0, from the first octet in the
|
||||
// stream. Where necessary, an alignment gap, consisting of octets of unspecified value, precedes the representation
|
||||
// of a primitive. The gap is of the smallest size sufficient to align the primitive.
|
||||
func (dec *Decoder) ensureAlignment(n int) {
|
||||
p := dec.size - dec.r.Buffered()
|
||||
if s := p % n; s != 0 {
|
||||
dec.r.Discard(n - s)
|
||||
}
|
||||
}
|
61
vendor/github.com/jcmturner/rpc/v2/ndr/rawbytes.go
generated
vendored
Normal file
61
vendor/github.com/jcmturner/rpc/v2/ndr/rawbytes.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// type MyBytes []byte
|
||||
// implement RawBytes interface
|
||||
|
||||
const (
|
||||
sizeMethod = "Size"
|
||||
)
|
||||
|
||||
// RawBytes interface should be implemented if reading just a number of bytes from the NDR stream
|
||||
type RawBytes interface {
|
||||
Size(interface{}) int
|
||||
}
|
||||
|
||||
func rawBytesSize(parent reflect.Value, v reflect.Value) (int, error) {
|
||||
sf := v.MethodByName(sizeMethod)
|
||||
if !sf.IsValid() {
|
||||
return 0, fmt.Errorf("could not find a method called %s on the implementation of RawBytes", sizeMethod)
|
||||
}
|
||||
in := []reflect.Value{parent}
|
||||
f := sf.Call(in)
|
||||
if f[0].Kind() != reflect.Int {
|
||||
return 0, errors.New("the RawBytes size function did not return an integer")
|
||||
}
|
||||
return int(f[0].Int()), nil
|
||||
}
|
||||
|
||||
func addSizeToTag(parent reflect.Value, v reflect.Value, tag reflect.StructTag) (reflect.StructTag, error) {
|
||||
size, err := rawBytesSize(parent, v)
|
||||
if err != nil {
|
||||
return tag, err
|
||||
}
|
||||
ndrTag := parseTags(tag)
|
||||
ndrTag.Map["size"] = strconv.Itoa(size)
|
||||
return ndrTag.StructTag(), nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readRawBytes(v reflect.Value, tag reflect.StructTag) error {
|
||||
ndrTag := parseTags(tag)
|
||||
sizeStr, ok := ndrTag.Map["size"]
|
||||
if !ok {
|
||||
return errors.New("size tag not available")
|
||||
}
|
||||
size, err := strconv.Atoi(sizeStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("size not valid: %v", err)
|
||||
}
|
||||
b, err := dec.readBytes(size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Set(reflect.ValueOf(b).Convert(v.Type()))
|
||||
return nil
|
||||
}
|
70
vendor/github.com/jcmturner/rpc/v2/ndr/strings.go
generated
vendored
Normal file
70
vendor/github.com/jcmturner/rpc/v2/ndr/strings.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
const (
|
||||
subStringArrayTag = `ndr:"varying,X-subStringArray"`
|
||||
subStringArrayValue = "X-subStringArray"
|
||||
)
|
||||
|
||||
func uint16SliceToString(a []uint16) string {
|
||||
s := make([]rune, len(a), len(a))
|
||||
for i := range s {
|
||||
s[i] = rune(a[i])
|
||||
}
|
||||
if len(s) > 0 {
|
||||
// Remove any null terminator
|
||||
if s[len(s)-1] == rune(0) {
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
}
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (dec *Decoder) readVaryingString(def *[]deferedPtr) (string, error) {
|
||||
a := new([]uint16)
|
||||
v := reflect.ValueOf(a)
|
||||
var t reflect.StructTag
|
||||
err := dec.fillUniDimensionalVaryingArray(v.Elem(), t, def)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s := uint16SliceToString(*a)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readConformantVaryingString(def *[]deferedPtr) (string, error) {
|
||||
a := new([]uint16)
|
||||
v := reflect.ValueOf(a)
|
||||
var t reflect.StructTag
|
||||
err := dec.fillUniDimensionalConformantVaryingArray(v.Elem(), t, def)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s := uint16SliceToString(*a)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) readStringsArray(v reflect.Value, tag reflect.StructTag, def *[]deferedPtr) error {
|
||||
d, _ := sliceDimensions(v.Type())
|
||||
ndrTag := parseTags(tag)
|
||||
var m []int
|
||||
//var ms int
|
||||
if ndrTag.HasValue(TagConformant) {
|
||||
for i := 0; i < d; i++ {
|
||||
m = append(m, int(dec.precedingMax()))
|
||||
}
|
||||
//common max size
|
||||
_ = dec.precedingMax()
|
||||
//ms = int(n)
|
||||
}
|
||||
tag = reflect.StructTag(subStringArrayTag)
|
||||
err := dec.fillVaryingArray(v, tag, def)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read string array: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
69
vendor/github.com/jcmturner/rpc/v2/ndr/tags.go
generated
vendored
Normal file
69
vendor/github.com/jcmturner/rpc/v2/ndr/tags.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const ndrNameSpace = "ndr"
|
||||
|
||||
type tags struct {
|
||||
Values []string
|
||||
Map map[string]string
|
||||
}
|
||||
|
||||
// parse the struct field tags and extract the ndr related ones.
|
||||
// format of tag ndr:"value,key:value1,value2"
|
||||
func parseTags(st reflect.StructTag) tags {
|
||||
s := st.Get(ndrNameSpace)
|
||||
t := tags{
|
||||
Values: []string{},
|
||||
Map: make(map[string]string),
|
||||
}
|
||||
if s != "" {
|
||||
ndrTags := strings.Trim(s, `"`)
|
||||
for _, tag := range strings.Split(ndrTags, ",") {
|
||||
if strings.Contains(tag, ":") {
|
||||
m := strings.SplitN(tag, ":", 2)
|
||||
t.Map[m[0]] = m[1]
|
||||
} else {
|
||||
t.Values = append(t.Values, tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func appendTag(t reflect.StructTag, s string) reflect.StructTag {
|
||||
ts := t.Get(ndrNameSpace)
|
||||
ts = fmt.Sprintf(`%s"%s,%s"`, ndrNameSpace, ts, s)
|
||||
return reflect.StructTag(ts)
|
||||
}
|
||||
|
||||
func (t *tags) StructTag() reflect.StructTag {
|
||||
mv := t.Values
|
||||
for key, val := range t.Map {
|
||||
mv = append(mv, key+":"+val)
|
||||
}
|
||||
s := ndrNameSpace + ":" + `"` + strings.Join(mv, ",") + `"`
|
||||
return reflect.StructTag(s)
|
||||
}
|
||||
|
||||
func (t *tags) delete(s string) {
|
||||
for i, x := range t.Values {
|
||||
if x == s {
|
||||
t.Values = append(t.Values[:i], t.Values[i+1:]...)
|
||||
}
|
||||
}
|
||||
delete(t.Map, s)
|
||||
}
|
||||
|
||||
func (t *tags) HasValue(s string) bool {
|
||||
for _, v := range t.Values {
|
||||
if v == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
57
vendor/github.com/jcmturner/rpc/v2/ndr/union.go
generated
vendored
Normal file
57
vendor/github.com/jcmturner/rpc/v2/ndr/union.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
package ndr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Union interface must be implemented by structs that will be unmarshaled into from the NDR byte stream union representation.
|
||||
// The union's discriminating tag will be passed to the SwitchFunc method.
|
||||
// The discriminating tag field must have the struct tag: `ndr:"unionTag"`
|
||||
// If the union is encapsulated the discriminating tag field must have the struct tag: `ndr:"encapsulated"`
|
||||
// The possible value fields that can be selected from must have the struct tag: `ndr:"unionField"`
|
||||
type Union interface {
|
||||
SwitchFunc(t interface{}) string
|
||||
}
|
||||
|
||||
// Union related constants such as struct tag values
|
||||
const (
|
||||
unionSelectionFuncName = "SwitchFunc"
|
||||
TagEncapsulated = "encapsulated"
|
||||
TagUnionTag = "unionTag"
|
||||
TagUnionField = "unionField"
|
||||
)
|
||||
|
||||
func (dec *Decoder) isUnion(field reflect.Value, tag reflect.StructTag) (r reflect.Value) {
|
||||
ndrTag := parseTags(tag)
|
||||
if !ndrTag.HasValue(TagUnionTag) {
|
||||
return
|
||||
}
|
||||
r = field
|
||||
// For a non-encapsulated union, the discriminant is marshalled into the transmitted data stream twice: once as the
|
||||
// field or parameter, which is referenced by the switch_is construct, in the procedure argument list; and once as
|
||||
// the first part of the union representation.
|
||||
if !ndrTag.HasValue(TagEncapsulated) {
|
||||
dec.r.Discard(int(r.Type().Size()))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// unionSelectedField returns the field name of which of the union values to fill
|
||||
func unionSelectedField(union, discriminant reflect.Value) (string, error) {
|
||||
if !union.Type().Implements(reflect.TypeOf(new(Union)).Elem()) {
|
||||
return "", errors.New("struct does not implement union interface")
|
||||
}
|
||||
args := []reflect.Value{discriminant}
|
||||
// Call the SelectFunc of the union struct to find the name of the field to fill with the value selected.
|
||||
sf := union.MethodByName(unionSelectionFuncName)
|
||||
if !sf.IsValid() {
|
||||
return "", fmt.Errorf("could not find a selection function called %s in the unions struct representation", unionSelectionFuncName)
|
||||
}
|
||||
f := sf.Call(args)
|
||||
if f[0].Kind() != reflect.String || f[0].String() == "" {
|
||||
return "", fmt.Errorf("the union select function did not return a string for the name of the field to fill")
|
||||
}
|
||||
return f[0].String(), nil
|
||||
}
|
Reference in New Issue
Block a user