From b8af3ac7e29317b93015a724c417b9594605519c Mon Sep 17 00:00:00 2001 From: FerroO2000 <30318301+FerroO2000@users.noreply.github.com> Date: Wed, 22 May 2024 18:06:59 +0200 Subject: [PATCH] attribute protos --- attribute.go | 157 +++++++++++++------------------ attribute_test.go | 8 +- entity.go | 40 +++++++- exporter.go | 20 ++-- importer.go | 4 +- proto/acmelib/v1/attribute.proto | 67 +++++++++++++ proto/acmelib/v1/bus.proto | 2 +- proto/acmelib/v1/entity.proto | 18 ++++ proto/acmelib/v1/message.proto | 2 +- proto/acmelib/v1/network.proto | 2 + proto/acmelib/v1/node.proto | 2 +- proto/acmelib/v1/signal.proto | 2 +- 12 files changed, 210 insertions(+), 114 deletions(-) create mode 100644 proto/acmelib/v1/attribute.proto diff --git a/attribute.go b/attribute.go index 7941a9a..e2e9a97 100644 --- a/attribute.go +++ b/attribute.go @@ -21,7 +21,7 @@ func newAttributeValue(att Attribute, val any) *AttributeValue { func (av *AttributeValue) stringify(b *strings.Builder, tabs int) { b.WriteString(fmt.Sprintf("%sname: %s; type: %s; value: %v\n", - getTabString(tabs), av.attribute.Name(), av.attribute.Kind(), av.value)) + getTabString(tabs), av.attribute.Name(), av.attribute.Type(), av.value)) } // Attribute returns the [Attribute] of the [AttributeValue]. @@ -84,20 +84,35 @@ func (af *AttributeRef) Value() any { return af.value } -// AttributeKind defines the kind of an [Attribute]. -type AttributeKind string +// AttributeType defines the type of an [Attribute]. +type AttributeType int const ( - // AttributeKindString defines a string attribute. - AttributeKindString AttributeKind = "attribute-string" - // AttributeKindInteger defines an integer attribute. - AttributeKindInteger AttributeKind = "attribute-integer" - // AttributeKindFloat defines a float attribute. - AttributeKindFloat AttributeKind = "attribute-float" - // AttributeKindEnum defines an enum attribute. - AttributeKindEnum AttributeKind = "attribute-enum" + // AttributeTypeString defines a string attribute. + AttributeTypeString AttributeType = iota + // AttributeTypeInteger defines an integer attribute. + AttributeTypeInteger + // AttributeTypeFloat defines a float attribute. + AttributeTypeFloat + // AttributeTypeEnum defines an enum attribute. + AttributeTypeEnum ) +func (at AttributeType) String() string { + switch at { + case AttributeTypeString: + return "string" + case AttributeTypeInteger: + return "integer" + case AttributeTypeFloat: + return "float" + case AttributeTypeEnum: + return "enum" + default: + return "unknown" + } +} + // Attribute interface specifies all common methods of // [StringAttribute], [IntegerAttribute], [FloatAttribute], and // [EnumAttribute]. @@ -111,8 +126,8 @@ type Attribute interface { // CreateTime returns the time of creation of an attribute. CreateTime() time.Time - // Kind returns the kind of an attribute. - Kind() AttributeKind + // Type returns the kind of an attribute. + Type() AttributeType addReference(ref *AttributeRef) removeReference(refID EntityID) @@ -133,19 +148,17 @@ type Attribute interface { type attribute struct { *entity + *withRefs[*AttributeRef] - kind AttributeKind - - references *set[EntityID, *AttributeRef] + typ AttributeType } -func newAttribute(name string, kind AttributeKind) *attribute { +func newAttribute(name string, typ AttributeType) *attribute { return &attribute{ - entity: newEntity(name), - - kind: kind, + entity: newEntity(name), + withRefs: newWithRefs[*AttributeRef](), - references: newSet[EntityID, *AttributeRef](), + typ: typ, } } @@ -162,9 +175,9 @@ func (a *attribute) stringify(b *strings.Builder, tabs int) { a.entity.stringify(b, tabs) tabStr := getTabString(tabs) - b.WriteString(fmt.Sprintf("%skind: %s\n", tabStr, a.kind)) + b.WriteString(fmt.Sprintf("%skind: %s\n", tabStr, a.typ)) - if a.references.size() == 0 { + if a.refs.size() == 0 { return } @@ -174,20 +187,16 @@ func (a *attribute) stringify(b *strings.Builder, tabs int) { } } -func (a *attribute) Kind() AttributeKind { - return a.kind +func (a *attribute) Type() AttributeType { + return a.typ } func (a *attribute) addReference(ref *AttributeRef) { - a.references.add(ref.entityID, ref) + a.refs.add(ref.entityID, ref) } func (a *attribute) removeReference(refID EntityID) { - a.references.remove(refID) -} - -func (a *attribute) References() []*AttributeRef { - return a.references.getValues() + a.refs.remove(refID) } // StringAttribute is an [Attribute] that holds a string value. @@ -201,7 +210,7 @@ type StringAttribute struct { // and default value. func NewStringAttribute(name, defValue string) *StringAttribute { return &StringAttribute{ - attribute: newAttribute(name, AttributeKindString), + attribute: newAttribute(name, AttributeTypeString), defValue: defValue, } @@ -231,24 +240,24 @@ func (sa *StringAttribute) ToString() (*StringAttribute, error) { // ToInteger always returns an error. func (sa *StringAttribute) ToInteger() (*IntegerAttribute, error) { return nil, sa.errorf(&ConversionError{ - From: string(AttributeKindString), - To: string(AttributeKindInteger), + From: AttributeTypeString.String(), + To: AttributeTypeInteger.String(), }) } // ToFloat always returns an error. func (sa *StringAttribute) ToFloat() (*FloatAttribute, error) { return nil, sa.errorf(&ConversionError{ - From: string(AttributeKindString), - To: string(AttributeKindFloat), + From: AttributeTypeString.String(), + To: AttributeTypeFloat.String(), }) } // ToEnum always returns an error. func (sa *StringAttribute) ToEnum() (*EnumAttribute, error) { return nil, sa.errorf(&ConversionError{ - From: string(AttributeKindString), - To: string(AttributeKindEnum), + From: AttributeTypeString.String(), + To: AttributeTypeEnum.String(), }) } @@ -290,7 +299,7 @@ func NewIntegerAttribute(name string, defValue, min, max int) (*IntegerAttribute } return &IntegerAttribute{ - attribute: newAttribute(name, AttributeKindInteger), + attribute: newAttribute(name, AttributeTypeInteger), defValue: defValue, min: min, @@ -342,8 +351,8 @@ func (ia *IntegerAttribute) IsHexFormat() bool { // ToString always returns an error. func (ia *IntegerAttribute) ToString() (*StringAttribute, error) { return nil, ia.errorf(&ConversionError{ - From: string(AttributeKindInteger), - To: string(AttributeKindString), + From: AttributeTypeInteger.String(), + To: AttributeTypeString.String(), }) } @@ -355,16 +364,16 @@ func (ia *IntegerAttribute) ToInteger() (*IntegerAttribute, error) { // ToFloat always returns an error. func (ia *IntegerAttribute) ToFloat() (*FloatAttribute, error) { return nil, ia.errorf(&ConversionError{ - From: string(AttributeKindInteger), - To: string(AttributeKindFloat), + From: AttributeTypeInteger.String(), + To: AttributeTypeFloat.String(), }) } // ToEnum always returns an error. func (ia *IntegerAttribute) ToEnum() (*EnumAttribute, error) { return nil, ia.errorf(&ConversionError{ - From: string(AttributeKindInteger), - To: string(AttributeKindEnum), + From: AttributeTypeInteger.String(), + To: AttributeTypeEnum.String(), }) } @@ -404,7 +413,7 @@ func NewFloatAttribute(name string, defValue, min, max float64) (*FloatAttribute } return &FloatAttribute{ - attribute: newAttribute(name, AttributeKindFloat), + attribute: newAttribute(name, AttributeTypeFloat), defValue: defValue, min: min, @@ -444,16 +453,16 @@ func (fa *FloatAttribute) Max() float64 { // ToString always returns an error. func (fa *FloatAttribute) ToString() (*StringAttribute, error) { return nil, fa.errorf(&ConversionError{ - From: string(AttributeKindFloat), - To: string(AttributeKindString), + From: AttributeTypeFloat.String(), + To: AttributeTypeString.String(), }) } // ToInteger always returns an error. func (fa *FloatAttribute) ToInteger() (*IntegerAttribute, error) { return nil, fa.errorf(&ConversionError{ - From: string(AttributeKindFloat), - To: string(AttributeKindInteger), + From: AttributeTypeFloat.String(), + To: AttributeTypeInteger.String(), }) } @@ -465,8 +474,8 @@ func (fa *FloatAttribute) ToFloat() (*FloatAttribute, error) { // ToEnum always returns an error. func (fa *FloatAttribute) ToEnum() (*EnumAttribute, error) { return nil, fa.errorf(&ConversionError{ - From: string(AttributeKindFloat), - To: string(AttributeKindEnum), + From: AttributeTypeFloat.String(), + To: AttributeTypeEnum.String(), }) } @@ -501,7 +510,7 @@ func NewEnumAttribute(name string, values ...string) (*EnumAttribute, error) { } return &EnumAttribute{ - attribute: newAttribute(name, AttributeKindEnum), + attribute: newAttribute(name, AttributeTypeEnum), defValue: values[0], values: valSet, @@ -568,24 +577,24 @@ func (ea *EnumAttribute) GetValueAtIndex(valueIndex int) (string, error) { // ToString always returns an error. func (ea *EnumAttribute) ToString() (*StringAttribute, error) { return nil, ea.errorf(&ConversionError{ - From: string(AttributeKindEnum), - To: string(AttributeKindString), + From: AttributeTypeEnum.String(), + To: AttributeTypeString.String(), }) } // ToInteger always returns an error. func (ea *EnumAttribute) ToInteger() (*IntegerAttribute, error) { return nil, ea.errorf(&ConversionError{ - From: string(AttributeKindEnum), - To: string(AttributeKindInteger), + From: AttributeTypeEnum.String(), + To: AttributeTypeInteger.String(), }) } // ToFloat always returns an error. func (ea *EnumAttribute) ToFloat() (*FloatAttribute, error) { return nil, ea.errorf(&ConversionError{ - From: string(AttributeKindEnum), - To: string(AttributeKindFloat), + From: AttributeTypeEnum.String(), + To: AttributeTypeFloat.String(), }) } @@ -593,33 +602,3 @@ func (ea *EnumAttribute) ToFloat() (*FloatAttribute, error) { func (ea *EnumAttribute) ToEnum() (*EnumAttribute, error) { return ea, nil } - -type referenceableEntity interface { - EntityID() EntityID -} - -type withRefs[R referenceableEntity] struct { - refs *set[EntityID, R] -} - -func newWithRefs[R referenceableEntity]() *withRefs[R] { - return &withRefs[R]{ - refs: newSet[EntityID, R](), - } -} - -func (t *withRefs[R]) addRef(ref R) { - t.refs.add(ref.EntityID(), ref) -} - -func (t *withRefs[R]) removeRef(refID EntityID) { - t.refs.remove(refID) -} - -func (t *withRefs[R]) ReferenceCount() int { - return t.refs.size() -} - -func (t *withRefs[R]) References() []R { - return t.refs.getValues() -} diff --git a/attribute_test.go b/attribute_test.go index a503bc6..bbaf373 100644 --- a/attribute_test.go +++ b/attribute_test.go @@ -10,7 +10,7 @@ func Test_StringAttribute(t *testing.T) { assert := assert.New(t) strAtt := NewStringAttribute("str_att", "def_val") - assert.Equal(AttributeKindString, strAtt.Kind()) + assert.Equal(AttributeTypeString, strAtt.Type()) assert.Equal("str_att", strAtt.Name()) assert.Equal("def_val", strAtt.DefValue()) @@ -30,7 +30,7 @@ func Test_IntegerAttribute(t *testing.T) { intAtt, err := NewIntegerAttribute("int_att", 10, 0, 100) assert.NoError(err) - assert.Equal(AttributeKindInteger, intAtt.Kind()) + assert.Equal(AttributeTypeInteger, intAtt.Type()) assert.Equal("int_att", intAtt.Name()) assert.Equal(10, intAtt.DefValue()) assert.Equal(0, intAtt.Min()) @@ -60,7 +60,7 @@ func Test_FloatAttribute(t *testing.T) { floatAtt, err := NewFloatAttribute("float_att", 10, 0, 100) assert.NoError(err) - assert.Equal(AttributeKindFloat, floatAtt.Kind()) + assert.Equal(AttributeTypeFloat, floatAtt.Type()) assert.Equal("float_att", floatAtt.Name()) assert.Equal(10.0, floatAtt.DefValue()) assert.Equal(0.0, floatAtt.Min()) @@ -90,7 +90,7 @@ func Test_EnumAttribute(t *testing.T) { enumAtt, err := NewEnumAttribute("enum_att", "val_0", "val_1", "val_2") assert.NoError(err) - assert.Equal(AttributeKindEnum, enumAtt.Kind()) + assert.Equal(AttributeTypeEnum, enumAtt.Type()) assert.Equal("enum_att", enumAtt.Name()) assert.Equal("val_0", enumAtt.DefValue()) assert.Equal(3, len(enumAtt.Values())) diff --git a/entity.go b/entity.go index 38671a7..e42764b 100644 --- a/entity.go +++ b/entity.go @@ -177,7 +177,7 @@ func (ae *attributeEntity) AddAttributeValue(attribute Attribute, value any) err switch v := value.(type) { case int: - if attribute.Kind() != AttributeKindInteger { + if attribute.Type() != AttributeTypeInteger { entErr.Err = &ArgumentError{ Name: "value", Err: ErrInvalidType, @@ -198,7 +198,7 @@ func (ae *attributeEntity) AddAttributeValue(attribute Attribute, value any) err } case float64: - if attribute.Kind() != AttributeKindFloat { + if attribute.Type() != AttributeTypeFloat { entErr.Err = &ArgumentError{ Name: "value", Err: ErrInvalidType, @@ -219,9 +219,9 @@ func (ae *attributeEntity) AddAttributeValue(attribute Attribute, value any) err } case string: - switch attribute.Kind() { - case AttributeKindString: - case AttributeKindEnum: + switch attribute.Type() { + case AttributeTypeString: + case AttributeTypeEnum: enumAtt, err := attribute.ToEnum() if err != nil { panic(err) @@ -306,3 +306,33 @@ func (ae *attributeEntity) GetAttributeValue(attributeEntityID EntityID) (*Attri } return attVal, nil } + +type referenceableEntity interface { + EntityID() EntityID +} + +type withRefs[R referenceableEntity] struct { + refs *set[EntityID, R] +} + +func newWithRefs[R referenceableEntity]() *withRefs[R] { + return &withRefs[R]{ + refs: newSet[EntityID, R](), + } +} + +func (t *withRefs[R]) addRef(ref R) { + t.refs.add(ref.EntityID(), ref) +} + +func (t *withRefs[R]) removeRef(refID EntityID) { + t.refs.remove(refID) +} + +func (t *withRefs[R]) ReferenceCount() int { + return t.refs.size() +} + +func (t *withRefs[R]) References() []R { + return t.refs.getValues() +} diff --git a/exporter.go b/exporter.go index 7152fee..4f8cafc 100644 --- a/exporter.go +++ b/exporter.go @@ -131,12 +131,12 @@ func (e *exporter) exportAttributeValue(attVal *AttributeValue, dbcAttKind dbc.A e.exportAttribute(att, dbcAtt) } - switch att.Kind() { - case AttributeKindString: + switch att.Type() { + case AttributeTypeString: dbcAttVal.Type = dbc.AttributeValueString dbcAttVal.ValueString = attVal.value.(string) - case AttributeKindInteger: + case AttributeTypeInteger: intAtt, err := att.ToInteger() if err != nil { panic(err) @@ -150,11 +150,11 @@ func (e *exporter) exportAttributeValue(attVal *AttributeValue, dbcAttKind dbc.A dbcAttVal.ValueInt = attVal.value.(int) } - case AttributeKindFloat: + case AttributeTypeFloat: dbcAttVal.Type = dbc.AttributeValueFloat dbcAttVal.ValueFloat = attVal.value.(float64) - case AttributeKindEnum: + case AttributeTypeEnum: enumAtt, err := att.ToEnum() if err != nil { panic(err) @@ -180,8 +180,8 @@ func (e *exporter) exportAttribute(att Attribute, dbcAtt *dbc.Attribute) { dbcAttDef := new(dbc.AttributeDefault) dbcAttDef.AttributeName = attName - switch att.Kind() { - case AttributeKindString: + switch att.Type() { + case AttributeTypeString: strAtt, err := att.ToString() if err != nil { panic(err) @@ -191,7 +191,7 @@ func (e *exporter) exportAttribute(att Attribute, dbcAtt *dbc.Attribute) { dbcAttDef.Type = dbc.AttributeDefaultString dbcAttDef.ValueString = strAtt.defValue - case AttributeKindInteger: + case AttributeTypeInteger: intAtt, err := att.ToInteger() if err != nil { panic(err) @@ -213,7 +213,7 @@ func (e *exporter) exportAttribute(att Attribute, dbcAtt *dbc.Attribute) { dbcAttDef.ValueInt = intAtt.defValue } - case AttributeKindFloat: + case AttributeTypeFloat: floatAtt, err := att.ToFloat() if err != nil { panic(err) @@ -225,7 +225,7 @@ func (e *exporter) exportAttribute(att Attribute, dbcAtt *dbc.Attribute) { dbcAttDef.Type = dbc.AttributeDefaultString dbcAttDef.ValueFloat = floatAtt.defValue - case AttributeKindEnum: + case AttributeTypeEnum: enumAtt, err := att.ToEnum() if err != nil { panic(err) diff --git a/importer.go b/importer.go index 8abfd55..77a03b7 100644 --- a/importer.go +++ b/importer.go @@ -193,7 +193,7 @@ func (i *importer) importAttributes(dbcAtts []*dbc.Attribute, dbcAttDefs []*dbc. value = dbcAttVal.ValueString case dbc.AttributeValueInt: - if att.Kind() == AttributeKindEnum { + if att.Type() == AttributeTypeEnum { enumAtt, err := att.ToEnum() if err != nil { panic(err) @@ -208,7 +208,7 @@ func (i *importer) importAttributes(dbcAtts []*dbc.Attribute, dbcAttDefs []*dbc. break } - if att.Kind() == AttributeKindFloat { + if att.Type() == AttributeTypeFloat { value = float64(dbcAttVal.ValueInt) break } diff --git a/proto/acmelib/v1/attribute.proto b/proto/acmelib/v1/attribute.proto new file mode 100644 index 0000000..d790bd4 --- /dev/null +++ b/proto/acmelib/v1/attribute.proto @@ -0,0 +1,67 @@ +syntax = "proto3"; + +package acmelib.v1; + +import "acmelib/v1/entity.proto"; + +enum AttributeType { + ATTRIBUTE_TYPE_UNSPECIFIED = 0; + ATTRIBUTE_TYPE_STRING = 1; + ATTRIBUTE_TYPE_INTEGER = 2; + ATTRIBUTE_TYPE_FLOAT = 3; + ATTRIBUTE_TYPE_ENUM = 4; +} + +message Attribute { + acmelib.v1.Entity entity = 1; + + AttributeType type = 2; + + oneof attribute { + StringAttribute string_attribute = 3; + IntegerAttribute integer_attribute = 4; + FloatAttribute float_attribute = 5; + EnumAttribute enum_attribute = 6; + } +} + +message StringAttribute { + string def_value = 1; +} + +message IntegerAttribute { + int32 def_value = 1; + int32 min = 2; + int32 max = 3; + bool is_hex_format = 4; +} + +message FloatAttribute { + double def_value = 1; + double min = 2; + double max = 3; +} + +message EnumAttribute { + string def_value = 1; + repeated string values = 2; +} + +enum AttributeRefKind { + ATTRIBUTE_REF_KIND_UNSPECIFIED = 0; + ATTRIBUTE_REF_KIND_BUS = 1; + ATTRIBUTE_REF_KIND_NODE = 2; + ATTRIBUTE_REF_KIND_MESSAGE = 3; + ATTRIBUTE_REF_KIND_SIGNAL = 4; +} + +message AttributeRef { + string entity_id = 1; + AttributeRefKind kind = 2; + + oneof value { + string value_string = 3; + int32 value_int = 4; + double value_double = 5; + } +} \ No newline at end of file diff --git a/proto/acmelib/v1/bus.proto b/proto/acmelib/v1/bus.proto index 1037c00..a7dba4c 100644 --- a/proto/acmelib/v1/bus.proto +++ b/proto/acmelib/v1/bus.proto @@ -12,7 +12,7 @@ enum BusType { } message Bus { - acmelib.v1.Entity entity = 1; + acmelib.v1.EntityWithAttributes entity = 1; repeated acmelib.v1.NodeInterface node_interfaces = 2; diff --git a/proto/acmelib/v1/entity.proto b/proto/acmelib/v1/entity.proto index 5620d35..aa97878 100644 --- a/proto/acmelib/v1/entity.proto +++ b/proto/acmelib/v1/entity.proto @@ -9,4 +9,22 @@ message Entity { string name = 2; string desc = 3; google.protobuf.Timestamp create_time = 4; +} + +message EntityWithAttributes { + string entity_id = 1; + string name = 2; + string desc = 3; + google.protobuf.Timestamp create_time = 4; + repeated AttributeValue attribute_values = 5; +} + +message AttributeValue { + string attribute_entity_id = 1; + + oneof value { + string value_string = 2; + int32 value_int = 3; + double value_double = 4; + } } \ No newline at end of file diff --git a/proto/acmelib/v1/message.proto b/proto/acmelib/v1/message.proto index 5afbb8f..7e68981 100644 --- a/proto/acmelib/v1/message.proto +++ b/proto/acmelib/v1/message.proto @@ -29,7 +29,7 @@ enum MessageByteOrder { } message Message { - acmelib.v1.Entity entity = 1; + acmelib.v1.EntityWithAttributes entity = 1; repeated acmelib.v1.Signal signals = 2; acmelib.v1.SignalPayload payload = 3; diff --git a/proto/acmelib/v1/network.proto b/proto/acmelib/v1/network.proto index 2c00bdd..ecabe2b 100644 --- a/proto/acmelib/v1/network.proto +++ b/proto/acmelib/v1/network.proto @@ -9,6 +9,7 @@ import "acmelib/v1/node.proto"; import "acmelib/v1/signal_type.proto"; import "acmelib/v1/signal_unit.proto"; import "acmelib/v1/signal_enum.proto"; +import "acmelib/v1/attribute.proto"; message Network { acmelib.v1.Entity entity = 1; @@ -20,4 +21,5 @@ message Network { repeated acmelib.v1.SignalType signal_types = 5; repeated acmelib.v1.SignalUnit signal_units = 6; repeated acmelib.v1.SignalEnum signal_enums = 7; + repeated acmelib.v1.Attribute attributes = 8; } \ No newline at end of file diff --git a/proto/acmelib/v1/node.proto b/proto/acmelib/v1/node.proto index be812ca..c464c6d 100644 --- a/proto/acmelib/v1/node.proto +++ b/proto/acmelib/v1/node.proto @@ -5,7 +5,7 @@ package acmelib.v1; import "acmelib/v1/entity.proto"; message Node { - acmelib.v1.Entity entity = 1; + acmelib.v1.EntityWithAttributes entity = 1; uint32 node_id = 2; uint32 interface_count = 3; diff --git a/proto/acmelib/v1/signal.proto b/proto/acmelib/v1/signal.proto index 9879442..708091a 100644 --- a/proto/acmelib/v1/signal.proto +++ b/proto/acmelib/v1/signal.proto @@ -27,7 +27,7 @@ enum SignalSendType { } message Signal { - acmelib.v1.Entity entity = 1; + acmelib.v1.EntityWithAttributes entity = 1; SignalKind kind = 2; SignalSendType send_type = 3;