public void TestReferenceFieldWorks() { string s = @" name MySchema; enum MyEnum1 { value1, value2, value3 } type(234) MyObject { MyEnum1 enumValue; } "; s = s.Replace('X', '"'); PatternBufferSchema schema = this.Parse(s); Assert.That(schema.Name, Is.EqualTo("MySchema")); Assert.That(schema.Types.Count, Is.EqualTo(1)); Assert.That(schema.Enums.Count, Is.EqualTo(1)); Assert.That(schema.Hints.Count, Is.EqualTo(0)); PatternBufferType t = schema.Types[0]; Assert.That(t.Name, Is.EqualTo("MyObject")); Assert.That(t.TypeId, Is.EqualTo(234)); Assert.That(t.BaseType, Is.Null); Assert.That(HasReferenceField(t, "enumValue", "MyEnum1"), Is.True); }
public void TestVariantTypesWork() { string s = @" name MySchema; type(1) MyType { vushort vushortValue; vint vintValue; vuint vuintValue; vlong vlongValue; vulong vulongValue; } "; s = s.Replace('X', '"'); PatternBufferSchema schema = this.Parse(s); Assert.That(schema.Name, Is.EqualTo("MySchema")); Assert.That(schema.Enums.Count, Is.EqualTo(0)); Assert.That(schema.Types.Count, Is.EqualTo(1)); Assert.That(schema.Hints.Count, Is.EqualTo(0)); PatternBufferType t = schema.Types[0]; Assert.That(t.HintCount, Is.EqualTo(0)); Assert.That(t.Name, Is.EqualTo("MyType")); Assert.That(t.TypeId, Is.EqualTo(1)); Assert.That(t.Fields.Count, Is.EqualTo(5)); Assert.That(HasPrimitiveField(t, "vushortValue", PrimitiveType.VUShort), Is.True); Assert.That(HasPrimitiveField(t, "vintValue", PrimitiveType.VInt), Is.True); Assert.That(HasPrimitiveField(t, "vuintValue", PrimitiveType.VUInt), Is.True); Assert.That(HasPrimitiveField(t, "vlongValue", PrimitiveType.VLong), Is.True); Assert.That(HasPrimitiveField(t, "vulongValue", PrimitiveType.VULong), Is.True); }
public void TestASimpleTypeWorks() { string s = @" // comment name MySchema; type(123) MyType { [foo.bar = XwhateverX] int a; bool b; } "; s = s.Replace('X', '"'); PatternBufferSchema schema = this.Parse(s); Assert.That(schema.Name, Is.EqualTo("MySchema")); Assert.That(schema.Enums.Count, Is.EqualTo(0)); Assert.That(schema.Types.Count, Is.EqualTo(1)); Assert.That(schema.Hints.Count, Is.EqualTo(0)); PatternBufferType t = schema.Types[0]; Assert.That(t.HintCount, Is.EqualTo(1)); Assert.That(t.Name, Is.EqualTo("MyType")); Assert.That(t.TypeId, Is.EqualTo(123)); Assert.That(t.Fields.Count, Is.EqualTo(2)); Assert.That(HasPrimitiveField(t, "a", PrimitiveType.Int), Is.True); Assert.That(HasPrimitiveField(t, "b", PrimitiveType.Bool), Is.True); Assert.That(HasHint(t, "foo.bar", "whatever"), Is.True); }
/** * Returns true if the type has a map field of a particular name, key, and value type. */ protected bool HasMapField(PatternBufferType type, string fieldName, object keyType, object valueType) { bool has = true; PatternBufferField field = this.GetField <MapFieldType>(type, fieldName); if (field != null) { if (keyType is PrimitiveType && field.FieldType is PrimitiveFieldType) { has = has && (((PrimitiveFieldType)field.FieldType).PrimitiveType == (PrimitiveType)keyType); } else if (keyType is string && field.FieldType is ReferenceFieldType) { has = has && (((ReferenceFieldType)field.FieldType).ReferrableName == (string)keyType); } if (valueType is PrimitiveType && field.FieldType is PrimitiveFieldType) { has = has && (((PrimitiveFieldType)field.FieldType).PrimitiveType == (PrimitiveType)valueType); } else if (keyType is string && field.FieldType is ReferenceFieldType) { has = has && (((ReferenceFieldType)field.FieldType).ReferrableName == (string)valueType); } } return(has); }
/** * Returns true if the type has a list field containing a specific primitive type. */ protected bool HasPrimitiveListField(PatternBufferType type, string fieldName, PrimitiveType primitiveType) { PatternBufferField field = this.GetField <ListFieldType>(type, fieldName); IFieldType elementType = ((ListFieldType)field.FieldType).ElementType; return (elementType is PrimitiveFieldType && ((PrimitiveFieldType)elementType).PrimitiveType == primitiveType); }
/** * Returns true if the type has a set field containing a specific reference type. */ protected bool HasReferenceSetField(PatternBufferType type, string fieldName, String referrableName) { PatternBufferField field = this.GetField <SetFieldType>(type, fieldName); IFieldType elementType = ((SetFieldType)field.FieldType).ElementType; return (elementType is ReferenceFieldType && ((ReferenceFieldType)elementType).ReferrableName.Equals(referrableName)); }
/** * Appends C# code to write a referenced object to the byte buffer. */ public static void AppendWriteReference(ref string code, PatternBufferType patternBufferType, string varName, string schemaObjectTypeName) { if (patternBufferType.IsFinal) { code += " Energize(" + varName + ", bytes, ref index, false);\r\n"; } else { code += " Energize((" + schemaObjectTypeName + ")" + varName + ", bytes, ref index, true);\r\n"; } }
/** * Returns the field of a the given name. */ protected PatternBufferField GetField <T>(PatternBufferType type, string fieldName) { foreach (PatternBufferField field in type.Fields) { if (fieldName.Equals(field.Name) && field.FieldType is T) { return(field); } } throw new Exception("Could not find field \"" + fieldName + "\" on type \"" + type.Name + "\"."); }
/** * Appends C# code to read a referenced object from the byte buffer. */ public static void AppendReadReference(ref string code, PatternBufferType patternBufferType, string varName) { if (patternBufferType.IsFinal) { code += " " + varName + " = (" + ToCSharpName(patternBufferType.Name) + ")Energize(bytes, ref index, " + patternBufferType.TypeId + ");\r\n"; } else { code += " " + varName + " = (" + ToCSharpName(patternBufferType.Name) + ")Energize(bytes, ref index);\r\n"; } }
/** * Returns a list of all optional fields on the type, including fields in the type's * ancestors. */ public static List <PatternBufferField> GetAllOptionalFields(PatternBufferType type) { List <PatternBufferField> allFields = GetAllFields(type); List <PatternBufferField> optionalFields = new List <PatternBufferField>(); foreach (PatternBufferField field in allFields) { if (IsOptional(field.FieldType)) { optionalFields.Add(field); } } return(optionalFields); }
/** * Appends optiona bit flag bytes into the output. */ public static void AppendWriteOptionalFieldFlags(ref string code, PatternBufferType type, string varName) { List <PatternBufferField> optionalFields = GetAllOptionalFields(type); if (optionalFields.Count > 0) { code += " //\r\n"; code += " //\r\n"; code += " //\r\n"; code += " //\r\n"; code += " //\r\n"; code += " // you know what do this in the main field serialization loop it already checks nulls\r\n"; code += " //\r\n"; code += " //\r\n"; code += " //\r\n"; code += " //\r\n"; code += " \r\n"; code += " // OPTIONAL FIELD FLAGS\r\n"; code += " index--;\r\n"; int place = 7; for (int b = 0; b < optionalFields.Count; b++) { if (b % 8 == 0) { code += " bytes[++index] = 0;\r\n"; place = 7; } PatternBufferField optionalField = optionalFields[b]; //code += " if (" + varName + "." + ToCSharpPropertyName(optionalField.Name) + " != null) {\r\n"; //code += " bytes[index] |= (byte)(1 << " + place + ");\r\n"; //code += " }\r\n"; code += " bytes[index] |= (byte)((" + varName + "." + ToCSharpPropertyName(optionalField.Name) + " != null ? 1 : 0) << " + place + ");\r\n"; place--; } code += " index++;\r\n"; } }
/** * Returns a list of all the fields in a PatterBufferType's type hierarchy. The returned list * will contains the fields of all the given type's ancestors with the eldest (highest) ancestor's * fields first and the given type's fields last, along with all intermediate ancestors in between. * Fields are returned in the order defined in the schema file. */ public static List <PatternBufferField> GetAllFields(PatternBufferType type) { // Collect the hierarchy List <PatternBufferType> hierarchy = new List <PatternBufferType>(); PatternBufferType current = type; while (current != null) { hierarchy.Insert(0, current); current = current.BaseType; } // Collect the fields List <PatternBufferField> fields = new List <PatternBufferField>(); foreach (PatternBufferType t in hierarchy) { foreach (PatternBufferField f in t.Fields) { fields.Add(f); } } return(fields); }
public void TestAComplexTypeWorks() { string s = @" // comment name MySchema; [foobar.schema1=X12345X] [foobar.schema2=XABCDEX] enum MyEnum1 { [foobar.enum=X12345X] value1, value2, value3 } enum MyEnum2 { valueA, valueB, valueC, valueD } /* * Comment */ type(234) MyObject { [foobar.type=X12345X] short shortValue; ushort ushortValue; int intValue; uint uintValue; long longValue; ulong ulongValue; float floatValue; double doubleValue; bool boolValue; byte byteValue; DerivedObject otherObjectValue; MyEnum1 enumValue; list<int> intList; list<DerivedObject> otherObjectList; list<MyEnum1> myEnumList; set<int> intSet; set<DerivedObject> otherObjectSet; set<MyEnum1> myEnumSet; map<int,string> intStringMap; map<string,DerivedObject> stringOtherObjectMap; map<int,MyEnum1> intMyEnumMap; } type() AbstractObject { int intValue1; } type(789) DerivedObject : AbstractObject { int intValue2; } "; s = s.Replace('X', '"'); PatternBufferSchema schema = this.Parse(s); Assert.That(schema.Name, Is.EqualTo("MySchema")); Assert.That(schema.Types.Count, Is.EqualTo(3)); Assert.That(schema.Enums.Count, Is.EqualTo(2)); Assert.That(schema.Hints.Count, Is.EqualTo(2)); // Name Assert.That(schema.Name, Is.EqualTo("MySchema")); // Hints Assert.That(schema.Hints.Count, Is.EqualTo(2)); Assert.That(schema.Hints.ContainsKey("foobar.schema1"), Is.True); Assert.That(schema.Hints["foobar.schema1"], Is.EqualTo("12345")); Assert.That(schema.Hints.ContainsKey("foobar.schema2"), Is.True); Assert.That(schema.Hints["foobar.schema2"], Is.EqualTo("ABCDE")); // Enums foreach (PatternBufferEnum e in schema.Enums) { Assert.IsTrue("MyEnum1".Equals(e.Name) || "MyEnum2".Equals(e.Name)); if ("MyEnum1".Equals(e.Name)) { Assert.That(e.Values.Count, Is.EqualTo(3)); Assert.That(e.Values[0], Is.EqualTo("value1")); Assert.That(e.Values[1], Is.EqualTo("value2")); Assert.That(e.Values[2], Is.EqualTo("value3")); Assert.That(e.HintCount, Is.EqualTo(1)); Assert.That(e.GetHint("foobar.enum"), Is.EqualTo("12345")); } else { Assert.That(e.Values.Count, Is.EqualTo(4)); Assert.That(e.Values[0], Is.EqualTo("valueA")); Assert.That(e.Values[1], Is.EqualTo("valueB")); Assert.That(e.Values[2], Is.EqualTo("valueC")); Assert.That(e.Values[3], Is.EqualTo("valueD")); Assert.That(e.HintCount, Is.EqualTo(0)); } } // Types PatternBufferType abstractObjectPatternBufferType = null; foreach (PatternBufferType t in schema.Types) { Assert.That("MyObject".Equals(t.Name) || "AbstractObject".Equals(t.Name) || "DerivedObject".Equals(t.Name), Is.True); if ("MyObject".Equals(t.Name)) { Assert.That(t.TypeId, Is.EqualTo(234)); Assert.That(t.BaseType, Is.Null); Assert.That(t.Fields.Count, Is.EqualTo(21)); Assert.That(HasPrimitiveField(t, "shortValue", PrimitiveType.Short), Is.True); Assert.That(HasPrimitiveField(t, "ushortValue", PrimitiveType.UShort), Is.True); Assert.That(HasPrimitiveField(t, "intValue", PrimitiveType.Int), Is.True); Assert.That(HasPrimitiveField(t, "uintValue", PrimitiveType.UInt), Is.True); Assert.That(HasPrimitiveField(t, "longValue", PrimitiveType.Long), Is.True); Assert.That(HasPrimitiveField(t, "ulongValue", PrimitiveType.ULong), Is.True); Assert.That(HasPrimitiveField(t, "floatValue", PrimitiveType.Float), Is.True); Assert.That(HasPrimitiveField(t, "doubleValue", PrimitiveType.Double), Is.True); Assert.That(HasPrimitiveField(t, "boolValue", PrimitiveType.Bool), Is.True); Assert.That(HasPrimitiveField(t, "byteValue", PrimitiveType.Byte), Is.True); Assert.That(HasReferenceField(t, "otherObjectValue", "DerivedObject"), Is.True); Assert.That(HasReferenceField(t, "enumValue", "MyEnum1"), Is.True); Assert.That(HasPrimitiveListField(t, "intList", PrimitiveType.Int), Is.True); Assert.That(HasReferenceListField(t, "otherObjectList", "DerivedObject"), Is.True); Assert.That(HasReferenceListField(t, "myEnumList", "MyEnum1"), Is.True); Assert.That(HasPrimitiveSetField(t, "intSet", PrimitiveType.Int), Is.True); Assert.That(HasReferenceSetField(t, "otherObjectSet", "DerivedObject"), Is.True); Assert.That(HasReferenceSetField(t, "myEnumSet", "MyEnum1"), Is.True); Assert.That(HasMapField(t, "intStringMap", PrimitiveType.Int, PrimitiveType.String), Is.True); Assert.That(HasMapField(t, "stringOtherObjectMap", PrimitiveType.String, "DerivedObject"), Is.True); Assert.That(HasMapField(t, "stringOtherObjectMap", PrimitiveType.Int, "MyEnum1"), Is.True); Assert.That(t.HintCount, Is.EqualTo(1)); Assert.That(t.GetHint("foobar.type"), Is.EqualTo("12345")); } else if ("AbstractObject".Equals(t.Name)) { abstractObjectPatternBufferType = t; Assert.That(t.TypeId, Is.EqualTo(0)); Assert.That(t.BaseType, Is.Null); Assert.That(t.Fields.Count, Is.EqualTo(1)); Assert.That(HasPrimitiveField(t, "intValue1", PrimitiveType.Int), Is.True); Assert.That(t.HintCount, Is.EqualTo(0)); } else if ("DerivedObject".Equals(t.Name)) { Assert.That(t.TypeId, Is.EqualTo(789)); Assert.That(t.BaseType, Is.EqualTo(abstractObjectPatternBufferType)); Assert.That(HasPrimitiveField(t, "intValue2", PrimitiveType.Int), Is.True); Assert.That(t.HintCount, Is.EqualTo(0)); } } }
/** * Returns true if the type has a reference field of a particular type. */ protected bool HasReferenceField(PatternBufferType type, string fieldName, String referrableName) { PatternBufferField field = this.GetField <ReferenceFieldType>(type, fieldName); return(((ReferenceFieldType)field.FieldType).ReferrableName.Equals(referrableName)); }
/** * Appends C# code to read a collection of serialized objects into the appropriate collection type. */ public static void AppendSerializerReadCollection(ref string code, string fieldName, IFieldType elementType, string collectionTypeName, string subfieldName) { // Read the list item count code += " // Read list item count\r\n"; string countFieldName = PB.CreateRandomFieldName("count"); code += " ushort " + countFieldName + ";\r\n"; PBP.AppendReadVUInt16(ref code, countFieldName); // Continue if the bytes indicate more than zero items. code += " // Read list items\r\n"; code += " if (" + countFieldName + " > 0) {\r\n"; // The element size is constant if: // 1) It's a primitive field // 2) It's not a variant primitive // 3) It's not a string // Serialize constant-sized primitives if ((elementType is PrimitiveFieldType)) { PrimitiveFieldType primitiveFieldType = (PrimitiveFieldType)elementType; string cappedElementName = PB.ToCapitalizedCSharpType(primitiveFieldType); code += " " + fieldName + " = this.instantiator.Acquire" + collectionTypeName + "Of" + cappedElementName + "();\r\n"; string tempFieldName = PB.CreateRandomFieldName("listValue"); code += " " + PB.ToCSharpType(primitiveFieldType) + " " + tempFieldName + ";\r\n"; string i = PB.CreateRandomFieldName("i"); code += " for (int " + i + " = 0; " + i + " < " + countFieldName + "; " + i + "++) {\r\n"; code += " // Read " + primitiveFieldType.PrimitiveType + " list item\r\n"; PBP.AppendReadPrimitive(ref code, tempFieldName, primitiveFieldType.PrimitiveType); code += " " + fieldName + ".Add(" + tempFieldName + ");\r\n"; code += " }\r\n"; } // Serialize variable size list elements (incl. references, enums, strings) else { ReferenceFieldType referenceFieldType = (ReferenceFieldType)elementType; // list<enum> if (referenceFieldType.Referrable is PatternBufferEnum) { PatternBufferEnum e = (PatternBufferEnum)referenceFieldType.Referrable; string enumName = PB.ToCSharpName(e.Name); string cappedElementName = PB.ToCapitalizedCSharpType(referenceFieldType); code += " " + fieldName + " = this.instantiator.Acquire" + collectionTypeName + "Of" + cappedElementName + "();\r\n"; string i = PB.CreateRandomFieldName("i"); code += " for (int " + i + " = 0; " + i + " < " + countFieldName + "; " + i + "++) {\r\n"; code += " " + fieldName + ".Add((" + enumName + ")System.Enum.Parse(typeof(" + enumName + "), enumIndexValueMap[\"" + referenceFieldType.ReferrableName + "\"][bytes[index++]]));\r\n"; code += " }\r\n"; } // list<something> else if (referenceFieldType.Referrable is PatternBufferType) { PatternBufferType patternBufferType = (PatternBufferType)referenceFieldType.Referrable; string elementTypeName = PB.ToCSharpType(referenceFieldType); string cappedElementName = PB.ToCapitalizedCSharpType(referenceFieldType); code += " " + fieldName + " = this.instantiator.Acquire" + collectionTypeName + "Of" + cappedElementName + "();\r\n"; string i = PB.CreateRandomFieldName("li"); // All objects in the list are the same type if (patternBufferType.IsFinal) { code += " for (int " + i + " = 0; " + i + " < " + countFieldName + "; " + i + "++) {\r\n"; code += " " + fieldName + ".Add((" + elementTypeName + ")Energize(bytes, ref index, " + patternBufferType.TypeId + "));\r\n"; code += " }\r\n"; } // The objects in the list may be of different types else { code += " for (int " + i + " = 0; " + i + " < " + countFieldName + "; " + i + "++) {\r\n"; code += " " + fieldName + ".Add((" + elementTypeName + ")Energize(bytes, ref index));\r\n"; code += " }\r\n"; } } else { // what } } code += " }\r\n"; }
/** * Appends C# code to serialize a C# list into bytes. */ public static void AppendSerializerWriteCollection(ref string code, string fieldName, IFieldType elementType, string subfieldName, string schemaObjectTypeName) { string subfield = ""; if (subfieldName != null) { subfield = "." + subfieldName; } // Deal with list lengths string targetList = "o." + fieldName + subfield; code += " if (o." + fieldName + " == null || " + targetList + " == null || " + targetList + ".Count == 0) {\r\n"; PBP.AppendWriteByte(ref code, "0"); code += " }\r\n"; code += " else { \r\n"; PBP.AppendWriteVUInt16(ref code, targetList + ".Count"); if (elementType is PrimitiveFieldType) { PrimitiveFieldType primitiveFieldType = (PrimitiveFieldType)elementType; code += " foreach (" + PB.ToCSharpType(primitiveFieldType) + " primitive in " + targetList + ") {\r\n"; PBP.AppendWritePrimitive(ref code, "primitive", primitiveFieldType.PrimitiveType); code += " }\r\n"; } else if (elementType is ReferenceFieldType) { ReferenceFieldType referenceFieldType = (ReferenceFieldType)elementType; // list<enum> if (referenceFieldType.Referrable is PatternBufferEnum) { PatternBufferEnum patternBufferEnum = (PatternBufferEnum)referenceFieldType.Referrable; code += " foreach (" + PB.ToCSharpName(patternBufferEnum.Name) + " enumValue in " + targetList + ") {\r\n"; PBP.AppendWriteByte(ref code, "enumValueIndexMap[\"" + referenceFieldType.ReferrableName + "\"][enumValue.ToString()];\r\n"); code += " }\r\n"; } // list<something> else if (referenceFieldType.Referrable is PatternBufferType) { PatternBufferType patternBufferType = (PatternBufferType)referenceFieldType.Referrable; // All objects in the list are the same type; do not write type IDs for each item if (patternBufferType.IsFinal) { code += " foreach (" + PB.ToCSharpName(patternBufferType.Name) + " finalObject in " + targetList + ") {\r\n"; code += " Energize(finalObject, bytes, ref index, false);\r\n"; code += " }\r\n"; } // The objects in the list may be of different types; write the type ID for each item else { code += " foreach (" + schemaObjectTypeName + " abstractObject in " + targetList + ") {\r\n"; code += " Energize((" + schemaObjectTypeName + ")abstractObject, bytes, ref index, true);\r\n"; code += " }\r\n"; } } else { // what } } code += " }\r\n"; }
/** * Returns true if the type has a field of a prticular type. */ protected bool HasPrimitiveField(PatternBufferType type, string fieldName, PrimitiveType primitiveType) { PatternBufferField field = this.GetField <PrimitiveFieldType>(type, fieldName); return(((PrimitiveFieldType)field.FieldType).PrimitiveType == primitiveType); }