github.com/cilium/cilium@v1.16.2/pkg/safeio/safeio.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package safeio
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  )
    10  
    11  // ErrLimitReached indicates that ReadAllLimit has
    12  // reached its limit before completing a full read
    13  // of the io.Reader.
    14  var ErrLimitReached = fmt.Errorf("read limit reached")
    15  
    16  // ByteSize expresses the size of bytes
    17  type ByteSize float64
    18  
    19  const (
    20  	_ = iota // ignore first value by assigning to blank identifier
    21  	// KB is a Kilobyte
    22  	KB ByteSize = 1 << (10 * iota)
    23  	// MB is a Megabyte
    24  	MB
    25  	// GB is a Gigabyte
    26  	GB
    27  	// TB is a Terabyte
    28  	TB
    29  	// PB is a Petabyte
    30  	PB
    31  	// EB is an Exabyte
    32  	EB
    33  	// ZB is a Zettabyte
    34  	ZB
    35  	// YB is a Yottabyte
    36  	YB
    37  )
    38  
    39  // String converts a ByteSize to a string
    40  func (b ByteSize) String() string {
    41  	switch {
    42  	case b >= YB:
    43  		return fmt.Sprintf("%.1fYB", b/YB)
    44  	case b >= ZB:
    45  		return fmt.Sprintf("%.1fZB", b/ZB)
    46  	case b >= EB:
    47  		return fmt.Sprintf("%.1fEB", b/EB)
    48  	case b >= PB:
    49  		return fmt.Sprintf("%.1fPB", b/PB)
    50  	case b >= TB:
    51  		return fmt.Sprintf("%.1fTB", b/TB)
    52  	case b >= GB:
    53  		return fmt.Sprintf("%.1fGB", b/GB)
    54  	case b >= MB:
    55  		return fmt.Sprintf("%.1fMB", b/MB)
    56  	case b >= KB:
    57  		return fmt.Sprintf("%.1fKB", b/KB)
    58  	}
    59  	return fmt.Sprintf("%.1fB", b)
    60  }
    61  
    62  // ReadAllLimit reads from r until an error, EOF, or after n bytes and returns
    63  // the data it read. A successful call returns err == nil, not err == EOF.
    64  // Because ReadAllLimit is defined to read from src until EOF it does not
    65  // treat an EOF from Read as an error to be reported. If the limit is reached
    66  // ReadAllLimit will return ErrLimitReached as an error.
    67  func ReadAllLimit(r io.Reader, n ByteSize) ([]byte, error) {
    68  	limit := int(n + 1)
    69  	buf, err := io.ReadAll(io.LimitReader(r, int64(limit)))
    70  	if err != nil {
    71  		return buf, err
    72  	}
    73  	if len(buf) >= limit {
    74  		return buf[:limit-1], ErrLimitReached
    75  	}
    76  	return buf, nil
    77  }