mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
libnetwork/options: GenerateFromModel: use generics
Use generics so that the produced output is already in the right type. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
@@ -1865,11 +1865,7 @@ func parseContainerOptions(cOptions map[string]any) (*containerConfiguration, er
|
||||
}
|
||||
switch opt := genericData.(type) {
|
||||
case options.Generic:
|
||||
opaqueConfig, err := options.GenerateFromModel(opt, &containerConfiguration{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return opaqueConfig.(*containerConfiguration), nil
|
||||
return options.GenerateFromModel[*containerConfiguration](opt)
|
||||
case *containerConfiguration:
|
||||
return opt, nil
|
||||
default:
|
||||
|
||||
@@ -51,10 +51,12 @@ type Generic map[string]any
|
||||
//
|
||||
// The return value is of the same type than the model (including a potential
|
||||
// pointer qualifier).
|
||||
func GenerateFromModel(options Generic, model any) (any, error) {
|
||||
modType := reflect.TypeOf(model)
|
||||
func GenerateFromModel[T any](options Generic) (T, error) {
|
||||
var zero T
|
||||
|
||||
modType := reflect.TypeFor[T]()
|
||||
if modType == nil {
|
||||
return nil, errors.New("invalid model: model is nil")
|
||||
return zero, errors.New("invalid model: model is nil")
|
||||
}
|
||||
|
||||
isPtr := modType.Kind() == reflect.Ptr
|
||||
@@ -72,21 +74,21 @@ func GenerateFromModel(options Generic, model any) (any, error) {
|
||||
for name, value := range options {
|
||||
field := resVal.FieldByName(name)
|
||||
if !field.IsValid() {
|
||||
return nil, NoSuchFieldError{Field: name, Type: resType.String()}
|
||||
return zero, NoSuchFieldError{Field: name, Type: resType.String()}
|
||||
}
|
||||
if !field.CanSet() {
|
||||
return nil, CannotSetFieldError{Field: name, Type: resType.String()}
|
||||
return zero, CannotSetFieldError{Field: name, Type: resType.String()}
|
||||
}
|
||||
val := reflect.ValueOf(value)
|
||||
if val.Type() != field.Type() {
|
||||
return nil, TypeMismatchError{Field: name, ExpectType: field.Type().String(), ActualType: val.Type().String()}
|
||||
return zero, TypeMismatchError{Field: name, ExpectType: field.Type().String(), ActualType: val.Type().String()}
|
||||
}
|
||||
field.Set(val)
|
||||
}
|
||||
|
||||
// If the model is not of pointer type, return content of the result.
|
||||
if isPtr {
|
||||
return res.Interface(), nil
|
||||
return res.Interface().(T), nil
|
||||
}
|
||||
return resVal.Interface(), nil
|
||||
return resVal.Interface().(T), nil
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestGenerate(t *testing.T) {
|
||||
Rune: 'b',
|
||||
Float64: 2.0,
|
||||
}
|
||||
result, err := GenerateFromModel(gen, Model{})
|
||||
result, err := GenerateFromModel[Model](gen)
|
||||
assert.Check(t, err)
|
||||
assert.Check(t, is.DeepEqual(result, expected))
|
||||
}
|
||||
@@ -49,7 +49,7 @@ func TestGeneratePtr(t *testing.T) {
|
||||
Float64: 2.0,
|
||||
}
|
||||
|
||||
result, err := GenerateFromModel(gen, &Model{})
|
||||
result, err := GenerateFromModel[*Model](gen)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(result, expected))
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func TestGeneratePtr(t *testing.T) {
|
||||
func TestGenerateMissingField(t *testing.T) {
|
||||
type Model struct{}
|
||||
gen := Generic{"foo": "bar"}
|
||||
_, err := GenerateFromModel(gen, Model{})
|
||||
_, err := GenerateFromModel[Model](gen)
|
||||
const expected = `no field "foo" in type "options.Model"`
|
||||
assert.Check(t, is.Error(err, expected))
|
||||
assert.Check(t, is.ErrorType(err, NoSuchFieldError{}))
|
||||
@@ -68,7 +68,7 @@ func TestFieldCannotBeSet(t *testing.T) {
|
||||
foo int //nolint:nolintlint,unused // un-exported field is used to test error-handling
|
||||
}
|
||||
gen := Generic{"foo": "bar"}
|
||||
_, err := GenerateFromModel(gen, Model{})
|
||||
_, err := GenerateFromModel[Model](gen)
|
||||
const expected = `cannot set field "foo" of type "options.Model"`
|
||||
assert.Check(t, is.Error(err, expected))
|
||||
assert.Check(t, is.ErrorType(err, CannotSetFieldError{}))
|
||||
@@ -79,7 +79,7 @@ func TestTypeMismatchError(t *testing.T) {
|
||||
Foo int
|
||||
}
|
||||
gen := Generic{"Foo": "bar"}
|
||||
_, err := GenerateFromModel(gen, Model{})
|
||||
_, err := GenerateFromModel[Model](gen)
|
||||
const expected = `type mismatch, field Foo require type int, actual type string`
|
||||
assert.Check(t, is.Error(err, expected))
|
||||
assert.Check(t, is.ErrorType(err, TypeMismatchError{}))
|
||||
|
||||
Reference in New Issue
Block a user