Use strings.Cut instead of strings.Split* where possible #76

Merged
acid-ant merged 1 commit from improve/65-use-cut-insteadof-split into master 2023-02-28 10:39:15 +00:00
11 changed files with 69 additions and 72 deletions
Showing only changes of commit 95e799ed05 - Show all commits

View file

@ -141,13 +141,13 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
} }
func parseConfigPair(kvStr string, force bool) (key string, val any, err error) { func parseConfigPair(kvStr string, force bool) (key string, val any, err error) {
kv := strings.SplitN(kvStr, "=", 2) k, v, found := strings.Cut(kvStr, "=")
if len(kv) != 2 { if !found {
return "", nil, fmt.Errorf("invalid parameter format: must be 'key=val', got: %s", kvStr) return "", nil, fmt.Errorf("invalid parameter format: must be 'key=val', got: %s", kvStr)
} }
key = kv[0] key = k
valRaw := kv[1] valRaw := v
switch key { switch key {
case netmapAuditFeeKey, netmapBasicIncomeRateKey, case netmapAuditFeeKey, netmapBasicIncomeRateKey,
@ -162,7 +162,7 @@ func parseConfigPair(kvStr string, force bool) (key string, val any, err error)
case netmapEigenTrustAlphaKey: case netmapEigenTrustAlphaKey:
// just check that it could // just check that it could
// be parsed correctly // be parsed correctly
_, err = strconv.ParseFloat(kv[1], 64) _, err = strconv.ParseFloat(v, 64)
if err != nil { if err != nil {
err = fmt.Errorf("could not parse %s's value '%s' as float: %w", key, valRaw, err) err = fmt.Errorf("could not parse %s's value '%s' as float: %w", key, valRaw, err)
} }

View file

@ -27,23 +27,23 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error {
bw := io.NewBufBinWriter() bw := io.NewBufBinWriter()
for i := range args { for i := range args {
kv := strings.SplitN(args[i], "=", 2) k, v, found := strings.Cut(args[i], "=")
if len(kv) != 2 { if !found {
return fmt.Errorf("invalid parameter format, must be Parameter=Value") return fmt.Errorf("invalid parameter format, must be Parameter=Value")
} }
switch kv[0] { switch k {
case execFeeParam, storagePriceParam, setFeeParam: case execFeeParam, storagePriceParam, setFeeParam:
default: default:
return fmt.Errorf("parameter must be one of %s, %s and %s", execFeeParam, storagePriceParam, setFeeParam) return fmt.Errorf("parameter must be one of %s, %s and %s", execFeeParam, storagePriceParam, setFeeParam)
} }
value, err := strconv.ParseUint(kv[1], 10, 32) value, err := strconv.ParseUint(v, 10, 32)
if err != nil { if err != nil {
return fmt.Errorf("can't parse parameter value '%s': %w", args[1], err) return fmt.Errorf("can't parse parameter value '%s': %w", args[1], err)
} }
emit.AppCall(bw.BinWriter, policy.Hash, "set"+kv[0], callflag.All, int64(value)) emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value))
} }
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil { if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil {

View file

@ -197,12 +197,12 @@ func parseContainerPolicy(cmd *cobra.Command, policyString string) (*netmap.Plac
func parseAttributes(dst *container.Container, attributes []string) error { func parseAttributes(dst *container.Container, attributes []string) error {
for i := range attributes { for i := range attributes {
kvPair := strings.Split(attributes[i], attributeDelimiter) k, v, found := strings.Cut(attributes[i], attributeDelimiter)
if len(kvPair) != 2 { if !found {
return errors.New("invalid container attribute") return errors.New("invalid container attribute")
} }
dst.SetAttribute(kvPair[0], kvPair[1]) dst.SetAttribute(k, v)
} }
if !containerNoTimestamp { if !containerNoTimestamp {
dstepanov-yadro commented 2023-02-27 14:52:25 +00:00 (Migrated from github.com)
Review

I suppose attribute key=value=value is not valid, but after this it will pass check.
image

I suppose attribute `key=value=value` is not valid, but after this it will pass check. ![image](https://user-images.githubusercontent.com/125876766/221595977-22eb48c8-171e-490d-b4f7-96d661bae234.png)
acid-ant commented 2023-02-28 07:02:19 +00:00 (Migrated from github.com)
Review

Agree, but there are no restriction in the sdk for the content of the key or value. it should be non empty only. The idea of the cli is to be as simple as it can, @fyrchik correct me if I'm wrong.

Agree, but there are no restriction in the sdk for the content of the key or value. it should be non empty only. The idea of the cli is to be as simple as it can, @fyrchik correct me if I'm wrong.
fyrchik commented 2023-02-28 07:22:27 +00:00 (Migrated from github.com)
Review

Most likely, it was a bug. API gives no restrictions on container value https://github.com/TrueCloudLab/frostfs-api/blob/master/container/types.proto#L30

Most likely, it was a bug. API gives no restrictions on container value https://github.com/TrueCloudLab/frostfs-api/blob/master/container/types.proto#L30

View file

@ -179,12 +179,12 @@ func parseObjectAttrs(cmd *cobra.Command) ([]object.Attribute, error) {
attrs := make([]object.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes attrs := make([]object.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes
for i := range rawAttrs { for i := range rawAttrs {
kv := strings.SplitN(rawAttrs[i], "=", 2) k, v, found := strings.Cut(rawAttrs[i], "=")
if len(kv) != 2 { if !found {
return nil, fmt.Errorf("invalid attribute format: %s", rawAttrs[i]) return nil, fmt.Errorf("invalid attribute format: %s", rawAttrs[i])
} }
attrs[i].SetKey(kv[0]) attrs[i].SetKey(k)
attrs[i].SetValue(kv[1]) attrs[i].SetValue(v)
} }
disableFilename, _ := cmd.Flags().GetBool("disable-filename") disableFilename, _ := cmd.Flags().GetBool("disable-filename")
@ -218,26 +218,26 @@ func parseObjectNotifications(cmd *cobra.Command) (*object.NotificationInfo, err
return nil, nil return nil, nil
} }
rawSlice := strings.SplitN(raw, separator, 2) before, after, found := strings.Cut(raw, separator)
if len(rawSlice) != 2 { if !found {
return nil, fmt.Errorf("notification must be in the form of: *epoch*%s*topic*, got %s", separator, raw) return nil, fmt.Errorf("notification must be in the form of: *epoch*%s*topic*, got %s", separator, raw)
} }
ni := new(object.NotificationInfo) ni := new(object.NotificationInfo)
epoch, err := strconv.ParseUint(rawSlice[0], 10, 64) epoch, err := strconv.ParseUint(before, 10, 64)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not parse notification epoch %s: %w", rawSlice[0], err) return nil, fmt.Errorf("could not parse notification epoch %s: %w", before, err)
} }
ni.SetEpoch(epoch) ni.SetEpoch(epoch)
if rawSlice[1] == "" { if after == "" {
return nil, fmt.Errorf("incorrect empty topic: use %s to force using default topic", useDefaultTopic) return nil, fmt.Errorf("incorrect empty topic: use %s to force using default topic", useDefaultTopic)
} }
if rawSlice[1] != useDefaultTopic { if after != useDefaultTopic {
ni.SetTopic(rawSlice[1]) ni.SetTopic(after)
} }
return ni, nil return ni, nil

View file

@ -154,16 +154,16 @@ func getRangeList(cmd *cobra.Command) ([]*object.Range, error) {
vs := strings.Split(v, ",") vs := strings.Split(v, ",")
rs := make([]*object.Range, len(vs)) rs := make([]*object.Range, len(vs))
for i := range vs { for i := range vs {
r := strings.Split(vs[i], rangeSep) before, after, found := strings.Cut(vs[i], rangeSep)
if len(r) != 2 { if !found {
return nil, fmt.Errorf("invalid range specifier: %s", vs[i]) return nil, fmt.Errorf("invalid range specifier: %s", vs[i])
} }
offset, err := strconv.ParseUint(r[0], 10, 64) offset, err := strconv.ParseUint(before, 10, 64)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid '%s' range offset specifier: %w", vs[i], err) return nil, fmt.Errorf("invalid '%s' range offset specifier: %w", vs[i], err)
} }
length, err := strconv.ParseUint(r[1], 10, 64) length, err := strconv.ParseUint(after, 10, 64)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid '%s' range length specifier: %w", vs[i], err) return nil, fmt.Errorf("invalid '%s' range length specifier: %w", vs[i], err)
} }

View file

@ -63,12 +63,12 @@ func parseXHeaders(cmd *cobra.Command) []string {
xs := make([]string, 0, 2*len(xHeaders)) xs := make([]string, 0, 2*len(xHeaders))
for i := range xHeaders { for i := range xHeaders {
kv := strings.SplitN(xHeaders[i], "=", 2) k, v, found := strings.Cut(xHeaders[i], "=")
if len(kv) != 2 { if !found {
panic(fmt.Errorf("invalid X-Header format: %s", xHeaders[i])) panic(fmt.Errorf("invalid X-Header format: %s", xHeaders[i]))
} }
xs = append(xs, kv[0], kv[1]) xs = append(xs, k, v)
} }
return xs return xs

View file

@ -79,14 +79,14 @@ func parseMeta(cmd *cobra.Command) ([]*tree.KeyValue, error) {
pairs := make([]*tree.KeyValue, 0, len(raws)) pairs := make([]*tree.KeyValue, 0, len(raws))
for i := range raws { for i := range raws {
kv := strings.SplitN(raws[i], "=", 2) k, v, found := strings.Cut(raws[i], "=")
if len(kv) != 2 { if !found {
return nil, fmt.Errorf("invalid meta pair format: %s", raws[i]) return nil, fmt.Errorf("invalid meta pair format: %s", raws[i])
} }
var pair tree.KeyValue var pair tree.KeyValue
pair.Key = kv[0] pair.Key = k
pair.Value = []byte(kv[1]) pair.Value = []byte(v)
pairs = append(pairs, &pair) pairs = append(pairs, &pair)
} }

View file

@ -226,35 +226,32 @@ func parseEACLTable(tb *eacl.Table, args []string) error {
fyrchik commented 2023-02-28 07:29:08 +00:00 (Migrated from github.com)
Review

Can use Cut here too.

Can use `Cut` here too.
acid-ant commented 2023-02-28 08:12:06 +00:00 (Migrated from github.com)
Review

Done.

Done.
func parseEACLRecord(args []string) (*eacl.Record, error) { func parseEACLRecord(args []string) (*eacl.Record, error) {
r := new(eacl.Record) r := new(eacl.Record)
for i := range args { for _, arg := range args {
ss := strings.SplitN(args[i], ":", 2) before, after, found := strings.Cut(arg, ":")
switch prefix := strings.ToLower(ss[0]); prefix { switch prefix := strings.ToLower(before); prefix {
case "req", "obj": // filters case "req", "obj": // filters
if len(ss) != 2 { if !found {
return nil, fmt.Errorf("invalid filter or target: %s", args[i]) return nil, fmt.Errorf("invalid filter or target: %s", arg)
}
i := strings.Index(ss[1], "=")
if i < 0 {
return nil, fmt.Errorf("invalid filter key-value pair: %s", ss[1])
} }
var key, value string var key, value string
var op eacl.Match var op eacl.Match
var f bool
if 0 < i && ss[1][i-1] == '!' { key, value, f = strings.Cut(after, "!=")
key = ss[1][:i-1] if f {
op = eacl.MatchStringNotEqual op = eacl.MatchStringNotEqual
} else { } else {
key = ss[1][:i] key, value, f = strings.Cut(after, "=")
if !f {
return nil, fmt.Errorf("invalid filter key-value pair: %s", after)
}
op = eacl.MatchStringEqual op = eacl.MatchStringEqual
} }
value = ss[1][i+1:]
typ := eacl.HeaderFromRequest typ := eacl.HeaderFromRequest
if ss[0] == "obj" { if before == "obj" {
typ = eacl.HeaderFromObject typ = eacl.HeaderFromObject
} }
@ -263,8 +260,8 @@ func parseEACLRecord(args []string) (*eacl.Record, error) {
var err error var err error
var pubs []ecdsa.PublicKey var pubs []ecdsa.PublicKey
if len(ss) == 2 { if found {
pubs, err = parseKeyList(ss[1]) pubs, err = parseKeyList(after)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -281,7 +278,7 @@ func parseEACLRecord(args []string) (*eacl.Record, error) {
eacl.AddFormedTarget(r, role, pubs...) eacl.AddFormedTarget(r, role, pubs...)
default: default:
return nil, fmt.Errorf("invalid prefix: %s", ss[0]) return nil, fmt.Errorf("invalid prefix: %s", before)
} }
} }

View file

@ -65,14 +65,14 @@ func loadEnv(path string) {
scanner := bufio.NewScanner(f) scanner := bufio.NewScanner(f)
for scanner.Scan() { for scanner.Scan() {
pair := strings.SplitN(scanner.Text(), "=", 2) k, v, found := strings.Cut(scanner.Text(), "=")
if len(pair) != 2 { if !found {
continue continue
} }
pair[1] = strings.Trim(pair[1], `"`) v = strings.Trim(v, `"`)
err = os.Setenv(pair[0], pair[1]) err = os.Setenv(k, v)
if err != nil { if err != nil {
panic("can't set environment variable") panic("can't set environment variable")
} }

View file

@ -73,18 +73,18 @@ func stringifyAddress(addr oid.Address) string {
} }
func addressFromString(s string) (oid.Address, error) { func addressFromString(s string) (oid.Address, error) {
i := strings.IndexByte(s, '.') before, after, found := strings.Cut(s, ".")
if i == -1 { if !found {
return oid.Address{}, errors.New("invalid address") return oid.Address{}, errors.New("invalid address")
} }
var obj oid.ID var obj oid.ID
if err := obj.DecodeString(s[:i]); err != nil { if err := obj.DecodeString(before); err != nil {
return oid.Address{}, err return oid.Address{}, err
} }
var cnr cid.ID var cnr cid.ID
if err := cnr.DecodeString(s[i+1:]); err != nil { if err := cnr.DecodeString(after); err != nil {
return oid.Address{}, err return oid.Address{}, err
} }

View file

@ -19,29 +19,29 @@ func ReadNodeAttributes(dst *netmap.NodeInfo, attrs []string) error {
for i := range attrs { for i := range attrs {
line := replaceEscaping(attrs[i], false) // replaced escaped symbols with non-printable symbols line := replaceEscaping(attrs[i], false) // replaced escaped symbols with non-printable symbols
words := strings.Split(line, keyValueSeparator) k, v, found := strings.Cut(line, keyValueSeparator)
if len(words) != 2 { if !found {
return errors.New("missing attribute key and/or value") return errors.New("missing attribute key and/or value")
} }
dstepanov-yadro commented 2023-02-27 15:00:21 +00:00 (Migrated from github.com)
Review

Maybe if !found || len(k) == 0 || len(v) == 0 will be better?

Maybe `if !found || len(k) == 0 || len(v) == 0` will be better?
acid-ant commented 2023-02-28 08:04:47 +00:00 (Migrated from github.com)
Review

We already have this check in sdk.

We already have this check in sdk.
_, ok := cache[words[0]] _, ok := cache[k]
if ok { if ok {
return fmt.Errorf("duplicated keys %s", words[0]) return fmt.Errorf("duplicated keys %s", k)
} }
cache[words[0]] = struct{}{} cache[k] = struct{}{}
// replace non-printable symbols with escaped symbols without escape character // replace non-printable symbols with escaped symbols without escape character
words[0] = replaceEscaping(words[0], true) k = replaceEscaping(k, true)
words[1] = replaceEscaping(words[1], true) v = replaceEscaping(v, true)
if words[0] == "" { if k == "" {
return errors.New("empty key") return errors.New("empty key")
} else if words[1] == "" { } else if v == "" {
return errors.New("empty value") return errors.New("empty value")
} }
dst.SetAttribute(words[0], words[1]) dst.SetAttribute(k, v)
} }
return nil return nil