github.com/elfadel/cilium@v1.6.12/pkg/bpf/binary/binary.go (about)

     1  // Copyright 2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // Copyright (c) 2009 The Go Authors. All rights reserved.
    16  //
    17  // Redistribution and use in source and binary forms, with or without
    18  // modification, are permitted provided that the following conditions are
    19  // met:
    20  //
    21  //   * Redistributions of source code must retain the above copyright
    22  // notice, this list of conditions and the following disclaimer.
    23  //   * Redistributions in binary form must reproduce the above
    24  // copyright notice, this list of conditions and the following disclaimer
    25  // in the documentation and/or other materials provided with the
    26  // distribution.
    27  //   * Neither the name of Google Inc. nor the names of its
    28  // contributors may be used to endorse or promote products derived from
    29  // this software without specific prior written permission.
    30  //
    31  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    32  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    33  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    34  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    35  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    36  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    37  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    38  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    39  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    40  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    41  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    42  
    43  package binary
    44  
    45  import (
    46  	"encoding/binary"
    47  	"math"
    48  	"reflect"
    49  )
    50  
    51  type coder struct {
    52  	order  binary.ByteOrder
    53  	buf    []byte
    54  	offset int
    55  }
    56  
    57  type decoder coder
    58  
    59  func (d *decoder) bool() bool {
    60  	x := d.buf[d.offset]
    61  	d.offset++
    62  	return x != 0
    63  }
    64  
    65  func (d *decoder) uint8() uint8 {
    66  	x := d.buf[d.offset]
    67  	d.offset++
    68  	return x
    69  }
    70  
    71  func (d *decoder) uint16() uint16 {
    72  	x := d.order.Uint16(d.buf[d.offset : d.offset+2])
    73  	d.offset += 2
    74  	return x
    75  }
    76  
    77  func (d *decoder) uint32() uint32 {
    78  	x := d.order.Uint32(d.buf[d.offset : d.offset+4])
    79  	d.offset += 4
    80  	return x
    81  }
    82  
    83  func (d *decoder) uint64() uint64 {
    84  	x := d.order.Uint64(d.buf[d.offset : d.offset+8])
    85  	d.offset += 8
    86  	return x
    87  }
    88  
    89  func (d *decoder) skip(v reflect.Value) {
    90  	d.offset += dataSize(v)
    91  }
    92  
    93  // sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
    94  func sizeof(t reflect.Type) int {
    95  	switch t.Kind() {
    96  	case reflect.Array:
    97  		if s := sizeof(t.Elem()); s >= 0 {
    98  			return s * t.Len()
    99  		}
   100  
   101  	case reflect.Struct:
   102  		sum := 0
   103  		for i, n := 0, t.NumField(); i < n; i++ {
   104  			s := sizeof(t.Field(i).Type)
   105  			if s < 0 {
   106  				return -1
   107  			}
   108  			sum += s
   109  		}
   110  		return sum
   111  
   112  	case reflect.Bool,
   113  		reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
   114  		reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   115  		reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
   116  		return int(t.Size())
   117  	}
   118  
   119  	return -1
   120  }
   121  
   122  // dataSize returns the number of bytes the actual data represented by v occupies in memory.
   123  // For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
   124  // it returns the length of the slice times the element size and does not count the memory
   125  // occupied by the header. If the type of v is not acceptable, dataSize returns -1.
   126  func dataSize(v reflect.Value) int {
   127  	if v.Kind() == reflect.Slice {
   128  		if s := sizeof(v.Type().Elem()); s >= 0 {
   129  			return s * v.Len()
   130  		}
   131  		return -1
   132  	}
   133  	return sizeof(v.Type())
   134  }
   135  
   136  func (d *decoder) int8() int8 { return int8(d.uint8()) }
   137  
   138  func (d *decoder) int16() int16 { return int16(d.uint16()) }
   139  
   140  func (d *decoder) int32() int32 { return int32(d.uint32()) }
   141  
   142  func (d *decoder) int64() int64 { return int64(d.uint64()) }
   143  
   144  func (d *decoder) value(v reflect.Value) {
   145  	switch v.Kind() {
   146  	case reflect.Array:
   147  		l := v.Len()
   148  		for i := 0; i < l; i++ {
   149  			d.value(v.Index(i))
   150  		}
   151  
   152  	case reflect.Struct:
   153  		t := v.Type()
   154  		l := v.NumField()
   155  		for i := 0; i < l; i++ {
   156  			// Note: Calling v.CanSet() below is an optimization.
   157  			// It would be sufficient to check the field name,
   158  			// but creating the StructField info for each field is
   159  			// costly (run "go test -bench=ReadStruct" and compare
   160  			// results when making changes to this code).
   161  			if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
   162  				d.value(v)
   163  			} else {
   164  				d.skip(v)
   165  			}
   166  		}
   167  
   168  	case reflect.Slice:
   169  		l := v.Len()
   170  		for i := 0; i < l; i++ {
   171  			d.value(v.Index(i))
   172  		}
   173  
   174  	case reflect.Bool:
   175  		v.SetBool(d.bool())
   176  
   177  	case reflect.Int8:
   178  		v.SetInt(int64(d.int8()))
   179  	case reflect.Int16:
   180  		v.SetInt(int64(d.int16()))
   181  	case reflect.Int32:
   182  		v.SetInt(int64(d.int32()))
   183  	case reflect.Int64:
   184  		v.SetInt(d.int64())
   185  
   186  	case reflect.Uint8:
   187  		v.SetUint(uint64(d.uint8()))
   188  	case reflect.Uint16:
   189  		v.SetUint(uint64(d.uint16()))
   190  	case reflect.Uint32:
   191  		v.SetUint(uint64(d.uint32()))
   192  	case reflect.Uint64:
   193  		v.SetUint(d.uint64())
   194  
   195  	case reflect.Float32:
   196  		v.SetFloat(float64(math.Float32frombits(d.uint32())))
   197  	case reflect.Float64:
   198  		v.SetFloat(math.Float64frombits(d.uint64()))
   199  
   200  	case reflect.Complex64:
   201  		v.SetComplex(complex(
   202  			float64(math.Float32frombits(d.uint32())),
   203  			float64(math.Float32frombits(d.uint32())),
   204  		))
   205  	case reflect.Complex128:
   206  		v.SetComplex(complex(
   207  			math.Float64frombits(d.uint64()),
   208  			math.Float64frombits(d.uint64()),
   209  		))
   210  	}
   211  }
   212  
   213  // Read reads structured binary data from r into data.
   214  // Data must be a pointer to a fixed-size value or a slice
   215  // of fixed-size values.
   216  // Bytes read from r are decoded using the specified byte order
   217  // and written to successive fields of the data.
   218  // When decoding boolean values, a zero byte is decoded as false, and
   219  // any other non-zero byte is decoded as true.
   220  // When reading into structs, the field data for fields with
   221  // blank (_) field names is skipped; i.e., blank field names
   222  // may be used for padding.
   223  // When reading into a struct, all non-blank fields must be exported
   224  // or Read may panic.
   225  //
   226  // The error is EOF only if no bytes were read.
   227  // If an EOF happens after reading some but not all the bytes,
   228  // Read returns ErrUnexpectedEOF.
   229  // This Read function differs from the upstream encoding/binary.Read as it does
   230  // not requires the caller to setup a reader as well as this function does
   231  // not allocate any memory to read from the given slice of bytes.
   232  func Read(r []byte, order binary.ByteOrder, data interface{}) error {
   233  	// Fallback to reflect-based decoding.
   234  	v := reflect.ValueOf(data)
   235  	switch v.Kind() {
   236  	case reflect.Ptr:
   237  		v = v.Elem()
   238  	}
   239  	d := &decoder{order: order, buf: r}
   240  	d.value(v)
   241  	return nil
   242  }