github.com/imran-kn/cilium-fork@v1.6.9/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 }