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 }