Skip to content

Commit 076cb6c

Browse files
authored
feat: Add support of []uint8 (#81)
1 parent 4f9dea7 commit 076cb6c

File tree

8 files changed

+326
-3
lines changed

8 files changed

+326
-3
lines changed

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
[![Go Reference](https://pkg.go.dev/badge/github.com/obalunenko/getenv.svg)](https://pkg.go.dev/github.com/obalunenko/getenv)
33
[![Go Report Card](https://goreportcard.com/badge/github.com/obalunenko/getenv)](https://goreportcard.com/report/github.com/obalunenko/getenv)
44
[![codecov](https://codecov.io/gh/obalunenko/getenv/branch/master/graph/badge.svg)](https://codecov.io/gh/obalunenko/getenv)
5-
![coverbadger-tag-do-not-edit](https://img.shields.io/badge/coverage-97.56%25-brightgreen?longCache=true&style=flat)
5+
![coverbadger-tag-do-not-edit](https://img.shields.io/badge/coverage-97.66%25-brightgreen?longCache=true&style=flat)
66
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=obalunenko_getenv&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=obalunenko_getenv)
7+
78
# getenv
89

910
Package getenv provides functionality for loading environment variables and parse them into go builtin types.
@@ -22,6 +23,7 @@ Types supported:
2223
- int64
2324
- []int64
2425
- uint8
26+
- []uint8
2527
- uint16
2628
- uint64
2729
- []uint64
@@ -51,6 +53,7 @@ package main
5153

5254
import (
5355
"fmt"
56+
url "net/url"
5457
"os"
5558
"time"
5659

@@ -114,6 +117,14 @@ func main() {
114117
val = getenv.EnvOrDefault(key, time.Second)
115118
fmt.Printf("[%T]: %v\n", val, val)
116119

120+
// url.URL
121+
if err := os.Setenv(key, "https://test:abcd123@golangbyexample.com:8000/tutorials/intro?type=advance&compact=false#history"); err != nil {
122+
panic(err)
123+
}
124+
125+
val = getenv.EnvOrDefault(key, url.URL{})
126+
fmt.Printf("[%T]: %v\n", val, val)
127+
117128
}
118129

119130
```
@@ -126,4 +137,5 @@ Output:
126137
[time.Time]: 2022-01-20 00:00:00 +0000 UTC
127138
[[]float64]: [26.89 0.67]
128139
[time.Duration]: 2h35m0s
140+
[url.URL]: {https test:abcd123 golangbyexample.com:8000 /tutorials/intro false false type=advance&compact=false history }
129141
```

getenv.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// - int64
1515
// - []int64
1616
// - uint8
17+
// - []uint8
1718
// - uint16
1819
// - uint64
1920
// - []uint64

getenv_test.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,6 +2344,119 @@ func TestInt16OrDefault(t *testing.T) {
23442344
}
23452345
}
23462346

2347+
func TestUint8SliceOrDefault(t *testing.T) {
2348+
type args struct {
2349+
key string
2350+
defaultVal []uint8
2351+
sep string
2352+
}
2353+
2354+
type expected struct {
2355+
val []uint8
2356+
}
2357+
2358+
var tests = []struct {
2359+
name string
2360+
precond precondition
2361+
args args
2362+
expected expected
2363+
}{
2364+
{
2365+
name: "env not set - default returned",
2366+
precond: precondition{
2367+
setenv: setenv{
2368+
isSet: false,
2369+
val: "1,27",
2370+
},
2371+
},
2372+
args: args{
2373+
key: testEnvKey,
2374+
defaultVal: []uint8{99},
2375+
sep: ",",
2376+
},
2377+
expected: expected{
2378+
val: []uint8{99},
2379+
},
2380+
},
2381+
{
2382+
name: "env set - env value returned",
2383+
precond: precondition{
2384+
setenv: setenv{
2385+
isSet: true,
2386+
val: "1,2",
2387+
},
2388+
},
2389+
args: args{
2390+
key: testEnvKey,
2391+
defaultVal: []uint8{99},
2392+
sep: ",",
2393+
},
2394+
expected: expected{
2395+
val: []uint8{1, 2},
2396+
},
2397+
},
2398+
{
2399+
name: "env set, no separator - default value returned",
2400+
precond: precondition{
2401+
setenv: setenv{
2402+
isSet: true,
2403+
val: "1,2",
2404+
},
2405+
},
2406+
args: args{
2407+
key: testEnvKey,
2408+
defaultVal: []uint8{99},
2409+
sep: "",
2410+
},
2411+
expected: expected{
2412+
val: []uint8{99},
2413+
},
2414+
},
2415+
{
2416+
name: "env set, wrong separator - default value returned",
2417+
precond: precondition{
2418+
setenv: setenv{
2419+
isSet: true,
2420+
val: "1,2",
2421+
},
2422+
},
2423+
args: args{
2424+
key: testEnvKey,
2425+
defaultVal: []uint8{99},
2426+
sep: "|",
2427+
},
2428+
expected: expected{
2429+
val: []uint8{99},
2430+
},
2431+
},
2432+
{
2433+
name: "empty env value set - default returned",
2434+
precond: precondition{
2435+
setenv: setenv{
2436+
isSet: true,
2437+
val: "",
2438+
},
2439+
},
2440+
args: args{
2441+
key: testEnvKey,
2442+
defaultVal: []uint8{99},
2443+
},
2444+
expected: expected{
2445+
val: []uint8{99},
2446+
},
2447+
},
2448+
}
2449+
2450+
for _, tt := range tests {
2451+
t.Run(tt.name, func(t *testing.T) {
2452+
tt.precond.maybeSetEnv(t, tt.args.key)
2453+
2454+
got := getenv.EnvOrDefault(tt.args.key, tt.args.defaultVal, option.WithSeparator(tt.args.sep))
2455+
assert.Equal(t, tt.expected.val, got)
2456+
})
2457+
}
2458+
}
2459+
23472460
func TestInt16SliceOrDefault(t *testing.T) {
23482461
type args struct {
23492462
key string

internal/constraint.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type (
2323

2424
// Uint is a constraint for unsigned integer and slice of unsigned integers.
2525
Uint interface {
26-
uint | []uint | uint8 | uint16 | uint32 | []uint32 | uint64 | []uint64
26+
uint | []uint | uint8 | []uint8 | uint16 | uint32 | []uint32 | uint64 | []uint64
2727
}
2828

2929
// Float is a constraint for floats and slice of floats.

internal/iface.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func NewEnvParser(v any) EnvParser {
1616
p = newStringParser(t)
1717
case int, []int, int8, []int8, int16, []int16, int32, []int32, int64, []int64:
1818
p = newIntParser(t)
19-
case uint, []uint, uint8, uint16, uint32, []uint32, uint64, []uint64:
19+
case uint, []uint, uint8, []uint8, uint16, uint32, []uint32, uint64, []uint64:
2020
p = newUintParser(t)
2121
case bool:
2222
p = boolParser(t)
@@ -83,6 +83,8 @@ func newUintParser(v any) EnvParser {
8383
switch t := v.(type) {
8484
case uint8:
8585
return uint8Parser(t)
86+
case []uint8:
87+
return uint8SliceParser(t)
8688
case uint:
8789
return uintParser(t)
8890
case []uint:
@@ -335,6 +337,16 @@ func (i uintSliceParser) ParseEnv(key string, defaltVal any, options Parameters)
335337
return val
336338
}
337339

340+
type uint8SliceParser []uint8
341+
342+
func (i uint8SliceParser) ParseEnv(key string, defaltVal any, options Parameters) any {
343+
sep := options.Separator
344+
345+
val := uint8SliceOrDefault(key, defaltVal.([]uint8), sep)
346+
347+
return val
348+
}
349+
338350
type uint32SliceParser []uint32
339351

340352
func (i uint32SliceParser) ParseEnv(key string, defaltVal any, options Parameters) any {

internal/iface_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ func TestNewEnvParser(t *testing.T) {
159159
want: int16SliceParser([]int16{1}),
160160
wantPanic: assert.NotPanics,
161161
},
162+
{
163+
name: "[]uint8",
164+
args: args{
165+
v: []uint8{1},
166+
},
167+
want: uint8SliceParser([]uint8{1}),
168+
wantPanic: assert.NotPanics,
169+
},
162170
{
163171
name: "[]int8",
164172
args: args{
@@ -694,6 +702,25 @@ func Test_ParseEnv(t *testing.T) {
694702
},
695703
want: 12,
696704
},
705+
{
706+
name: "uint8SliceParser",
707+
s: uint8SliceParser(nil),
708+
precond: precondition{
709+
setenv: setenv{
710+
isSet: true,
711+
val: "12,89",
712+
},
713+
},
714+
args: args{
715+
key: testEnvKey,
716+
defaltVal: []uint8{99},
717+
in2: Parameters{
718+
Separator: ",",
719+
Layout: "",
720+
},
721+
},
722+
want: []uint8{12, 89},
723+
},
697724
{
698725
name: "int8SliceParser",
699726
s: int8SliceParser(nil),

internal/parsers.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,34 @@ func uintSliceOrDefault(key string, defaultVal []uint, sep string) []uint {
543543
return val
544544
}
545545

546+
// uint8SliceOrDefault retrieves the uint8 slice value of the environment variable named
547+
// by the key and separated by sep.
548+
// If variable not set or value is empty - defaultVal will be returned.
549+
func uint8SliceOrDefault(key string, defaultVal []uint8, sep string) []uint8 {
550+
valraw := stringSliceOrDefault(key, nil, sep)
551+
if valraw == nil {
552+
return defaultVal
553+
}
554+
555+
val := make([]uint8, 0, len(valraw))
556+
557+
const (
558+
base = 10
559+
bitsize = 8
560+
)
561+
562+
for _, s := range valraw {
563+
v, err := strconv.ParseUint(s, base, bitsize)
564+
if err != nil {
565+
return defaultVal
566+
}
567+
568+
val = append(val, uint8(v))
569+
}
570+
571+
return val
572+
}
573+
546574
// uint32SliceOrDefault retrieves the uint32 slice value of the environment variable named
547575
// by the key and separated by sep.
548576
// If variable not set or value is empty - defaultVal will be returned.

0 commit comments

Comments
 (0)