Add string Parser to x/tools/stringer

159 views
Skip to first unread message

Diego Augusto Molina

unread,
Jun 7, 2020, 3:04:21 PM6/7/20
to golang-nuts
Very often I use the stringer command to generate lists of enumerated values, which is great btw.
But one thing that I see myself also writing after this is a Parse method or function to validate strings that are received.
The use case is that I have a list of possible values for a controlled field in a RESTful API. I receive and deliver string values from the API by I have a tight control inside the API itself.
I declare a new type (generally an uint8 alias) and then declare a bunch of auto incremental constants, starting with the zero value that I always set to "Invalid" which is used as a control value.
The stringer command makes the dull work but immediately after I write a Parse function or method. The following is a full example:
//go:generate stringer -linecomment -output=enum_string.go -type=MyEnum
package enum

type
MyEnum uint8

const (
   
// Reserved for internal use
   
MyEnumInvalid MyEnum = iota // Invalid

   
MyEnumValue1 // Value #1
   
MyEnumValue2 // Value #2
   
MyEnumValue3 // Value #3
   
MyEnumValue4 // Value #4
   
MyEnumValue5 // Value #5
)

func
(e *MyEnum) Parse(value string) MyEnum {
   
for lenIdx, lenVal, i := len(_MyEnum_index), uint8(len(value)), 1; i < lenIdx; i++ {
       
if _MyEnum_index[i]-_MyEnum_index[i-1] == lenVal && // Maybe too small optimization to be perceptible/useful(?)
            _MyEnum_name
[_MyEnum_index[i-1]:_MyEnum_index[i]] == value {
           
*e = MyEnum(i - 1)
           
return *e
       
}
   
}
   
return MyEnum(0)
}

So this couples a lot to my workflow, of course. This way I can do something like:
receivedVal = new(MyEnum).Parse(receivedStr)
Or:
var val *MyEnum
for _, strVal := range strValues {
    if val.Parse(strVal) ==
MyEnumInvalid {
        return fmt.Errorf("Invalid value for enum: %v", strVal)
    }
}

So I started to write this function within the stringer command, which I modified to do so. So I don't know if this is for some use to the community. I know that in order for it to be useful to everyone it should be more general. So I'm looking at alternatives and, of course, if it's worth working on that. I it would be of some use there are two alternatives where this could live:
  • As an option to the stringer command
  • As a separate command (because it would exceed the stringer interface and would be misleading, since "Parse" is not part of the "Stringer" interface)
And I'm only using here the stringer command to create series of consecutive numbers, so I would need to write extra code to fulfill the sparsiness of values (cases where stringer creates up to 10 different slices and after that just creates a map). It wouldn't be much work, actually, just read the code in the command.
And instead of writing a new method for the type (breaking the idea of the "stringer" interface), I thought it could just be a "ParseT" function.

Thoughts? Comments? Should I keep it for myself (hahaha)?

Ian Lance Taylor

unread,
Jun 8, 2020, 5:39:40 PM6/8/20
to Diego Augusto Molina, golang-nuts
There are many different possible enhancements that can be made to
stringer. We've decided to keep the tool simple rather than add
additional knobs. Thanks.

I encourage you to make your tool available for anybody who wants to use it.

Ian
Reply all
Reply to author
Forward
0 new messages