github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/binary/binary.go (about) 1 // Copyright 2018 The gVisor Authors. 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 // Package binary translates between select fixed-sized types and a binary 16 // representation. 17 package binary 18 19 import ( 20 "encoding/binary" 21 "fmt" 22 "io" 23 "reflect" 24 ) 25 26 // LittleEndian is the same as encoding/binary.LittleEndian. 27 // 28 // It is included here as a convenience. 29 var LittleEndian = binary.LittleEndian 30 31 // BigEndian is the same as encoding/binary.BigEndian. 32 // 33 // It is included here as a convenience. 34 var BigEndian = binary.BigEndian 35 36 // AppendUint16 appends the binary representation of a uint16 to buf. 37 func AppendUint16(buf []byte, order binary.ByteOrder, num uint16) []byte { 38 buf = append(buf, make([]byte, 2)...) 39 order.PutUint16(buf[len(buf)-2:], num) 40 return buf 41 } 42 43 // AppendUint32 appends the binary representation of a uint32 to buf. 44 func AppendUint32(buf []byte, order binary.ByteOrder, num uint32) []byte { 45 buf = append(buf, make([]byte, 4)...) 46 order.PutUint32(buf[len(buf)-4:], num) 47 return buf 48 } 49 50 // AppendUint64 appends the binary representation of a uint64 to buf. 51 func AppendUint64(buf []byte, order binary.ByteOrder, num uint64) []byte { 52 buf = append(buf, make([]byte, 8)...) 53 order.PutUint64(buf[len(buf)-8:], num) 54 return buf 55 } 56 57 // Marshal appends a binary representation of data to buf. 58 // 59 // data must only contain fixed-length signed and unsigned ints, arrays, 60 // slices, structs and compositions of said types. data may be a pointer, 61 // but cannot contain pointers. 62 func Marshal(buf []byte, order binary.ByteOrder, data any) []byte { 63 return marshal(buf, order, reflect.Indirect(reflect.ValueOf(data))) 64 } 65 66 func marshal(buf []byte, order binary.ByteOrder, data reflect.Value) []byte { 67 switch data.Kind() { 68 case reflect.Int8: 69 buf = append(buf, byte(int8(data.Int()))) 70 case reflect.Int16: 71 buf = AppendUint16(buf, order, uint16(int16(data.Int()))) 72 case reflect.Int32: 73 buf = AppendUint32(buf, order, uint32(int32(data.Int()))) 74 case reflect.Int64: 75 buf = AppendUint64(buf, order, uint64(data.Int())) 76 77 case reflect.Uint8: 78 buf = append(buf, byte(data.Uint())) 79 case reflect.Uint16: 80 buf = AppendUint16(buf, order, uint16(data.Uint())) 81 case reflect.Uint32: 82 buf = AppendUint32(buf, order, uint32(data.Uint())) 83 case reflect.Uint64: 84 buf = AppendUint64(buf, order, data.Uint()) 85 86 case reflect.Array, reflect.Slice: 87 for i, l := 0, data.Len(); i < l; i++ { 88 buf = marshal(buf, order, data.Index(i)) 89 } 90 91 case reflect.Struct: 92 for i, l := 0, data.NumField(); i < l; i++ { 93 buf = marshal(buf, order, data.Field(i)) 94 } 95 96 default: 97 panic("invalid type: " + data.Type().String()) 98 } 99 return buf 100 } 101 102 // Unmarshal unpacks buf into data. 103 // 104 // data must be a slice or a pointer and buf must have a length of exactly 105 // Size(data). data must only contain fixed-length signed and unsigned ints, 106 // arrays, slices, structs and compositions of said types. 107 func Unmarshal(buf []byte, order binary.ByteOrder, data any) { 108 value := reflect.ValueOf(data) 109 switch value.Kind() { 110 case reflect.Ptr: 111 value = value.Elem() 112 case reflect.Slice: 113 default: 114 panic("invalid type: " + value.Type().String()) 115 } 116 buf = unmarshal(buf, order, value) 117 if len(buf) != 0 { 118 panic(fmt.Sprintf("buffer too long by %d bytes", len(buf))) 119 } 120 } 121 122 func unmarshal(buf []byte, order binary.ByteOrder, data reflect.Value) []byte { 123 switch data.Kind() { 124 case reflect.Int8: 125 data.SetInt(int64(int8(buf[0]))) 126 buf = buf[1:] 127 case reflect.Int16: 128 data.SetInt(int64(int16(order.Uint16(buf)))) 129 buf = buf[2:] 130 case reflect.Int32: 131 data.SetInt(int64(int32(order.Uint32(buf)))) 132 buf = buf[4:] 133 case reflect.Int64: 134 data.SetInt(int64(order.Uint64(buf))) 135 buf = buf[8:] 136 137 case reflect.Uint8: 138 data.SetUint(uint64(buf[0])) 139 buf = buf[1:] 140 case reflect.Uint16: 141 data.SetUint(uint64(order.Uint16(buf))) 142 buf = buf[2:] 143 case reflect.Uint32: 144 data.SetUint(uint64(order.Uint32(buf))) 145 buf = buf[4:] 146 case reflect.Uint64: 147 data.SetUint(order.Uint64(buf)) 148 buf = buf[8:] 149 150 case reflect.Array, reflect.Slice: 151 for i, l := 0, data.Len(); i < l; i++ { 152 buf = unmarshal(buf, order, data.Index(i)) 153 } 154 155 case reflect.Struct: 156 for i, l := 0, data.NumField(); i < l; i++ { 157 if field := data.Field(i); field.CanSet() { 158 buf = unmarshal(buf, order, field) 159 } else { 160 buf = buf[sizeof(field):] 161 } 162 } 163 164 default: 165 panic("invalid type: " + data.Type().String()) 166 } 167 return buf 168 } 169 170 // Size calculates the buffer sized needed by Marshal or Unmarshal. 171 // 172 // Size only support the types supported by Marshal. 173 func Size(v any) uintptr { 174 return sizeof(reflect.Indirect(reflect.ValueOf(v))) 175 } 176 177 func sizeof(data reflect.Value) uintptr { 178 switch data.Kind() { 179 case reflect.Int8, reflect.Uint8: 180 return 1 181 case reflect.Int16, reflect.Uint16: 182 return 2 183 case reflect.Int32, reflect.Uint32: 184 return 4 185 case reflect.Int64, reflect.Uint64: 186 return 8 187 188 case reflect.Array, reflect.Slice: 189 var size uintptr 190 for i, l := 0, data.Len(); i < l; i++ { 191 size += sizeof(data.Index(i)) 192 } 193 return size 194 195 case reflect.Struct: 196 var size uintptr 197 for i, l := 0, data.NumField(); i < l; i++ { 198 size += sizeof(data.Field(i)) 199 } 200 return size 201 202 default: 203 panic("invalid type: " + data.Type().String()) 204 } 205 } 206 207 // ReadUint16 reads a uint16 from r. 208 func ReadUint16(r io.Reader, order binary.ByteOrder) (uint16, error) { 209 buf := make([]byte, 2) 210 if _, err := io.ReadFull(r, buf); err != nil { 211 return 0, err 212 } 213 return order.Uint16(buf), nil 214 } 215 216 // ReadUint32 reads a uint32 from r. 217 func ReadUint32(r io.Reader, order binary.ByteOrder) (uint32, error) { 218 buf := make([]byte, 4) 219 if _, err := io.ReadFull(r, buf); err != nil { 220 return 0, err 221 } 222 return order.Uint32(buf), nil 223 } 224 225 // ReadUint64 reads a uint64 from r. 226 func ReadUint64(r io.Reader, order binary.ByteOrder) (uint64, error) { 227 buf := make([]byte, 8) 228 if _, err := io.ReadFull(r, buf); err != nil { 229 return 0, err 230 } 231 return order.Uint64(buf), nil 232 } 233 234 // WriteUint16 writes a uint16 to w. 235 func WriteUint16(w io.Writer, order binary.ByteOrder, num uint16) error { 236 buf := make([]byte, 2) 237 order.PutUint16(buf, num) 238 _, err := w.Write(buf) 239 return err 240 } 241 242 // WriteUint32 writes a uint32 to w. 243 func WriteUint32(w io.Writer, order binary.ByteOrder, num uint32) error { 244 buf := make([]byte, 4) 245 order.PutUint32(buf, num) 246 _, err := w.Write(buf) 247 return err 248 } 249 250 // WriteUint64 writes a uint64 to w. 251 func WriteUint64(w io.Writer, order binary.ByteOrder, num uint64) error { 252 buf := make([]byte, 8) 253 order.PutUint64(buf, num) 254 _, err := w.Write(buf) 255 return err 256 } 257 258 // AlignUp rounds a length up to an alignment. align must be a power of 2. 259 func AlignUp(length int, align uint) int { 260 return (length + int(align) - 1) & ^(int(align) - 1) 261 } 262 263 // AlignDown rounds a length down to an alignment. align must be a power of 2. 264 func AlignDown(length int, align uint) int { 265 return length & ^(int(align) - 1) 266 }