Skip to content

Commit

Permalink
Merge pull request #1 from joanlopez/fix-marshal
Browse files Browse the repository at this point in the history
Fix support for nil marshalable pointers
  • Loading branch information
mstoykov authored Apr 4, 2024
2 parents 765c6d8 + f5be74b commit 29baae8
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 15 deletions.
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}

0 comments on commit 29baae8

Please sign in to comment.