├── LICENSE ├── README.md ├── bytesize.go └── bytesize_test.go /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2017, Zack Patrick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go Bytesize 2 | 3 | [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/zpatrick/go-bytesize/blob/master/LICENSE) 4 | [![Go Report Card](https://goreportcard.com/badge/github.com/zpatrick/go-bytesize)](https://goreportcard.com/report/github.com/zpatrick/go-bytesize) 5 | [![Go Doc](https://godoc.org/github.com/zpatrick/go-bytesize?status.svg)](https://godoc.org/github.com/zpatrick/go-bytesize) 6 | 7 | 8 | ## Overview 9 | Go Bytesize is a utility package for working with common multiples of bytes in Go, such as: Bytes (B), Kilobytes (KB), Megabytes (MB), Gigabytes (GB), Terabytes (TB), Petabytes (PB), Exabytes (EB), Kibibytes (Kib), Mebibytes (MiB), Gibibytes (GiB), Tebibytes (TiB), Pebibytes (PiB), and Exbibytes (EiB). 10 | 11 | ## Example 12 | ``` 13 | package main 14 | 15 | import ( 16 | "fmt" 17 | "github.com/zpatrick/go-bytesize" 18 | ) 19 | 20 | func main() { 21 | b := bytesize.Bytesize(10000) 22 | fmt.Printf("%g bytes is: %g KB and %g MB\n", b, b.Kilobytes(), b.Megabytes()) 23 | 24 | b = bytesize.TB * 2 25 | fmt.Printf("2 Terabytes is %g Gibibytes\n", b.Gibibytes()) 26 | 27 | b = bytesize.Bytesize(1000000) 28 | fmt.Printf("%g bytes is %s\n", b, b.Format("mb")) 29 | } 30 | ``` 31 | 32 | Output: 33 | ``` 34 | 10000 bytes is: 10 KB and 0.01 MB 35 | 2 Terabytes is 1862.645149230957 Gibibytes 36 | 1e+06 bytes is 1MB 37 | ``` 38 | 39 | ## License 40 | This work is published under the MIT license. 41 | Please see the `LICENSE` file for details. 42 | -------------------------------------------------------------------------------- /bytesize.go: -------------------------------------------------------------------------------- 1 | package bytesize 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // A Bytesize represents a single byte as a float64 9 | type Bytesize float64 10 | 11 | // bytes sizes generally used for computer storage and memory 12 | const ( 13 | B Bytesize = 1 14 | KB Bytesize = 1000 * B 15 | MB Bytesize = 1000 * KB 16 | GB Bytesize = 1000 * MB 17 | TB Bytesize = 1000 * GB 18 | PB Bytesize = 1000 * TB 19 | EB Bytesize = 1000 * PB 20 | 21 | KiB Bytesize = 1024 * B 22 | MiB Bytesize = 1024 * KiB 23 | GiB Bytesize = 1024 * MiB 24 | TiB Bytesize = 1024 * GiB 25 | PiB Bytesize = 1024 * TiB 26 | EiB Bytesize = 1024 * PiB 27 | ) 28 | 29 | // Bytes returns the number of Bytes (B) in b 30 | func (b Bytesize) Bytes() float64 { 31 | return float64(b) 32 | } 33 | 34 | // Kilobytes returns the number of Kilobytes (KB) in b 35 | func (b Bytesize) Kilobytes() float64 { 36 | return float64(b / KB) 37 | } 38 | 39 | // Megabytes returns the number of Megabytes (MB) in b 40 | func (b Bytesize) Megabytes() float64 { 41 | return float64(b / MB) 42 | } 43 | 44 | // Gigabytes returns the number of Gigabytes (GB) in b 45 | func (b Bytesize) Gigabytes() float64 { 46 | return float64(b / GB) 47 | } 48 | 49 | // Terabytes returns the number of Terabytes (TB) in b 50 | func (b Bytesize) Terabytes() float64 { 51 | return float64(b / TB) 52 | } 53 | 54 | // Petabytes returns the number of Petabytes (PB) in b 55 | func (b Bytesize) Petabytes() float64 { 56 | return float64(b / PB) 57 | } 58 | 59 | // Exabytes returns the number of Exabytes (EB) in b 60 | func (b Bytesize) Exabytes() float64 { 61 | return float64(b / EB) 62 | } 63 | 64 | // Kibibytes returns the number of Kibibytes (KiB) in b 65 | func (b Bytesize) Kibibytes() float64 { 66 | return float64(b / KiB) 67 | } 68 | 69 | // Mebibytes returns the number of Mebibbytes (MiB) in b 70 | func (b Bytesize) Mebibytes() float64 { 71 | return float64(b / MiB) 72 | } 73 | 74 | // Gibibytes returns the number of Gibibytes (GiB) in b 75 | func (b Bytesize) Gibibytes() float64 { 76 | return float64(b / GiB) 77 | } 78 | 79 | // Tebibytes returns the number of Tebibytes (TiB) in b 80 | func (b Bytesize) Tebibytes() float64 { 81 | return float64(b / TiB) 82 | } 83 | 84 | // Pebibytes returns the number of Pebibytes (PiB) in b 85 | func (b Bytesize) Pebibytes() float64 { 86 | return float64(b / PiB) 87 | } 88 | 89 | // Exbibytes returns the number of Exbibytes (EiB) in b 90 | func (b Bytesize) Exbibytes() float64 { 91 | return float64(b / EiB) 92 | } 93 | 94 | // Format returns a textual representation of the Bytesize value formatted 95 | // according to layout, which defines the format by specifying an abbreviation. 96 | // Abbreviations are not case-sensitive. 97 | // 98 | // Valid abbreviations are as follows: 99 | // B (Bytesizes) 100 | // KB (Kilobytes) 101 | // MB (Megabytes) 102 | // GB (Gigabytes) 103 | // TB (Terabytes) 104 | // PB (Petabytes) 105 | // EB (Exabytes) 106 | // KiB (Kibibytes) 107 | // MiB (Mebibytes) 108 | // GiB (Gibibytes) 109 | // TiB (Tebibtyes) 110 | // PiB (Pebibytes) 111 | // EiB (Exbibyte) 112 | func (b Bytesize) Format(layout string) string { 113 | switch strings.ToLower(layout) { 114 | case "b": 115 | return fmt.Sprintf("%gB", b.Bytes()) 116 | case "kb": 117 | return fmt.Sprintf("%gKB", b.Kilobytes()) 118 | case "mb": 119 | return fmt.Sprintf("%gMB", b.Megabytes()) 120 | case "gb": 121 | return fmt.Sprintf("%gGB", b.Gigabytes()) 122 | case "tb": 123 | return fmt.Sprintf("%gTB", b.Terabytes()) 124 | case "pb": 125 | return fmt.Sprintf("%gPB", b.Petabytes()) 126 | case "eb": 127 | return fmt.Sprintf("%gEB", b.Exabytes()) 128 | case "kib": 129 | return fmt.Sprintf("%gKiB", b.Kibibytes()) 130 | case "mib": 131 | return fmt.Sprintf("%gMiB", b.Mebibytes()) 132 | case "gib": 133 | return fmt.Sprintf("%gGiB", b.Gibibytes()) 134 | case "tib": 135 | return fmt.Sprintf("%gTiB", b.Tebibytes()) 136 | case "pib": 137 | return fmt.Sprintf("%gPiB", b.Pebibytes()) 138 | case "eib": 139 | return fmt.Sprintf("%gEiB", b.Exbibytes()) 140 | default: 141 | return fmt.Sprintf("%%!%s(byte=%g)", layout, b) 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /bytesize_test.go: -------------------------------------------------------------------------------- 1 | package bytesize 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | const MAX_INT64 = 9223372036854775807 11 | 12 | func init() { 13 | rand.Seed(time.Now().Unix()) 14 | } 15 | 16 | func TestBytesizeConversions(t *testing.T) { 17 | for i := 0; i < 1000; i++ { 18 | b := Bytesize(rand.Int63n(MAX_INT64)) 19 | t.Logf("Testing %f", b) 20 | 21 | if r, e := b.Bytes(), float64(b); r != e { 22 | t.Errorf("Bytes %f: result %f, expected %f", b, r, e) 23 | } 24 | 25 | if r, e := b.Kilobytes(), float64(b/KB); r != e { 26 | t.Errorf("Kilobytes %f: result %f, expected %f", b, r, e) 27 | } 28 | 29 | if r, e := b.Megabytes(), float64(b/MB); r != e { 30 | t.Errorf("Megabytes %f: result %f, expected %f", b, r, e) 31 | } 32 | 33 | if r, e := b.Gigabytes(), float64(b/GB); r != e { 34 | t.Errorf("Gigabytes %f: result %f, expected %f", b, r, e) 35 | } 36 | 37 | if r, e := b.Terabytes(), float64(b/TB); r != e { 38 | t.Errorf("Terabytes %f: result %f, expected %f", b, r, e) 39 | } 40 | 41 | if r, e := b.Petabytes(), float64(b/PB); r != e { 42 | t.Errorf("Petabytes %f: result %f, expected %f", b, r, e) 43 | } 44 | 45 | if r, e := b.Exabytes(), float64(b/EB); r != e { 46 | t.Errorf("Exabytes %f: result %f, expected %f", b, r, e) 47 | } 48 | 49 | if r, e := b.Kibibytes(), float64(b/KiB); r != e { 50 | t.Errorf("Kibibytes %f: result %f, expected %f", b, r, e) 51 | } 52 | 53 | if r, e := b.Mebibytes(), float64(b/MiB); r != e { 54 | t.Errorf("Mebibytes %f: result %f, expected %f", b, r, e) 55 | } 56 | 57 | if r, e := b.Gibibytes(), float64(b/GiB); r != e { 58 | t.Errorf("Gibibytes %f: result %f, expected %f", b, r, e) 59 | } 60 | 61 | if r, e := b.Tebibytes(), float64(b/TiB); r != e { 62 | t.Errorf("Tebibytes %f: result %f, expected %f", b, r, e) 63 | } 64 | 65 | if r, e := b.Pebibytes(), float64(b/PiB); r != e { 66 | t.Errorf("Pebibytes %f: result %f, expected %f", b, r, e) 67 | } 68 | 69 | if r, e := b.Exbibytes(), float64(b/EiB); r != e { 70 | t.Errorf("Exbibytes %f: result %f, expected %f", b, r, e) 71 | } 72 | } 73 | } 74 | 75 | func TestBytesizeConstants(t *testing.T) { 76 | constants := map[string]struct { 77 | Constant Bytesize 78 | Expected Bytesize 79 | }{ 80 | "B": {B, 1}, 81 | "KB": {KB, 1000}, 82 | "MB": {MB, 1000000}, 83 | "GB": {GB, 1000000000}, 84 | "TB": {TB, 1000000000000}, 85 | "PB": {PB, 1000000000000000}, 86 | "EB": {EB, 1000000000000000000}, 87 | "KiB": {KiB, 1024}, 88 | "MiB": {MiB, 1048576}, 89 | "GiB": {GiB, 1073741824}, 90 | "TiB": {TiB, 1099511627776}, 91 | "PiB": {PiB, 1125899906842624}, 92 | "EiB": {EiB, 1152921504606846976}, 93 | } 94 | 95 | for abbreviation, s := range constants { 96 | if s.Constant != s.Expected { 97 | t.Errorf("%s: result %f, expected %f", abbreviation, s.Constant, s.Expected) 98 | } 99 | } 100 | } 101 | 102 | func Example() { 103 | b := Bytesize(10000) 104 | fmt.Printf("%g bytes is: %g KB and %g MB\n", b, b.Kilobytes(), b.Megabytes()) 105 | 106 | // Output: 107 | // 10000 bytes is: 10 KB and 0.01 MB 108 | } 109 | 110 | func ExampleBytesize_Format() { 111 | b := Bytesize(100000) 112 | fmt.Println(b.Format("b")) 113 | fmt.Println(b.Format("kb")) 114 | fmt.Println(b.Format("gb")) 115 | fmt.Println(b.Format("tb")) 116 | fmt.Println(b.Format("pb")) 117 | fmt.Println(b.Format("eb")) 118 | fmt.Println(b.Format("kib")) 119 | fmt.Println(b.Format("gib")) 120 | fmt.Println(b.Format("tib")) 121 | fmt.Println(b.Format("pib")) 122 | fmt.Println(b.Format("eib")) 123 | 124 | // Output: 125 | // 100000B 126 | // 100KB 127 | // 0.0001GB 128 | // 1e-07TB 129 | // 1e-10PB 130 | // 1e-13EB 131 | // 97.65625KiB 132 | // 9.313225746154785e-05GiB 133 | // 9.094947017729282e-08TiB 134 | // 8.881784197001252e-11PiB 135 | // 8.673617379884035e-14EiB 136 | } 137 | --------------------------------------------------------------------------------