Skip to content

Commit e0199ca

Browse files
MD-Mushfiqur123god032396-del
authored andcommitted
refactor: replace interface{} with any (Go 1.18+)
Signed-off-by: god032396-del <god032396@gmail.com>
0 parents  commit e0199ca

23 files changed

Lines changed: 2381 additions & 0 deletions

.github/workflows/gommon.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Run Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
paths:
8+
- '**.go'
9+
- 'go.*'
10+
- '_fixture/**'
11+
- '.github/**'
12+
- 'codecov.yml'
13+
pull_request:
14+
branches:
15+
- master
16+
paths:
17+
- '**.go'
18+
- 'go.*'
19+
- '_fixture/**'
20+
- '.github/**'
21+
- 'codecov.yml'
22+
workflow_dispatch:
23+
24+
env:
25+
# run static analysis only with the latest Go version
26+
LATEST_GO_VERSION: "1.26"
27+
28+
jobs:
29+
test:
30+
strategy:
31+
matrix:
32+
os: [ubuntu-latest, macos-latest, windows-latest]
33+
# Each major Go release is supported until there are two newer major releases. https://golang.org/doc/devel/release.html#policy
34+
# Matches the go directive floor in go.mod.
35+
go: ["1.23","1.24","1.25","1.26"]
36+
name: ${{ matrix.os }} @ Go ${{ matrix.go }}
37+
runs-on: ${{ matrix.os }}
38+
steps:
39+
- name: Set up Go ${{ matrix.go }}
40+
uses: actions/setup-go@v4
41+
with:
42+
go-version: ${{ matrix.go }}
43+
44+
- name: Checkout Code
45+
uses: actions/checkout@v4
46+
with:
47+
ref: ${{ github.ref }}
48+
49+
- name: Run Tests
50+
run: |
51+
go test -race --coverprofile=coverage.coverprofile --covermode=atomic ./...
52+
53+
- name: Upload coverage to Codecov
54+
if: success() && matrix.go == env.LATEST_GO_VERSION && matrix.os == 'ubuntu-latest'
55+
uses: codecov/codecov-action@v3
56+
with:
57+
fail_ci_if_error: false

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
coverage.txt
3+
_test
4+
vendor
5+
.idea
6+
*.iml
7+
*.out
8+
.vscode

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2018 labstack
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 all
13+
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 THE
21+
SOFTWARE.
22+

Makefile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
PKG := "github.com/labstack/gommon"
2+
PKG_LIST := $(shell go list ${PKG}/...)
3+
4+
.DEFAULT_GOAL := check
5+
check: lint vet race ## Check project
6+
7+
init:
8+
@go install golang.org/x/lint/golint@latest
9+
10+
lint: ## Lint the files
11+
@golint -set_exit_status ${PKG_LIST}
12+
13+
vet: ## Vet the files
14+
@go vet ${PKG_LIST}
15+
16+
test: ## Run tests
17+
@go test -short ${PKG_LIST}
18+
19+
race: ## Run tests with data race detector
20+
@go test -race ${PKG_LIST}
21+
22+
benchmark: ## Run benchmarks
23+
@go test -run="-" -bench=".*" ${PKG_LIST}
24+
25+
help: ## Display this help screen
26+
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
27+
28+
goversion ?= "1.20"
29+
test_version: ## Run tests inside Docker with given version (defaults to 1.20). Example: make test_version goversion=1.20
30+
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Gommon [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/labstack/gommon) [![Coverage Status](http://img.shields.io/coveralls/labstack/gommon.svg?style=flat-square)](https://coveralls.io/r/labstack/gommon)
2+
3+
Common packages for Go.
4+
5+
Requires Go 1.23 or later.
6+
7+
- [Bytes](https://github.com/labstack/gommon/tree/master/bytes) — format/parse byte sizes (binary IEC and decimal SI).
8+
- [Color](https://github.com/labstack/gommon/tree/master/color) — style terminal text.
9+
- [Email](https://github.com/labstack/gommon/tree/master/email) — send email over SMTP; supports STARTTLS and implicit TLS (SMTPS, port 465).
10+
- [Log](https://github.com/labstack/gommon/tree/master/log) — simple leveled logger with text and JSON output.
11+
- [Random](https://github.com/labstack/gommon/tree/master/random) — cryptographically secure random strings over configurable charsets.
12+
13+
## Install
14+
15+
```sh
16+
go get github.com/labstack/gommon
17+
```

bytes/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Bytes
2+
3+
- Format bytes integer to human readable bytes string.
4+
- Parse human readable bytes string to bytes integer.
5+
6+
## Installation
7+
8+
```go
9+
go get github.com/labstack/gommon/bytes
10+
```
11+
12+
## [Usage](https://github.com/labstack/gommon/blob/master/bytes/bytes_test.go)
13+
14+
### Format
15+
16+
```go
17+
println(bytes.Format(13231323))
18+
```
19+
20+
`12.62MB`
21+
22+
### Parse
23+
24+
```go
25+
b, _ = Parse("2M")
26+
println(b)
27+
```
28+
29+
`2097152`

bytes/bytes.go

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package bytes
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strconv"
7+
"strings"
8+
)
9+
10+
type (
11+
// Bytes struct
12+
Bytes struct{}
13+
)
14+
15+
// binary units (IEC 60027)
16+
const (
17+
_ = 1.0 << (10 * iota) // ignore first value by assigning to blank identifier
18+
KiB
19+
MiB
20+
GiB
21+
TiB
22+
PiB
23+
EiB
24+
)
25+
26+
// decimal units (SI international system of units)
27+
const (
28+
KB = 1000
29+
MB = KB * 1000
30+
GB = MB * 1000
31+
TB = GB * 1000
32+
PB = TB * 1000
33+
EB = PB * 1000
34+
)
35+
36+
var (
37+
patternBinary = regexp.MustCompile(`(?i)^(-?\d+(?:\.\d+)?)\s?([KMGTPE]iB?)$`)
38+
patternDecimal = regexp.MustCompile(`(?i)^(-?\d+(?:\.\d+)?)\s?([KMGTPE]B?|B?)$`)
39+
global = New()
40+
)
41+
42+
// New creates a Bytes instance.
43+
func New() *Bytes {
44+
return &Bytes{}
45+
}
46+
47+
// Format formats bytes integer to human readable string according to IEC 60027.
48+
// For example, 31323 bytes will return 30.59KB.
49+
func (b *Bytes) Format(value int64) string {
50+
return b.FormatBinary(value)
51+
}
52+
53+
// FormatBinary formats bytes integer to human readable string according to IEC 60027.
54+
// For example, 31323 bytes will return 30.59KB.
55+
func (*Bytes) FormatBinary(value int64) string {
56+
multiple := ""
57+
val := float64(value)
58+
59+
switch {
60+
case value >= EiB:
61+
val /= EiB
62+
multiple = "EiB"
63+
case value >= PiB:
64+
val /= PiB
65+
multiple = "PiB"
66+
case value >= TiB:
67+
val /= TiB
68+
multiple = "TiB"
69+
case value >= GiB:
70+
val /= GiB
71+
multiple = "GiB"
72+
case value >= MiB:
73+
val /= MiB
74+
multiple = "MiB"
75+
case value >= KiB:
76+
val /= KiB
77+
multiple = "KiB"
78+
case value == 0:
79+
return "0"
80+
default:
81+
return strconv.FormatInt(value, 10) + "B"
82+
}
83+
84+
return fmt.Sprintf("%.2f%s", val, multiple)
85+
}
86+
87+
// FormatDecimal formats bytes integer to human readable string according to SI international system of units.
88+
// For example, 31323 bytes will return 31.32KB.
89+
func (*Bytes) FormatDecimal(value int64) string {
90+
multiple := ""
91+
val := float64(value)
92+
93+
switch {
94+
case value >= EB:
95+
val /= EB
96+
multiple = "EB"
97+
case value >= PB:
98+
val /= PB
99+
multiple = "PB"
100+
case value >= TB:
101+
val /= TB
102+
multiple = "TB"
103+
case value >= GB:
104+
val /= GB
105+
multiple = "GB"
106+
case value >= MB:
107+
val /= MB
108+
multiple = "MB"
109+
case value >= KB:
110+
val /= KB
111+
multiple = "KB"
112+
case value == 0:
113+
return "0"
114+
default:
115+
return strconv.FormatInt(value, 10) + "B"
116+
}
117+
118+
return fmt.Sprintf("%.2f%s", val, multiple)
119+
}
120+
121+
// Parse parses human readable bytes string to bytes integer.
122+
// For example, 6GiB (6Gi is also valid) will return 6442450944, and
123+
// 6GB (6G is also valid) will return 6000000000.
124+
func (b *Bytes) Parse(value string) (int64, error) {
125+
126+
i, err := b.ParseBinary(value)
127+
if err == nil {
128+
return i, err
129+
}
130+
131+
return b.ParseDecimal(value)
132+
}
133+
134+
// ParseBinary parses human readable bytes string to bytes integer.
135+
// For example, 6GiB (6Gi is also valid) will return 6442450944.
136+
func (*Bytes) ParseBinary(value string) (i int64, err error) {
137+
parts := patternBinary.FindStringSubmatch(value)
138+
if len(parts) < 3 {
139+
return 0, fmt.Errorf("error parsing value=%s", value)
140+
}
141+
bytesString := parts[1]
142+
multiple := strings.ToUpper(parts[2])
143+
bytes, err := strconv.ParseFloat(bytesString, 64)
144+
if err != nil {
145+
return
146+
}
147+
148+
switch multiple {
149+
case "KI", "KIB":
150+
return int64(bytes * KiB), nil
151+
case "MI", "MIB":
152+
return int64(bytes * MiB), nil
153+
case "GI", "GIB":
154+
return int64(bytes * GiB), nil
155+
case "TI", "TIB":
156+
return int64(bytes * TiB), nil
157+
case "PI", "PIB":
158+
return int64(bytes * PiB), nil
159+
case "EI", "EIB":
160+
return int64(bytes * EiB), nil
161+
default:
162+
return int64(bytes), nil
163+
}
164+
}
165+
166+
// ParseDecimal parses human readable bytes string to bytes integer.
167+
// For example, 6GB (6G is also valid) will return 6000000000.
168+
func (*Bytes) ParseDecimal(value string) (i int64, err error) {
169+
parts := patternDecimal.FindStringSubmatch(value)
170+
if len(parts) < 3 {
171+
return 0, fmt.Errorf("error parsing value=%s", value)
172+
}
173+
bytesString := parts[1]
174+
multiple := strings.ToUpper(parts[2])
175+
bytes, err := strconv.ParseFloat(bytesString, 64)
176+
if err != nil {
177+
return
178+
}
179+
180+
switch multiple {
181+
case "K", "KB":
182+
return int64(bytes * KB), nil
183+
case "M", "MB":
184+
return int64(bytes * MB), nil
185+
case "G", "GB":
186+
return int64(bytes * GB), nil
187+
case "T", "TB":
188+
return int64(bytes * TB), nil
189+
case "P", "PB":
190+
return int64(bytes * PB), nil
191+
case "E", "EB":
192+
return int64(bytes * EB), nil
193+
default:
194+
return int64(bytes), nil
195+
}
196+
}
197+
198+
// Format wraps global Bytes's Format function.
199+
func Format(value int64) string {
200+
return global.Format(value)
201+
}
202+
203+
// FormatBinary wraps global Bytes's FormatBinary function.
204+
func FormatBinary(value int64) string {
205+
return global.FormatBinary(value)
206+
}
207+
208+
// FormatDecimal wraps global Bytes's FormatDecimal function.
209+
func FormatDecimal(value int64) string {
210+
return global.FormatDecimal(value)
211+
}
212+
213+
// Parse wraps global Bytes's Parse function.
214+
func Parse(value string) (int64, error) {
215+
return global.Parse(value)
216+
}

0 commit comments

Comments
 (0)