package datavisor import ( "encoding/hex" "encoding/json" "errors" "os" "ripple/helpers" ) var errInvalidConfigFile = errors.New("invalid config file") type ( PortNumber int Username string ServerAddress string SecretKey [32]byte ) type configJSON struct { Port PortNumber `json:"port"` Username Username `json:"username"` ServerAddress ServerAddress `json:"serverAddress"` SecretKey SecretKey `json:"secretKey"` } func (sa *ServerAddress) UnmarshalJSON(b []byte) error { var raw string if err := json.Unmarshal(b, &raw); err != nil { return err } if len(raw) > 32 { return errInvalidConfigFile } *sa = ServerAddress(raw) return nil } func (pn *PortNumber) UnmarshalJSON(b []byte) error { var n int if err := json.Unmarshal(b, &n); err != nil { return err } if n < 1 || n > 65535 { return errInvalidConfigFile } *pn = PortNumber(n) return nil } func (u *Username) UnmarshalJSON(b []byte) error { var raw string if err := json.Unmarshal(b, &raw); err != nil { return err } if !helpers.UsernameRegex.MatchString(raw) { return errInvalidConfigFile } *u = Username(raw) return nil } func (sk *SecretKey) UnmarshalJSON(b []byte) error { var raw string if err := json.Unmarshal(b, &raw); err != nil { return err } decoded, err := hex.DecodeString(raw) if err != nil || len(decoded) != 32 { return errInvalidConfigFile } copy(sk[:], decoded) return nil } func (cfg *configJSON) validateAddress() error { return helpers.ValidateAddress(string(cfg.ServerAddress), int(cfg.Port)) } func loadConfigFile(filePath string) (*configJSON, error) { data, err := os.ReadFile(filePath) if err != nil { return nil, err } var cfg configJSON if err := json.Unmarshal(data, &cfg); err != nil { return nil, err } if err := cfg.validateAddress(); err != nil { return nil, err } return &cfg, nil }