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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix support for nil marshalable pointers #1

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions envconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,6 @@ func processField(value string, field reflect.Value) error {
return setter.Set(value)
}

if t := textUnmarshaler(field); t != nil {
return t.UnmarshalText([]byte(value))
}

if b := binaryUnmarshaler(field); b != nil {
return b.UnmarshalBinary([]byte(value))
}

if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
if field.IsNil() {
Expand All @@ -269,6 +261,14 @@ func processField(value string, field reflect.Value) error {
field = field.Elem()
}

if t := textUnmarshaler(field); t != nil {
return t.UnmarshalText([]byte(value))
}

if b := binaryUnmarshaler(field); b != nil {
return b.UnmarshalBinary([]byte(value))
}

switch typ.Kind() {
case reflect.String:
field.SetString(value)
Expand Down
59 changes: 52 additions & 7 deletions envconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@ func (cu *CustomURL) UnmarshalBinary(data []byte) error {
return err
}

type FilePermission uint8

type FilePermissionSet FilePermission

const (
ReadPermission FilePermission = 1 << iota // 1 << 0 == 1
WritePermission // 1 << 1 == 2
ExecutePermission // 1 << 2 == 4
)

func (fps *FilePermissionSet) addPermission(permission FilePermission) {
*fps |= FilePermissionSet(permission)
}

func (fps *FilePermissionSet) UnmarshalText(text []byte) error {
*fps = 0 // Reset permissions
for _, b := range text {
switch b {
case 'r':
fps.addPermission(ReadPermission)
case 'w':
fps.addPermission(WritePermission)
case 'x':
fps.addPermission(ExecutePermission)
default:
return fmt.Errorf("invalid permission: %c", b)
}
}
return nil
}

type Specification struct {
Embedded `desc:"can we document a struct"`
EmbeddedButIgnored `ignored:"true"`
Expand Down Expand Up @@ -64,12 +95,14 @@ type Specification struct {
Property string `envconfig:"inner"`
PropertyWithDefault string `default:"fuzzybydefault"`
} `envconfig:"outer"`
AfterNested string
DecodeStruct HonorDecodeInStruct `envconfig:"honor"`
Datetime time.Time
MapField map[string]string `default:"one:two,three:four"`
UrlValue CustomURL
UrlPointer *CustomURL
AfterNested string
DecodeStruct HonorDecodeInStruct `envconfig:"honor"`
Datetime time.Time
MapField map[string]string `default:"one:two,three:four"`
UrlValue CustomURL
UrlPointer *CustomURL
FilePermissionValue FilePermissionSet
FilePermissionPointer *FilePermissionSet
}

type Embedded struct {
Expand Down Expand Up @@ -111,6 +144,8 @@ func TestProcess(t *testing.T) {
os.Setenv("ENV_CONFIG_MULTI_WORD_ACR_WITH_AUTO_SPLIT", "25")
os.Setenv("ENV_CONFIG_URLVALUE", "https://github.com/kelseyhightower/envconfig")
os.Setenv("ENV_CONFIG_URLPOINTER", "https://github.com/kelseyhightower/envconfig")
os.Setenv("ENV_CONFIG_FILEPERMISSIONVALUE", "rwx")
os.Setenv("ENV_CONFIG_FILEPERMISSIONPOINTER", "rwx")
err := Process("env_config", &s)
if err != nil {
t.Error(err.Error())
Expand Down Expand Up @@ -217,6 +252,16 @@ func TestProcess(t *testing.T) {
if *s.UrlPointer.Value != *u {
t.Errorf("expected %q, got %q", u, s.UrlPointer.Value.String())
}

fps := FilePermissionSet(ReadPermission | WritePermission | ExecutePermission)

if s.FilePermissionValue != fps {
t.Errorf("expected %q, got %q", fps, s.FilePermissionValue)
}

if *s.FilePermissionPointer != fps {
t.Errorf("expected %q, got %q", fps, *s.FilePermissionPointer)
}
}

func TestParseErrorBool(t *testing.T) {
Expand Down Expand Up @@ -794,7 +839,7 @@ func TestCheckDisallowedIgnored(t *testing.T) {

func TestErrorMessageForRequiredAltVar(t *testing.T) {
var s struct {
Foo string `envconfig:"BAR" required:"true"`
Foo string `envconfig:"BAR" required:"true"`
}

os.Clearenv()
Expand Down
2 changes: 2 additions & 0 deletions testdata/custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ ENV_CONFIG_DATETIME=
ENV_CONFIG_MAPFIELD=
ENV_CONFIG_URLVALUE=
ENV_CONFIG_URLPOINTER=
ENV_CONFIG_FILEPERMISSIONVALUE=
ENV_CONFIG_FILEPERMISSIONPOINTER=
10 changes: 10 additions & 0 deletions testdata/default_list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,13 @@ ENV_CONFIG_URLPOINTER
..[type]........CustomURL
..[default].....
..[required]....
ENV_CONFIG_FILEPERMISSIONVALUE
..[description].
..[type]........FilePermissionSet
..[default].....
..[required]....
ENV_CONFIG_FILEPERMISSIONPOINTER
..[description].
..[type]........FilePermissionSet
..[default].....
..[required]....
2 changes: 2 additions & 0 deletions testdata/default_table.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ ENV_CONFIG_DATETIME..............................Time...........................
ENV_CONFIG_MAPFIELD..............................Comma-separated.list.of.String:String.pairs.....one:two,three:four................
ENV_CONFIG_URLVALUE..............................CustomURL.........................................................................
ENV_CONFIG_URLPOINTER............................CustomURL.........................................................................
ENV_CONFIG_FILEPERMISSIONVALUE...................FilePermissionSet.................................................................
ENV_CONFIG_FILEPERMISSIONPOINTER.................FilePermissionSet.................................................................
2 changes: 2 additions & 0 deletions testdata/fault.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@
{.Key}
{.Key}
{.Key}
{.Key}
{.Key}