Skip to content

Commit 9ec81c9

Browse files
Matthew Jaffeejaffee
Matthew Jaffee
authored andcommitted
add support for "wrapped" types using some unsafe shenanigans
1 parent ec5b9f0 commit 9ec81c9

File tree

3 files changed

+41
-23
lines changed

3 files changed

+41
-23
lines changed

com.go

+14-14
Original file line numberDiff line numberDiff line change
@@ -271,27 +271,27 @@ func setFlags(flags *flagTracker, main interface{}, prefix string) error {
271271
// now check basic kinds
272272
switch ft.Type.Kind() {
273273
case reflect.String:
274-
p := f.Addr().Interface().(*string)
274+
p := (*string)(f.Addr().UnsafePointer())
275275
flags.string(p, flagName, shorthand, f.String(), flagHelp(ft))
276276
case reflect.Bool:
277-
p := f.Addr().Interface().(*bool)
277+
p := (*bool)(f.Addr().UnsafePointer())
278278
flags.bool(p, flagName, shorthand, f.Bool(), flagHelp(ft))
279279
case reflect.Int:
280-
p := f.Addr().Interface().(*int)
280+
p := (*int)(f.Addr().UnsafePointer())
281281
val := int(f.Int())
282282
flags.int(p, flagName, shorthand, val, flagHelp(ft))
283283
case reflect.Int64:
284-
p := f.Addr().Interface().(*int64)
284+
p := (*int64)(f.Addr().UnsafePointer())
285285
flags.int64(p, flagName, shorthand, f.Int(), flagHelp(ft))
286286
case reflect.Float64:
287-
p := f.Addr().Interface().(*float64)
287+
p := (*float64)(f.Addr().UnsafePointer())
288288
flags.float64(p, flagName, shorthand, f.Float(), flagHelp(ft))
289289
case reflect.Uint:
290-
p := f.Addr().Interface().(*uint)
290+
p := (*uint)(f.Addr().UnsafePointer())
291291
val := uint(f.Uint())
292292
flags.uint(p, flagName, shorthand, val, flagHelp(ft))
293293
case reflect.Uint64:
294-
p := f.Addr().Interface().(*uint64)
294+
p := (*uint64)(f.Addr().UnsafePointer())
295295
flags.uint64(p, flagName, shorthand, f.Uint(), flagHelp(ft))
296296
case reflect.Slice:
297297
if !flags.pflag {
@@ -317,43 +317,43 @@ func setFlags(flags *flagTracker, main interface{}, prefix string) error {
317317
if !flags.pflag {
318318
return fmt.Errorf("cannot support float32 field at '%v' with stdlib flag pkg.", flagName)
319319
}
320-
p := f.Addr().Interface().(*float32)
320+
p := (*float32)(f.Addr().UnsafePointer())
321321
flags.float32(p, flagName, shorthand, *p, flagHelp(ft))
322322
case reflect.Int16:
323323
if !flags.pflag {
324324
return fmt.Errorf("cannot support int16 field at '%v' with stdlib flag pkg.", flagName)
325325
}
326-
p := f.Addr().Interface().(*int16)
326+
p := (*int16)(f.Addr().UnsafePointer())
327327
flags.int16(p, flagName, shorthand, *p, flagHelp(ft))
328328
case reflect.Int32:
329329
if !flags.pflag {
330330
return fmt.Errorf("cannot support int32 field at '%v' with stdlib flag pkg.", flagName)
331331
}
332-
p := f.Addr().Interface().(*int32)
332+
p := (*int32)(f.Addr().UnsafePointer())
333333
flags.int32(p, flagName, shorthand, *p, flagHelp(ft))
334334
case reflect.Uint16:
335335
if !flags.pflag {
336336
return fmt.Errorf("cannot support uint16 field at '%v' with stdlib flag pkg.", flagName)
337337
}
338-
p := f.Addr().Interface().(*uint16)
338+
p := (*uint16)(f.Addr().UnsafePointer())
339339
flags.uint16(p, flagName, shorthand, *p, flagHelp(ft))
340340
case reflect.Uint32:
341341
if !flags.pflag {
342342
return fmt.Errorf("cannot support uint32 field at '%v' with stdlib flag pkg.", flagName)
343343
}
344-
p := f.Addr().Interface().(*uint32)
344+
p := (*uint32)(f.Addr().UnsafePointer())
345345
flags.uint32(p, flagName, shorthand, *p, flagHelp(ft))
346346
case reflect.Uint8:
347347
if !flags.pflag {
348348
return fmt.Errorf("cannot support uint8 field at '%v' with stdlib flag pkg.", flagName)
349349
}
350-
p := f.Addr().Interface().(*uint8)
350+
p := (*uint8)(f.Addr().UnsafePointer())
351351
flags.uint8(p, flagName, shorthand, *p, flagHelp(ft))
352352
case reflect.Int8:
353353
if !flags.pflag {
354354
return fmt.Errorf("cannot support int8 field at '%v' with stdlib flag pkg.", flagName)
355355
}
356-
p := f.Addr().Interface().(*int8)
356+
p := (*int8)(f.Addr().UnsafePointer())
357357
flags.int8(p, flagName, shorthand, *p, flagHelp(ft))
358358
case reflect.Struct:
359359
var newprefix string

com_test.go

+23-9
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ func TestLoadEnv(t *testing.T) {
1818

1919
// create initial instance with defaults
2020
mm := &test.SimpleMain{
21-
One: "one",
22-
Two: 2,
23-
Three: 3,
24-
Four: true,
25-
Five: 5,
26-
Six: 6,
27-
Seven: 7.0,
28-
Eight: time.Millisecond * 8,
21+
One: "one",
22+
Two: 2,
23+
Three: 3,
24+
Four: true,
25+
Five: 5,
26+
Six: 6,
27+
Seven: 7.0,
28+
Eight: time.Millisecond * 8,
29+
Twelve: "blah",
2930
}
3031

3132
// create flags with defaults by walking instance
@@ -53,7 +54,7 @@ func TestLoadEnv(t *testing.T) {
5354
}
5455

5556
// change values on instance by parsing command line
56-
err = fs.Parse([]string{"-two", "99"})
57+
err = fs.Parse([]string{"-two", "99", "-twelve", "haha"})
5758
if err != nil {
5859
t.Fatalf("parsing command line: %v", err)
5960
}
@@ -65,6 +66,9 @@ func TestLoadEnv(t *testing.T) {
6566
if mm.One != "z" {
6667
t.Errorf("unexpected value for One after command line parsing: %s", mm.One)
6768
}
69+
if mm.Twelve != "haha" {
70+
t.Errorf("unexpected value for Twelve after cmd line parsing: %s", mm.Twelve)
71+
}
6872

6973
// simulate parsing a config file and setting values directly from it
7074
mm.Three = 33
@@ -562,4 +566,14 @@ func TestRunSimpleMain(t *testing.T) {
562566
} else {
563567
t.Fatalf("couldn't look up 'ten'")
564568
}
569+
if f := flags.Lookup("eleven"); f != nil {
570+
if f.DefValue != "11s" {
571+
t.Fatalf("wrong default value for 'eleven': %v", f.DefValue)
572+
}
573+
}
574+
if f := flags.Lookup("twelve"); f != nil {
575+
if f.DefValue != "twelve" {
576+
t.Fatalf("wrong default value for 'tweleve': %v", f.DefValue)
577+
}
578+
}
565579
}

test/test.go

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ func (m *MyMain) Run() error {
9494
return fmt.Errorf("mymain error")
9595
}
9696

97+
type WrappedString string
98+
9799
type SimpleMain struct {
98100
One string
99101
Two int
@@ -106,6 +108,7 @@ type SimpleMain struct {
106108
Nine []string
107109
Ten time.Time
108110
Eleven MyDuration
111+
Twelve WrappedString
109112
}
110113

111114
func NewSimpleMain() *SimpleMain {
@@ -121,6 +124,7 @@ func NewSimpleMain() *SimpleMain {
121124
Nine: []string{"9", "nine"},
122125
Ten: time.Unix(0, 0).UTC(),
123126
Eleven: MyDuration(time.Second * 11),
127+
Twelve: "twelve",
124128
}
125129
}
126130

0 commit comments

Comments
 (0)