func convertToAPI(src *storagepb.Config) *quotapb.Config {
	dest := &quotapb.Config{
		Name:      src.Name,
		State:     quotapb.Config_State(quotapb.Config_State_value[src.State.String()]),
		MaxTokens: src.MaxTokens,
	}
	sb := src.GetSequencingBased()
	tb := src.GetTimeBased()
	switch {
	case sb != nil:
		dest.ReplenishmentStrategy = &quotapb.Config_SequencingBased{
			SequencingBased: &quotapb.SequencingBasedStrategy{},
		}
	case tb != nil:
		dest.ReplenishmentStrategy = &quotapb.Config_TimeBased{
			TimeBased: &quotapb.TimeBasedStrategy{
				TokensToReplenish:        tb.TokensToReplenish,
				ReplenishIntervalSeconds: tb.ReplenishIntervalSeconds,
			},
		}
	}
	return dest
}
convertToAPI returns the API representation of a storagepb.Config proto.
package quotaapi
import (
	"fmt"
	"github.com/google/trillian/quota/etcd/quotapb"
	"github.com/google/trillian/quota/etcd/storagepb"
	"google.golang.org/genproto/protobuf/field_mask"
)
const (
	statePath           = "state"
	maxTokensPath       = "max_tokens"
	sequencingBasedPath = "sequencing_based"
	timeBasedPath       = "time_based"
)
var (
	commonMask          = &field_mask.FieldMask{Paths: []string{statePath, maxTokensPath}}
	sequencingBasedMask = &field_mask.FieldMask{Paths: append(commonMask.Paths, sequencingBasedPath)}
	timeBasedMask       = &field_mask.FieldMask{Paths: append(commonMask.Paths, timeBasedPath)}
	errBothReplenishmentStrategies = fmt.Errorf("both %q and %q paths specified, please pick a single replenishment strategy", sequencingBasedPath, timeBasedPath)
)
func validateMask(mask *field_mask.FieldMask) error {
	sequencingBasedFound := false
	timeBasedFound := false
	for _, path := range mask.Paths {
		switch path {
		case statePath, maxTokensPath:
		case sequencingBasedPath:
			if timeBasedFound {
				return errBothReplenishmentStrategies
			}
			sequencingBasedFound = true
		case timeBasedPath:
			if sequencingBasedFound {
				return errBothReplenishmentStrategies
			}
			timeBasedFound = true
		default:
			return fmt.Errorf("invalid field path for Config: %q", path)
		}
	}
	return nil
}
func applyMask(src *quotapb.Config, dest *storagepb.Config, mask *field_mask.FieldMask) {
	for _, path := range mask.Paths {
		switch path {
		case statePath:
			dest.State = storagepb.Config_State(storagepb.Config_State_value[src.State.String()])
		case maxTokensPath:
			dest.MaxTokens = src.MaxTokens
		case sequencingBasedPath:
			if src.GetSequencingBased() == nil {
				dest.ReplenishmentStrategy = nil
			} else {
				dest.ReplenishmentStrategy = &storagepb.Config_SequencingBased{
					SequencingBased: &storagepb.SequencingBasedStrategy{},
				}
			}
		case timeBasedPath:
			if tb := src.GetTimeBased(); tb == nil {
				dest.ReplenishmentStrategy = nil
			} else {
				dest.ReplenishmentStrategy = &storagepb.Config_TimeBased{
					TimeBased: &storagepb.TimeBasedStrategy{
						TokensToReplenish:        tb.GetTokensToReplenish(),
						ReplenishIntervalSeconds: tb.GetReplenishIntervalSeconds(),
					},
				}
			}
		}
	}
}