gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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  }