Initial QSfera import
This commit is contained in:
+140
@@ -0,0 +1,140 @@
|
||||
package lx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Field represents a key-value pair where the key is a string and the value is of any type.
|
||||
type Field struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// Fields represents a slice of key-value pairs.
|
||||
type Fields []Field
|
||||
|
||||
// Map converts the Fields slice to a map[string]interface{}.
|
||||
// This is useful for backward compatibility or when map operations are needed.
|
||||
// Example:
|
||||
//
|
||||
// fields := lx.Fields{{"user", "alice"}, {"age", 30}}
|
||||
// m := fields.Map() // Returns map[string]interface{}{"user": "alice", "age": 30}
|
||||
func (f Fields) Map() map[string]interface{} {
|
||||
m := make(map[string]interface{}, len(f))
|
||||
for _, pair := range f {
|
||||
m[pair.Key] = pair.Value
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Get returns the value for a given key and a boolean indicating if the key was found.
|
||||
// This provides O(n) lookup, which is fine for small numbers of fields.
|
||||
// Example:
|
||||
//
|
||||
// fields := lx.Fields{{"user", "alice"}, {"age", 30}}
|
||||
// value, found := fields.Get("user") // Returns "alice", true
|
||||
func (f Fields) Get(key string) (interface{}, bool) {
|
||||
for _, pair := range f {
|
||||
if pair.Key == key {
|
||||
return pair.Value, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Filter returns a new Fields slice containing only pairs where the predicate returns true.
|
||||
// Example:
|
||||
//
|
||||
// fields := lx.Fields{{"user", "alice"}, {"password", "secret"}, {"age", 30}}
|
||||
// filtered := fields.Filter(func(key string, value interface{}) bool {
|
||||
// return key != "password" // Remove sensitive fields
|
||||
// })
|
||||
func (f Fields) Filter(predicate func(key string, value interface{}) bool) Fields {
|
||||
result := make(Fields, 0, len(f))
|
||||
for _, pair := range f {
|
||||
if predicate(pair.Key, pair.Value) {
|
||||
result = append(result, pair)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Translate returns a new Fields slice with keys translated according to the provided mapping.
|
||||
// Keys not in the mapping are passed through unchanged. This is useful for adapters like Victoria.
|
||||
// Example:
|
||||
//
|
||||
// fields := lx.Fields{{"user", "alice"}, {"timestamp", time.Now()}}
|
||||
// translated := fields.Translate(map[string]string{
|
||||
// "user": "username",
|
||||
// "timestamp": "ts",
|
||||
// })
|
||||
// // Returns: {{"username", "alice"}, {"ts", time.Now()}}
|
||||
func (f Fields) Translate(mapping map[string]string) Fields {
|
||||
result := make(Fields, len(f))
|
||||
for i, pair := range f {
|
||||
if newKey, ok := mapping[pair.Key]; ok {
|
||||
result[i] = Field{Key: newKey, Value: pair.Value}
|
||||
} else {
|
||||
result[i] = pair
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Merge merges another Fields slice into this one, with the other slice's fields taking precedence
|
||||
// for duplicate keys (overwrites existing keys).
|
||||
// Example:
|
||||
//
|
||||
// base := lx.Fields{{"user", "alice"}, {"age", 30}}
|
||||
// additional := lx.Fields{{"age", 31}, {"city", "NYC"}}
|
||||
// merged := base.Merge(additional)
|
||||
// // Returns: {{"user", "alice"}, {"age", 31}, {"city", "NYC"}}
|
||||
func (f Fields) Merge(other Fields) Fields {
|
||||
result := make(Fields, 0, len(f)+len(other))
|
||||
|
||||
// Create a map to track which keys from 'other' we've seen
|
||||
seen := make(map[string]bool, len(other))
|
||||
|
||||
// First add all fields from 'f'
|
||||
result = append(result, f...)
|
||||
|
||||
// Then add fields from 'other', overwriting duplicates
|
||||
for _, pair := range other {
|
||||
// Check if this key already exists in result
|
||||
found := false
|
||||
for i, existing := range result {
|
||||
if existing.Key == pair.Key {
|
||||
result[i] = pair // Overwrite
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
result = append(result, pair)
|
||||
}
|
||||
seen[pair.Key] = true
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// String returns a human-readable string representation of the fields.
|
||||
// Example:
|
||||
//
|
||||
// fields := lx.Fields{{"user", "alice"}, {"age", 30}}
|
||||
// str := fields.String() // Returns: "[user=alice age=30]"
|
||||
func (f Fields) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString(LeftBracket)
|
||||
for i, pair := range f {
|
||||
if i > 0 {
|
||||
builder.WriteString(Space)
|
||||
}
|
||||
builder.WriteString(pair.Key)
|
||||
builder.WriteString("=")
|
||||
builder.WriteString(fmt.Sprint(pair.Value))
|
||||
}
|
||||
builder.WriteString(RightBracket)
|
||||
return builder.String()
|
||||
}
|
||||
Reference in New Issue
Block a user