package params import ( "fmt" "google.golang.org/protobuf/types/known/structpb" ) // Reader provides typed helpers around a Struct param payload. type Reader struct { raw map[string]interface{} } // New builds a Reader for the provided struct, tolerating nil inputs. func New(params *structpb.Struct) Reader { if params == nil { return Reader{} } return Reader{raw: params.AsMap()} } // Value returns the raw value and whether it was present. func (r Reader) Value(key string) (interface{}, bool) { if r.raw == nil { return nil, false } value, ok := r.raw[key] return value, ok } // String returns the string value for a key, or "" if missing/not a string. func (r Reader) String(key string) string { value, ok := r.Value(key) if !ok { return "" } switch v := value.(type) { case string: return v case fmt.Stringer: return v.String() default: return "" } } // Bool returns the bool value for a key, or false when missing/not a bool. func (r Reader) Bool(key string) bool { value, ok := r.Value(key) if !ok { return false } switch v := value.(type) { case bool: return v default: return false } } // Int64 returns the int64 value for a key with a presence flag. func (r Reader) Int64(key string) (int64, bool) { value, ok := r.Value(key) if !ok { return 0, false } switch v := value.(type) { case int64: return v, true case int32: return int64(v), true case int: return int64(v), true case float64: return int64(v), true case float32: return int64(v), true default: return 0, false } } // Float64 returns the float64 value for a key with a presence flag. func (r Reader) Float64(key string) (float64, bool) { value, ok := r.Value(key) if !ok { return 0, false } switch v := value.(type) { case float64: return v, true case float32: return float64(v), true case int: return float64(v), true case int64: return float64(v), true default: return 0, false } } // Map returns a nested object value as a map. func (r Reader) Map(key string) map[string]interface{} { value, ok := r.Value(key) if !ok { return nil } if m, ok := value.(map[string]interface{}); ok { return m } return nil } // List returns a list value as a slice. func (r Reader) List(key string) []interface{} { value, ok := r.Value(key) if !ok { return nil } if list, ok := value.([]interface{}); ok { return list } return nil } // StringMap converts a nested map into a string map. func (r Reader) StringMap(key string) map[string]string { raw := r.Map(key) if len(raw) == 0 { return nil } out := make(map[string]string, len(raw)) for k, v := range raw { out[k] = fmt.Sprint(v) } return out }