110 lines · 2.3 KB · Go
RawDownload
package fs import (	"encoding/json"	"fmt"	"strings") // Enum is an option which can only be one of the Choices.//// Suggested implementation is something like this:////	type choice = Enum[choices]////	const (//		choiceA choice = iota//		choiceB//		choiceC//	)////	type choices struct{}////	func (choices) Choices() []string {//		return []string{//			choiceA: "A",//			choiceB: "B",//			choiceC: "C",//		}//	}type Enum[C Choices] byte // Choices returns the valid choices for this type.//// It must work on the zero value.//// Note that when using this in an Option the ExampleChoices will be// filled in automatically.type Choices interface {	// Choices returns the valid choices for this type	Choices() []string} // String renders the Enum as a stringfunc (e Enum[C]) String() string {	choices := e.Choices()	if int(e) >= len(choices) {		return fmt.Sprintf("Unknown(%d)", e)	}	return choices[e]} // Choices returns the possible values of the Enum.func (e Enum[C]) Choices() []string {	var c C	return c.Choices()} // Help returns a comma separated list of all possible states.func (e Enum[C]) Help() string {	return strings.Join(e.Choices(), ", ")} // Set the Enum entriesfunc (e *Enum[C]) Set(s string) error {	for i, choice := range e.Choices() {		if strings.EqualFold(s, choice) {			*e = Enum[C](i)			return nil		}	}	return fmt.Errorf("invalid choice %q from: %s", s, e.Help())} // Type of the value.//// If C has a Type() string method then it will be used instead.func (e Enum[C]) Type() string {	var c C	if do, ok := any(c).(typer); ok {		return do.Type()	}	return strings.Join(e.Choices(), "|")} // Scan implements the fmt.Scanner interfacefunc (e *Enum[C]) Scan(s fmt.ScanState, ch rune) error {	token, err := s.Token(true, nil)	if err != nil {		return err	}	return e.Set(string(token))} // UnmarshalJSON parses it as a string or an integerfunc (e *Enum[C]) UnmarshalJSON(in []byte) error {	choices := e.Choices()	return UnmarshalJSONFlag(in, e, func(i int64) error {		if i < 0 || i >= int64(len(choices)) {			return fmt.Errorf("%d is out of range: must be 0..%d", i, len(choices))		}		*e = Enum[C](i)		return nil	}) } // MarshalJSON encodes it as stringfunc (e *Enum[C]) MarshalJSON() ([]byte, error) {	return json.Marshal(e.String())}