package policy import ( "fmt" "strconv" "strings" "github.com/nspcc-dev/neofs-api-go/pkg/netmap" ) // Encode parses data of PlacementPolicy to a string. func Encode(p *netmap.PlacementPolicy) []string { if p == nil { return nil } var ( replicas = p.Replicas() selectors = p.Selectors() filters = p.Filters() ) // 1 for container backup factor result := make([]string, 0, len(replicas)+len(selectors)+len(filters)+1) // first print replicas encodeReplicas(replicas, &result) // then backup factor if backupFactor := p.ContainerBackupFactor(); backupFactor != 0 { result = append(result, fmt.Sprintf("CBF %d", backupFactor)) } // then selectors encodeSelectors(selectors, &result) // then filters encodeFilters(filters, &result) return result } func encodeReplicas(replicas []*netmap.Replica, dst *[]string) { builder := new(strings.Builder) for _, replica := range replicas { builder.WriteString("REP ") builder.WriteString(strconv.FormatUint(uint64(replica.Count()), 10)) if s := replica.Selector(); s != "" { builder.WriteString(" IN ") builder.WriteString(s) } *dst = append(*dst, builder.String()) builder.Reset() } } func encodeSelectors(selectors []*netmap.Selector, dst *[]string) { builder := new(strings.Builder) for _, selector := range selectors { builder.WriteString("SELECT ") builder.WriteString(strconv.FormatUint(uint64(selector.Count()), 10)) if a := selector.Attribute(); a != "" { builder.WriteString(" IN") switch selector.Clause() { case netmap.ClauseSame: builder.WriteString(" SAME ") case netmap.ClauseDistinct: builder.WriteString(" DISTINCT ") default: builder.WriteString(" ") } builder.WriteString(a) } if f := selector.Filter(); f != "" { builder.WriteString(" FROM ") builder.WriteString(f) } if n := selector.Name(); n != "" { builder.WriteString(" AS ") builder.WriteString(n) } *dst = append(*dst, builder.String()) builder.Reset() } } func encodeFilters(filters []*netmap.Filter, dst *[]string) { builder := new(strings.Builder) for _, filter := range filters { builder.WriteString("FILTER ") builder.WriteString(encodeFilter(filter)) *dst = append(*dst, builder.String()) builder.Reset() } } func encodeFilter(filter *netmap.Filter) string { builder := new(strings.Builder) unspecified := filter.Operation() == 0 if k := filter.Key(); k != "" { builder.WriteString(k) builder.WriteString(" ") builder.WriteString(filter.Operation().String()) builder.WriteString(" ") builder.WriteString(filter.Value()) } else if n := filter.Name(); unspecified && n != "" { builder.WriteString("@") builder.WriteString(n) } for i, subfilter := range filter.InnerFilters() { if i != 0 { builder.WriteString(" ") builder.WriteString(filter.Operation().String()) builder.WriteString(" ") } builder.WriteString(encodeFilter(subfilter)) } if n := filter.Name(); n != "" && !unspecified { builder.WriteString(" AS ") builder.WriteString(n) } return builder.String() }