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

Allow to use integer literals #19

Merged
merged 4 commits into from
Jul 24, 2020
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: go
go: 1.11
go: 1.13
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self:
"This PR require at least go1.13"

Per the number literal proposal, Go 1.13 supports a more uniform and modernized set of number literal prefixes.

https://golang.org/doc/go1.13#language


branches:
only:
Expand Down
33 changes: 20 additions & 13 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ var (

const (
fieldName = "default"

autoBase = 0

bitSize8 = 8
bitSize16 = 16
bitSize32 = 32
bitSize64 = 64
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see the point in defining these constants...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree with bitXXSize constants , but autoBase add context to 0 value in base but it is not so significant therefore I will change that

)

// Set initializes members in a struct referenced by a pointer.
Expand Down Expand Up @@ -58,57 +65,57 @@ func setField(field reflect.Value, defaultVal string) error {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
}
case reflect.Int:
if val, err := strconv.ParseInt(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseInt(defaultVal, autoBase, strconv.IntSize); err == nil {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strconv.IntSize

Nice 👍

field.Set(reflect.ValueOf(int(val)).Convert(field.Type()))
}
case reflect.Int8:
if val, err := strconv.ParseInt(defaultVal, 10, 8); err == nil {
if val, err := strconv.ParseInt(defaultVal, autoBase, bitSize8); err == nil {
field.Set(reflect.ValueOf(int8(val)).Convert(field.Type()))
}
case reflect.Int16:
if val, err := strconv.ParseInt(defaultVal, 10, 16); err == nil {
if val, err := strconv.ParseInt(defaultVal, autoBase, bitSize16); err == nil {
field.Set(reflect.ValueOf(int16(val)).Convert(field.Type()))
}
case reflect.Int32:
if val, err := strconv.ParseInt(defaultVal, 10, 32); err == nil {
if val, err := strconv.ParseInt(defaultVal, autoBase, bitSize32); err == nil {
field.Set(reflect.ValueOf(int32(val)).Convert(field.Type()))
}
case reflect.Int64:
if val, err := time.ParseDuration(defaultVal); err == nil {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
} else if val, err := strconv.ParseInt(defaultVal, 10, 64); err == nil {
} else if val, err := strconv.ParseInt(defaultVal, autoBase, bitSize64); err == nil {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
}
case reflect.Uint:
if val, err := strconv.ParseUint(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseUint(defaultVal, autoBase, strconv.IntSize); err == nil {
field.Set(reflect.ValueOf(uint(val)).Convert(field.Type()))
}
case reflect.Uint8:
if val, err := strconv.ParseUint(defaultVal, 10, 8); err == nil {
if val, err := strconv.ParseUint(defaultVal, autoBase, bitSize8); err == nil {
field.Set(reflect.ValueOf(uint8(val)).Convert(field.Type()))
}
case reflect.Uint16:
if val, err := strconv.ParseUint(defaultVal, 10, 16); err == nil {
if val, err := strconv.ParseUint(defaultVal, autoBase, bitSize16); err == nil {
field.Set(reflect.ValueOf(uint16(val)).Convert(field.Type()))
}
case reflect.Uint32:
if val, err := strconv.ParseUint(defaultVal, 10, 32); err == nil {
if val, err := strconv.ParseUint(defaultVal, autoBase, bitSize32); err == nil {
field.Set(reflect.ValueOf(uint32(val)).Convert(field.Type()))
}
case reflect.Uint64:
if val, err := strconv.ParseUint(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseUint(defaultVal, autoBase, bitSize64); err == nil {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
}
case reflect.Uintptr:
if val, err := strconv.ParseUint(defaultVal, 10, 64); err == nil {
if val, err := strconv.ParseUint(defaultVal, autoBase, strconv.IntSize); err == nil {
field.Set(reflect.ValueOf(uintptr(val)).Convert(field.Type()))
}
case reflect.Float32:
if val, err := strconv.ParseFloat(defaultVal, 32); err == nil {
if val, err := strconv.ParseFloat(defaultVal, bitSize32); err == nil {
field.Set(reflect.ValueOf(float32(val)).Convert(field.Type()))
}
case reflect.Float64:
if val, err := strconv.ParseFloat(defaultVal, 64); err == nil {
if val, err := strconv.ParseFloat(defaultVal, bitSize64); err == nil {
field.Set(reflect.ValueOf(val).Convert(field.Type()))
}
case reflect.String:
Expand Down
127 changes: 127 additions & 0 deletions defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,39 @@ type Sample struct {
String string `default:"hello"`
Duration time.Duration `default:"10s"`

IntOct int `default:"0o1"`
Int8Oct int8 `default:"0o10"`
Int16Oct int16 `default:"0o20"`
Int32Oct int32 `default:"0o40"`
Int64Oct int64 `default:"0o100"`
UintOct uint `default:"0o1"`
Uint8Oct uint8 `default:"0o10"`
Uint16Oct uint16 `default:"0o20"`
Uint32Oct uint32 `default:"0o40"`
Uint64Oct uint64 `default:"0o100"`

IntHex int `default:"0x1"`
Int8Hex int8 `default:"0x8"`
Int16Hex int16 `default:"0x10"`
Int32Hex int32 `default:"0x20"`
Int64Hex int64 `default:"0x40"`
UintHex uint `default:"0x1"`
Uint8Hex uint8 `default:"0x8"`
Uint16Hex uint16 `default:"0x10"`
Uint32Hex uint32 `default:"0x20"`
Uint64Hex uint64 `default:"0x40"`

IntBin int `default:"0b1"`
Int8Bin int8 `default:"0b1000"`
Int16Bin int16 `default:"0b10000"`
Int32Bin int32 `default:"0b100000"`
Int64Bin int64 `default:"0b1000000"`
UintBin uint `default:"0b1"`
Uint8Bin uint8 `default:"0b1000"`
Uint16Bin uint16 `default:"0b10000"`
Uint32Bin uint32 `default:"0b100000"`
Uint64Bin uint64 `default:"0b1000000"`

Struct Struct `default:"{}"`
StructPtr *Struct `default:"{}"`
Map map[string]int `default:"{}"`
Expand Down Expand Up @@ -182,6 +215,100 @@ func TestInit(t *testing.T) {
if sample.String != "hello" {
t.Errorf("it should initialize string")
}

if sample.IntOct != 0o1 {
t.Errorf("it should initialize int with octal literal")
}
if sample.Int8Oct != 0o10 {
t.Errorf("it should initialize int8 with octal literal")
}
if sample.Int16Oct != 0o20 {
t.Errorf("it should initialize int16 with octal literal")
}
if sample.Int32Oct != 0o40 {
t.Errorf("it should initialize int32 with octal literal")
}
if sample.Int64Oct != 0o100 {
t.Errorf("it should initialize int64 with octal literal")
}
if sample.UintOct != 0o1 {
t.Errorf("it should initialize uint with octal literal")
}
if sample.Uint8Oct != 0o10 {
t.Errorf("it should initialize uint8 with octal literal")
}
if sample.Uint16Oct != 0o20 {
t.Errorf("it should initialize uint16 with octal literal")
}
if sample.Uint32Oct != 0o40 {
t.Errorf("it should initialize uint32 with octal literal")
}
if sample.Uint64Oct != 0o100 {
t.Errorf("it should initialize uint64 with octal literal")
}

if sample.IntHex != 0x1 {
t.Errorf("it should initialize int with hexadecimal literal")
}
if sample.Int8Hex != 0x8 {
t.Errorf("it should initialize int8 with hexadecimal literal")
}
if sample.Int16Hex != 0x10 {
t.Errorf("it should initialize int16 with hexadecimal literal")
}
if sample.Int32Hex != 0x20 {
t.Errorf("it should initialize int32 with hexadecimal literal")
}
if sample.Int64Hex != 0x40 {
t.Errorf("it should initialize int64 with hexadecimal literal")
}
if sample.UintHex != 0x1 {
t.Errorf("it should initialize uint with hexadecimal literal")
}
if sample.Uint8Hex != 0x8 {
t.Errorf("it should initialize uint8 with hexadecimal literal")
}
if sample.Uint16Hex != 0x10 {
t.Errorf("it should initialize uint16 with hexadecimal literal")
}
if sample.Uint32Hex != 0x20 {
t.Errorf("it should initialize uint32 with hexadecimal literal")
}
if sample.Uint64Hex != 0x40 {
t.Errorf("it should initialize uint64 with hexadecimal literal")
}

if sample.IntBin != 0b1 {
t.Errorf("it should initialize int with binary literal")
}
if sample.Int8Bin != 0b1000 {
t.Errorf("it should initialize int8 with binary literal")
}
if sample.Int16Bin != 0b10000 {
t.Errorf("it should initialize int16 with binary literal")
}
if sample.Int32Bin != 0b100000 {
t.Errorf("it should initialize int32 with binary literal")
}
if sample.Int64Bin != 0b1000000 {
t.Errorf("it should initialize int64 with binary literal")
}
if sample.UintBin != 0b1 {
t.Errorf("it should initialize uint with binary literal")
}
if sample.Uint8Bin != 0b1000 {
t.Errorf("it should initialize uint8 with binary literal")
}
if sample.Uint16Bin != 0b10000 {
t.Errorf("it should initialize uint16 with binary literal")
}
if sample.Uint32Bin != 0b100000 {
t.Errorf("it should initialize uint32 with binary literal")
}
if sample.Uint64Bin != 0b1000000 {
t.Errorf("it should initialize uint64 with binary literal")
}

})

t.Run("complex types", func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/creasty/defaults

go 1.11
go 1.13