-
Notifications
You must be signed in to change notification settings - Fork 154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Stronger Types for Enums and Improve Set Encoding #151
Conversation
Pull Request Test Coverage Report for Build 1034832956
💛 - Coveralls |
@amorenoz can you please take a look when you have time |
This commit: 1. Adjusts the mapper to handle stronger enum types 2. Adjusts modelgen to produce these types Fixes: ovn-org#154 Signed-off-by: Dave Tucker <[email protected]>
Sets with min 1 and max 1 are a type Sets with min 0 and max 1 are a pointer to a type Sets with a max > 1 (non-default) are an array Otherwise a set is represented by a slice Signed-off-by: Dave Tucker <[email protected]>
This handles mapping from OvsToNative - min 0, max > 1 && !unlimted to an array - min 0, max 1 to a pointer - min 0, max unlimited to a slice And in NativeToOvs, we convert all cases back in to an OvsSet Signed-off-by: Dave Tucker <[email protected]>
@@ -133,7 +149,12 @@ func NewInfo(table *ovsdb.TableSchema, obj interface{}) (*Info, error) { | |||
|
|||
// Perform schema-based type checking | |||
expType := ovsdb.NativeType(column) | |||
if expType != field.Type { | |||
// check for slice of enums | |||
if expType.Kind() == reflect.Slice && expType.Elem().Kind() == reflect.String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should distinguish between slice of strings and slice of enums. We should check the ColumnSchema here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, do we want to allow all kind of type aliases? e.g:
type Priority int
type ACL struct {
Priority Priority
}
return fmt.Errorf("column %s: native value %v (%s) is not assignable to field %s (%s)", | ||
column, value, reflect.TypeOf(value), fieldName, fieldValue.Type()) | ||
if v.Type().ConvertibleTo(fieldValue.Type()) { | ||
// handle enum |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would explicitly check the tableSchema to make sure it's a Enum
} | ||
fieldValue.Set(reflect.ValueOf(value)) | ||
fieldValue.Set(v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a shame that we have to split the conversion of a type between Ovs2Native and this function.
I don't see a clear way out of it.
Maybe add a comment to the function explaining that some fields (despite being already "native") need an extra translation step?
@@ -182,11 +182,28 @@ func NativeToOvsAtomic(basicType string, nativeElem interface{}) (interface{}, e | |||
// NativeToOvs transforms an native type to a ovs type based on the column type information | |||
func NativeToOvs(column *ColumnSchema, rawElem interface{}) (interface{}, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to keep things more or less tidy and symetric, how about moving this logic to mapper.info?
That way we would have a clear logical separation:
bindings.NativeToOvs & bindings.OvsToNative: Convert from/to OVS types to a neutral, common, generic, native type that can hold the column
info.SetField & info.FieldByPtr & info.FieldByColumn : May perform an extra conversion step to adjust the neutral, common, generic native type to whatever type the Field actually has
WDYT?
v = v.Elem() | ||
} else { | ||
schema := i.table.Column(column) | ||
native, err := ovsdb.OvsToNative(schema, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Info.SetField is expected to receive Native values. Why do we need this?
Besides, we are not making this optional are we? I mean, we are enforcing that the native type of a set with max = 1 is a pointer. OvsToNative should create a pointer and SetField should fail if the Field is not a pointer. Why do we need extra conversion here?
switch ovsSet := ovsElem.(type) { | ||
case OvsSet: | ||
if len(ovsSet.GoSet) > 1 { | ||
return nil, fmt.Errorf("expected a slice of len < 1, but got a slice with %d elements", len(ovsSet.GoSet)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/</<=/?
Besides, I think we should refactor slice length checking to a common place and verify len(ovsSet) <= columnSchema.Max.
This PR:
These changes are together, as it was an optional (min 0, max 1) enum that prompted this discussion in the first place.
In the generated code, enum constants can no lionger be constant, but must instead be
var
because we can't take aconst string
by address for use in structs with*string
fields (or* AnEnumType
fields).Closes: #154
Closes: #191