Skip to content

Commit

Permalink
feat: Improve UnmarshalJSON error handling and type checking
Browse files Browse the repository at this point in the history
Signed-off-by: haitwang-cloud <haitao_wht@outlook.com>
  • Loading branch information
haitwang-cloud committed May 7, 2024
1 parent ee0417e commit 2bf4592
Showing 1 changed file with 27 additions and 32 deletions.
59 changes: 27 additions & 32 deletions api/config/v1/replicas.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,29 +269,22 @@ func (s *ReplicatedResource) UnmarshalJSON(b []byte) error {

// UnmarshalJSON unmarshals raw bytes into a 'ReplicatedDevices' struct.
func (s *ReplicatedDevices) UnmarshalJSON(b []byte) error {
var target interface{}
if err := json.Unmarshal(b, &target); err != nil {
return fmt.Errorf("unrecognized type for devices spec: %w", err)
var str string
if err := json.Unmarshal(b, &str); err == nil {
return handleStringInput(str, s)
}

switch t := target.(type) {
case string:
if err := handleStringInput(t, s); err != nil {
return err
}
case float64:
if err := handleFloatInput(int(t), s); err != nil {
return err
}
case []interface{}:
if err := handleListInput(t, s); err != nil {
return err
}
default:
return fmt.Errorf("unsupported type for devices spec: %T", target)
var count int
if err := json.Unmarshal(b, &count); err == nil {
return handleIntInput(count, s)
}

return nil
var slice []json.RawMessage
if err := json.Unmarshal(b, &slice); err == nil {
return handleListInput(slice, s)
}

return fmt.Errorf("unrecognized type for devices spec: %s", string(b))
}

func handleStringInput(str string, s *ReplicatedDevices) error {
Expand All @@ -302,30 +295,32 @@ func handleStringInput(str string, s *ReplicatedDevices) error {
return nil
}

func handleFloatInput(count int, s *ReplicatedDevices) error {
func handleIntInput(count int, s *ReplicatedDevices) error {
if count <= 0 {
return fmt.Errorf("devices set as '%v' but a count of devices must be > 0", count)
}
s.Count = count
return nil
}

func handleListInput(items []interface{}, s *ReplicatedDevices) error {
result := make([]ReplicatedDeviceRef, len(items))
for i, item := range items {
switch v := item.(type) {
case float64:
result[i] = ReplicatedDeviceRef(strconv.Itoa(int(v)))
case string:
rd := ReplicatedDeviceRef(v)
func handleListInput(slice []json.RawMessage, s *ReplicatedDevices) error {
result := make([]ReplicatedDeviceRef, len(slice))
for i, raw := range slice {
var index uint
if err := json.Unmarshal(raw, &index); err == nil {
result[i] = ReplicatedDeviceRef(strconv.Itoa(int(index)))
continue
}

var item string
if err := json.Unmarshal(raw, &item); err == nil {
rd := ReplicatedDeviceRef(item)
if rd.IsGPUIndex() || rd.IsMigIndex() || rd.IsUUID() {
result[i] = rd
} else {
return fmt.Errorf("unsupported type for device in devices list: %v", v)
continue
}
default:
return fmt.Errorf("unsupported type for device in devices list: %v, %T", item, item)
}
return fmt.Errorf("unsupported type for device in devices list: %v, %T", item, item)
}
s.List = result
return nil
Expand Down

0 comments on commit 2bf4592

Please sign in to comment.