From d73e12b838a52d367851a47196ef547f3817d378 Mon Sep 17 00:00:00 2001 From: Tordarus Date: Tue, 14 Jan 2025 18:54:50 +0100 Subject: [PATCH] initial commit --- .gitignore | 1 + converters.go | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 3 ++ object.go | 34 ++++++++++++++++++++ slices.go | 79 +++++++++++++++++++++++++++++++++++++++++++++ vars.go | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 289 insertions(+) create mode 100644 .gitignore create mode 100644 converters.go create mode 100644 go.mod create mode 100644 object.go create mode 100644 slices.go create mode 100644 vars.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/converters.go b/converters.go new file mode 100644 index 0000000..aaec516 --- /dev/null +++ b/converters.go @@ -0,0 +1,89 @@ +package envvars + +import ( + "errors" + "strconv" + "unicode/utf8" +) + +func ConvertString(s string) (string, error) { + return s, nil +} + +func ConvertRune(s string) (rune, error) { + rn, _ := utf8.DecodeRuneInString(s) + if rn == utf8.RuneError { + return 0, errors.New("rune decoding failed") + } + return rn, nil +} + +func ConvertInt64(s string) (int64, error) { + return strconv.ParseInt(s, 10, 64) +} + +func ConvertInt32(s string) (int32, error) { + v, err := strconv.ParseInt(s, 10, 32) + return int32(v), err +} + +func ConvertInt16(s string) (int16, error) { + v, err := strconv.ParseInt(s, 10, 16) + return int16(v), err +} + +func ConvertInt8(s string) (int8, error) { + v, err := strconv.ParseInt(s, 10, 8) + return int8(v), err +} + +func ConvertInt(s string) (int, error) { + v, err := strconv.ParseInt(s, 10, 64) + return int(v), err +} + +func ConvertUint64(s string) (uint64, error) { + return strconv.ParseUint(s, 10, 64) +} + +func ConvertUint32(s string) (uint32, error) { + v, err := strconv.ParseUint(s, 10, 32) + return uint32(v), err +} + +func ConvertUint16(s string) (uint16, error) { + v, err := strconv.ParseUint(s, 10, 16) + return uint16(v), err +} + +func ConvertUint8(s string) (uint8, error) { + v, err := strconv.ParseUint(s, 10, 8) + return uint8(v), err +} + +func ConvertUint(s string) (uint, error) { + v, err := strconv.ParseUint(s, 10, 64) + return uint(v), err +} + +func ConvertFloat64(s string) (float64, error) { + return strconv.ParseFloat(s, 64) +} + +func ConvertFloat32(s string) (float32, error) { + v, err := strconv.ParseFloat(s, 32) + return float32(v), err +} + +func ConvertComplex128(s string) (complex128, error) { + return strconv.ParseComplex(s, 128) +} + +func ConvertComplex64(s string) (complex64, error) { + v, err := strconv.ParseComplex(s, 64) + return complex64(v), err +} + +func ConvertBool(s string) (bool, error) { + return strconv.ParseBool(s) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7db33cf --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.tordarus.net/tordarus/envvars + +go 1.18 diff --git a/object.go b/object.go new file mode 100644 index 0000000..478476c --- /dev/null +++ b/object.go @@ -0,0 +1,34 @@ +package envvars + +import ( + "os" + "strings" +) + +func Object[T any](key string, defaultValue T, converter func(string) (T, error)) T { + if v, ok := os.LookupEnv(key); ok { + if v2, err := converter(v); err == nil { + return v2 + } + } + return defaultValue +} + +func ObjectSlice[T any](key, sep string, defaultValue []T, converter func(string) (T, error)) []T { + return Object(key, defaultValue, func(s string) ([]T, error) { + if s == "" { + return []T{}, nil + } + + splits := strings.Split(s, sep) + values := make([]T, 0, len(splits)) + for _, s := range splits { + v, err := converter(s) + if err != nil { + return values, err + } + values = append(values, v) + } + return values, nil + }) +} diff --git a/slices.go b/slices.go new file mode 100644 index 0000000..9204814 --- /dev/null +++ b/slices.go @@ -0,0 +1,79 @@ +package envvars + +import "time" + +func StringSlice(key, sep string, defaultValue []string) []string { + return ObjectSlice(key, sep, defaultValue, ConvertString) +} + +func ByteSlice(key, sep string, defaultValue []byte) []byte { + return Uint8Slice(key, sep, defaultValue) +} + +func RuneSlice(key, sep string, defaultValue []rune) []rune { + return ObjectSlice(key, sep, defaultValue, ConvertRune) +} + +func IntSlice(key, sep string, defaultValue []int) []int { + return ObjectSlice(key, sep, defaultValue, ConvertInt) +} + +func Int8Slice(key, sep string, defaultValue []int8) []int8 { + return ObjectSlice(key, sep, defaultValue, ConvertInt8) +} + +func Int16Slice(key, sep string, defaultValue []int16) []int16 { + return ObjectSlice(key, sep, defaultValue, ConvertInt16) +} + +func Int32Slice(key, sep string, defaultValue []int32) []int32 { + return ObjectSlice(key, sep, defaultValue, ConvertInt32) +} + +func Int64Slice(key, sep string, defaultValue []int64) []int64 { + return ObjectSlice(key, sep, defaultValue, ConvertInt64) +} + +func Uint8Slice(key, sep string, defaultValue []uint8) []uint8 { + return ObjectSlice(key, sep, defaultValue, ConvertUint8) +} + +func Uint16Slice(key, sep string, defaultValue []uint16) []uint16 { + return ObjectSlice(key, sep, defaultValue, ConvertUint16) +} + +func Uint32Slice(key, sep string, defaultValue []uint32) []uint32 { + return ObjectSlice(key, sep, defaultValue, ConvertUint32) +} + +func Uint64Slice(key, sep string, defaultValue []uint64) []uint64 { + return ObjectSlice(key, sep, defaultValue, ConvertUint64) +} + +func Float32Slice(key, sep string, defaultValue []float32) []float32 { + return ObjectSlice(key, sep, defaultValue, ConvertFloat32) +} + +func Float64Slice(key, sep string, defaultValue []float64) []float64 { + return ObjectSlice(key, sep, defaultValue, ConvertFloat64) +} + +func Complex64Slice(key, sep string, defaultValue []complex64) []complex64 { + return ObjectSlice(key, sep, defaultValue, ConvertComplex64) +} + +func Complex128Slice(key, sep string, defaultValue []complex128) []complex128 { + return ObjectSlice(key, sep, defaultValue, ConvertComplex128) +} + +func BoolSlice(key, sep string, defaultValue []bool) []bool { + return ObjectSlice(key, sep, defaultValue, ConvertBool) +} + +func TimeSlice(key, sep string, defaultValue []time.Time, layout string) []time.Time { + return ObjectSlice(key, sep, defaultValue, func(s string) (time.Time, error) { return time.Parse(layout, s) }) +} + +func DurationSlice(key, sep string, defaultValue []time.Duration) []time.Duration { + return ObjectSlice(key, sep, defaultValue, time.ParseDuration) +} diff --git a/vars.go b/vars.go new file mode 100644 index 0000000..591dbd3 --- /dev/null +++ b/vars.go @@ -0,0 +1,83 @@ +package envvars + +import "time" + +func String(key, defaultValue string) string { + return Object(key, defaultValue, ConvertString) +} + +func Byte(key string, defaultValue byte) byte { + return Uint8(key, defaultValue) +} + +func Rune(key string, defaultValue rune) rune { + return Object(key, defaultValue, ConvertRune) +} + +func Int64(key string, defaultValue int64) int64 { + return Object(key, defaultValue, ConvertInt64) +} + +func Int32(key string, defaultValue int32) int32 { + return Object(key, defaultValue, ConvertInt32) +} + +func Int16(key string, defaultValue int16) int16 { + return Object(key, defaultValue, ConvertInt16) +} + +func Int8(key string, defaultValue int8) int8 { + return Object(key, defaultValue, ConvertInt8) +} + +func Int(key string, defaultValue int) int { + return Object(key, defaultValue, ConvertInt) +} + +func Uint64(key string, defaultValue uint64) uint64 { + return Object(key, defaultValue, ConvertUint64) +} + +func Uint32(key string, defaultValue uint32) uint32 { + return Object(key, defaultValue, ConvertUint32) +} + +func Uint16(key string, defaultValue uint16) uint16 { + return Object(key, defaultValue, ConvertUint16) +} + +func Uint8(key string, defaultValue uint8) uint8 { + return Object(key, defaultValue, ConvertUint8) +} + +func Uint(key string, defaultValue uint) uint { + return Object(key, defaultValue, ConvertUint) +} + +func Float64(key string, defaultValue float64) float64 { + return Object(key, defaultValue, ConvertFloat64) +} + +func Float32(key string, defaultValue float32) float32 { + return Object(key, defaultValue, ConvertFloat32) +} + +func Complex128(key string, defaultValue complex128) complex128 { + return Object(key, defaultValue, ConvertComplex128) +} + +func Complex64(key string, defaultValue complex64) complex64 { + return Object(key, defaultValue, ConvertComplex64) +} + +func Bool(key string, defaultValue bool) bool { + return Object(key, defaultValue, ConvertBool) +} + +func Time(key string, defaultValue time.Time, layout string) time.Time { + return Object(key, defaultValue, func(s string) (time.Time, error) { return time.Parse(layout, s) }) +} + +func Duration(key string, defaultValue time.Duration) time.Duration { + return Object(key, defaultValue, time.ParseDuration) +}