[VOL-1349] EPON ONU adapter (package B)
Change-Id: I609ba349c429bc7e87c74b66bb1121841f9caef6
diff --git a/vendor/gopkg.in/jcmturner/rpc.v1/ndr/arrays.go b/vendor/gopkg.in/jcmturner/rpc.v1/ndr/arrays.go
new file mode 100644
index 0000000..5e2def2
--- /dev/null
+++ b/vendor/gopkg.in/jcmturner/rpc.v1/ndr/arrays.go
@@ -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
+}