From d8b12a2871187fe3e87eedfda866f877a9d516386b1de58776ce1065cd92bfc3 Mon Sep 17 00:00:00 2001 From: LixenWraith Date: Wed, 23 Apr 2025 00:34:15 -0400 Subject: [PATCH] e1.0.1 Minor feature to register config with struct tag. --- cmd/main.go | 2 -- config.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 8d24a02..3458462 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -207,7 +207,6 @@ func printLogConfig(cfg LogConfig) { func verifyConfig(cfg LogConfig) { allCorrect := true - // Check each modified value if cfg.Level != 2 { fmt.Printf("ERROR: Level is %d, expected 2\n", cfg.Level) allCorrect = false @@ -238,7 +237,6 @@ func verifyConfig(cfg LogConfig) { allCorrect = false } - // Check that unmodified values retained their defaults if cfg.Directory != "./logs" { fmt.Printf("ERROR: Directory changed to %s, expected './logs'\n", cfg.Directory) allCorrect = false diff --git a/config.go b/config.go index 512e608..3c888ef 100644 --- a/config.go +++ b/config.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path/filepath" + "reflect" "strconv" "strings" "sync" @@ -84,6 +85,75 @@ func (c *Config) Unregister(path string) error { return nil } +// RegisterStruct registers configuration values derived from a struct. +// It uses struct tags to determine the configuration paths. +// The prefix is prepended to all paths (e.g., "log."). +func (c *Config) RegisterStruct(prefix string, structWithDefaults interface{}) error { + v := reflect.ValueOf(structWithDefaults) + + // Handle pointer or direct struct value + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + if v.Kind() != reflect.Struct { + return fmt.Errorf("RegisterStruct requires a struct, got %T", structWithDefaults) + } + + t := v.Type() + var firstErr error + + for i := 0; i < v.NumField(); i++ { + field := t.Field(i) + fieldValue := v.Field(i) + + // Skip unexported fields + if !field.IsExported() { + continue + } + + // Get tag value or use field name + tag := field.Tag.Get("toml") + if tag == "-" { + continue // Skip this field + } + + // Extract tag name or use field name + key := field.Name + if tag != "" { + parts := strings.Split(tag, ",") + if parts[0] != "" { + key = parts[0] + } + } + + // Build full path + path := prefix + key + + // Register this field + if err := c.Register(path, fieldValue.Interface()); err != nil && firstErr == nil { + firstErr = err + } + } + + return firstErr +} + +// GetRegisteredPaths returns all registered configuration paths with the specified prefix. +func (c *Config) GetRegisteredPaths(prefix string) map[string]bool { + c.mutex.RLock() + defer c.mutex.RUnlock() + + result := make(map[string]bool) + for path := range c.items { + if strings.HasPrefix(path, prefix) { + result[path] = true + } + } + + return result +} + // Get retrieves a configuration value using the path. // It returns the current value (or default if not explicitly set). // The second return value indicates if the path was registered.