github.com/rootless-containers/rootlesskit/v2@v2.3.4/pkg/lowlevelmsgutil/lowlevelmsgutil.go (about)

     1  // Package lowlevelmsgutil provides utility for JSON message with uint32le header
     2  package lowlevelmsgutil
     3  
     4  import (
     5  	"bytes"
     6  	"encoding/binary"
     7  	"encoding/json"
     8  	"fmt"
     9  	"io"
    10  )
    11  
    12  const (
    13  	maxLength = 1 << 16
    14  )
    15  
    16  func MarshalToWriter(w io.Writer, x interface{}) (int, error) {
    17  	b, err := json.Marshal(x)
    18  	if err != nil {
    19  		return 0, err
    20  	}
    21  	if len(b) > maxLength {
    22  		return 0, fmt.Errorf("bad message length: %d (max: %d)", len(b), maxLength)
    23  	}
    24  	h := make([]byte, 4)
    25  	binary.LittleEndian.PutUint32(h, uint32(len(b)))
    26  	return w.Write(append(h, b...))
    27  }
    28  
    29  func UnmarshalFromReader(r io.Reader, x interface{}) (int, error) {
    30  	hdr := make([]byte, 4)
    31  	n, err := r.Read(hdr)
    32  	if err != nil {
    33  		return n, err
    34  	}
    35  	if n != 4 {
    36  		return n, fmt.Errorf("read %d bytes, expected 4 bytes", n)
    37  	}
    38  	bLen := binary.LittleEndian.Uint32(hdr)
    39  	if bLen > maxLength || bLen < 1 {
    40  		return n, fmt.Errorf("bad message length: %d (max: %d)", bLen, maxLength)
    41  	}
    42  	b := make([]byte, bLen)
    43  	n, err = r.Read(b)
    44  	if err != nil {
    45  		return 4 + n, err
    46  	}
    47  	if n != int(bLen) {
    48  		return 4 + n, fmt.Errorf("read %d bytes, expected %d bytes", n, bLen)
    49  	}
    50  	return 4 + n, json.Unmarshal(b, x)
    51  }
    52  
    53  func Marshal(x interface{}) ([]byte, error) {
    54  	var b bytes.Buffer
    55  	_, err := MarshalToWriter(&b, x)
    56  	return b.Bytes(), err
    57  }
    58  
    59  func Unmarshal(b []byte, x interface{}) error {
    60  	n, err := UnmarshalFromReader(bytes.NewReader(b), x)
    61  	if n != len(b) {
    62  		return fmt.Errorf("read %d bytes, expected %d bytes", n, len(b))
    63  	}
    64  	return err
    65  }