Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃 Add support encoding.TextUnmarshaler #123

Merged
merged 6 commits into from Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 11 additions & 10 deletions README.md
Expand Up @@ -4,7 +4,7 @@

Minimalistic configuration reader

[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
[![GoDoc](https://godoc.org/github.com/ilyakaznacheev/cleanenv?status.svg)](https://godoc.org/github.com/ilyakaznacheev/cleanenv)
[![Go Report Card](https://goreportcard.com/badge/github.com/ilyakaznacheev/cleanenv)](https://goreportcard.com/report/github.com/ilyakaznacheev/cleanenv)
[![Coverage Status](https://codecov.io/github/ilyakaznacheev/cleanenv/coverage.svg?branch=master)](https://codecov.io/gh/ilyakaznacheev/cleanenv)
Expand All @@ -24,18 +24,18 @@ This is a simple configuration reading tool. It just does the following:

- [Installation](#installation)
- [Usage](#usage)
- [Read Configuration](#read-configuration)
- [Read Environment Variables Only](#read-environment-variables-only)
- [Update Environment Variables](#update-environment-variables)
- [Description](#description)
- [Read Configuration](#read-configuration)
mirecl marked this conversation as resolved.
Show resolved Hide resolved
- [Read Environment Variables Only](#read-environment-variables-only)
- [Update Environment Variables](#update-environment-variables)
- [Description](#description)
- [Model Format](#model-format)
- [Supported types](#supported-types)
- [Custom Functions](#custom-functions)
- [Custom Value Setter](#custom-value-setter)
- [Custom Value Update](#custom-value-update)
- [Custom Value Setter](#custom-value-setter)
- [Custom Value Update](#custom-value-update)
- [Supported File Formats](#supported-file-formats)
- [Integration](#integration)
- [Flag](#flag)
- [Flag](#flag)
- [Examples](#examples)
- [Contribution](#contribution)
- [Thanks](#thanks)
Expand Down Expand Up @@ -93,7 +93,7 @@ This will do the following:

Sometimes you don't want to use configuration files at all, or you may want to use `.env` file format instead. Thus, you can limit yourself with only reading environment variables:

```go
```go
import "github.com/ilyakaznacheev/cleanenv"

type ConfigDatabase struct {
Expand Down Expand Up @@ -193,9 +193,9 @@ There are following supported types:
- `time.Duration`;
- `time.Time` (layout by default is RFC3339, may be overridden by `env-layout`);
- `*time.Location` (time zone parsing [depends](https://pkg.go.dev/time#LoadLocation) on running machine)
- any type that implements `encoding.TextUnmarshaler`;
- any type implementing `cleanenv.Setter` interface.


## Custom Functions

To enhance package abilities you can use some custom functions.
Expand Down Expand Up @@ -251,6 +251,7 @@ There are several most popular config file formats supported:
- ENV (`.env`)

**Note**:

- while using `.env` file the library will set corresponding data to process environment variables.
It will override existing variables with the same keys in the process environment.

Expand Down
20 changes: 14 additions & 6 deletions cleanenv.go
@@ -1,6 +1,7 @@
package cleanenv

import (
"encoding"
"encoding/json"
"flag"
"fmt"
Expand Down Expand Up @@ -459,15 +460,27 @@ func readEnvVars(cfg interface{}, update bool) error {
func parseValue(field reflect.Value, value, sep string, layout *string) error {
// TODO: simplify recursion

valueType := field.Type()

// look for supported struct parser
if structParser, found := validStructs[valueType]; found {
return structParser(&field, value, layout)
}

mirecl marked this conversation as resolved.
Show resolved Hide resolved
if field.CanInterface() {
if ctp, ok := field.Addr().Interface().(encoding.TextUnmarshaler); ok {
return ctp.UnmarshalText([]byte(value))
} else if ct, ok := field.Interface().(encoding.TextUnmarshaler); ok {
return ct.UnmarshalText([]byte(value))
}

if cs, ok := field.Interface().(Setter); ok {
return cs.SetValue(value)
} else if csp, ok := field.Addr().Interface().(Setter); ok {
return csp.SetValue(value)
}
mirecl marked this conversation as resolved.
Show resolved Hide resolved
}

valueType := field.Type()
switch valueType.Kind() {

// parse string value
Expand Down Expand Up @@ -542,11 +555,6 @@ func parseValue(field reflect.Value, value, sep string, layout *string) error {
field.Set(*mapValue)

default:
// look for supported struct parser
if structParser, found := validStructs[valueType]; found {
return structParser(&field, value, layout)
}

return fmt.Errorf("unsupported type %s.%s", valueType.PkgPath(), valueType.Name())
}

Expand Down