public static PropertyTypeKind DefaultTypeMapper(PropertyDefinition property, out TypeDefinition referencedType) { PropertyTypeKind fieldType = PropertyTypeKind.UNKNOWN; // If the property is a reference to another type, this variable contains the typedefinition. // Defaults to null. referencedType = null; // The actual type object of the property. TypeReference type = property.PropertyType; // The type could be a list<X> (GENERIC), so the actual type would be the first template // parameter. if (type.IsGenericInstance) { // We SUPPOSE the actual type is a List with 1 generic parameter. type = (type as GenericInstanceType).GenericArguments.First(); } // Get the type by literal name. fieldType = LiteralTypeMapper(type.Name); if (fieldType == PropertyTypeKind.TYPE_REF) { // The type is not a primitive and references something else. // We just resolve the reference and pass it back.. the caller can // decide what to do with it. var typeDefinition = type.Resolve(); referencedType = typeDefinition; } return(fieldType); }
// Get all properties from the type we are analyzing. public static List <IRClassProperty> ExtractClassProperties(TypeDefinition _subjectClass, out List <TypeDefinition> references) { // Will contain all typedefinitions of types referenced by this class. references = new List <TypeDefinition>(); // All properties for the given class definition. List <IRClassProperty> properties = new List <IRClassProperty>(); // Property != field // Properties expose fields by providing a getter/setter. // The properties are public accessible data, and these are the things that map // to protobuffer files. foreach (var property in _subjectClass.Properties) { // Property must have a setter method, otherwise it wouldn't be related to ProtoBuffers schema. if (property.SetMethod == null) { continue; } // Object which the current property references. TypeDefinition refDefinition; // Set of field (proto) options. IRClassProperty.ILPropertyOptions options = new IRClassProperty.ILPropertyOptions(); // Default to invalid field. options.Label = FieldLabel.INVALID; // IR type of the property. PropertyTypeKind propType = InspectorTools.DefaultTypeMapper(property, out refDefinition); // IR object - reference placeholder for the IR Class. IRTypeNode irReference = null; if (propType == PropertyTypeKind.TYPE_REF) { irReference = InspectorTools.ConstructIRType(refDefinition); // Also save the reference typedefinition for the caller to process. references.Add(refDefinition); } // Construct IR property and store. var prop = new IRClassProperty { Name = property.Name, Type = propType, ReferencedType = irReference, Options = options, }; properties.Add(prop); } return(properties); }
public static string TypeTostring(PropertyTypeKind type, IRClass current, IRTypeNode reference) { switch (type) { case PropertyTypeKind.DOUBLE: return("double"); case PropertyTypeKind.FLOAT: return("float"); case PropertyTypeKind.INT32: return("int32"); case PropertyTypeKind.INT64: return("int64"); case PropertyTypeKind.UINT32: return("uint32"); case PropertyTypeKind.UINT64: return("uint64"); case PropertyTypeKind.FIXED32: return("fixed32"); case PropertyTypeKind.FIXED64: return("fixed64"); case PropertyTypeKind.BOOL: return("bool"); case PropertyTypeKind.STRING: return("string"); case PropertyTypeKind.BYTES: return("bytes"); case PropertyTypeKind.TYPE_REF: return(ResolveTypeReferenceString(current, reference)); default: throw new Exception("Type not recognized!"); } }
// Give this function all bytes written to write the header of a field to the wire. // It will test if the last 3 bits are value 2. 2 means a length-delimited, =packed, // variable. // Little ENDIAN order! public static bool TagToPackedSpecifier(List <byte> tag, PropertyTypeKind fieldType) { // Read the last written byte. var lastByte = tag.Last(); // Check if the written bytes are formatted according to the spec. if (0 != (lastByte & 0x80)) { throw new InvalidProgramException( "The last byte of the field header must have it's MSB set to 0!"); } // Test if the last 3 bits equal 2 -> = packed | embedded message | string | bytes. // ONLY PRIMITIVE TYPES CAN BE PACKED! [varint, 32-bit, or 64-bit wire types] if (2 == (lastByte & 0x07) && fieldType < PropertyTypeKind.STRING) { return(true); } // Per default, return false. return(false); }
// Get all properties from the type we are analyzing. public static List <IRClassProperty> ExtractClassProperties(TypeDefinition _subjectClass, out List <TypeDefinition> references) { // Contains all references (TypeDefinitions) that are referenced by this class. references = new List <TypeDefinition>(); // All properties for the given class. List <IRClassProperty> properties = new List <IRClassProperty>(); // Propertye != field; see SilentOrbitInspector.ExtractClassproperties(..) foreach (var property in _subjectClass.Properties) { // Default to OPTIONAL label. The Google protobuffer compiler is written for // proto3 syntax, which does not allow REQUIRED. // Everything is implicitly OPTIONAL, but OPTIONAL fields who have the default value // will not be written onto the wire. // CARE MUST BE TAKEN to provide all necessary values when using these decompiled proto files. FieldLabel label = FieldLabel.OPTIONAL; // Each schema related property must have a set method, but repeated fields don't have // a set method. We must figure out if the property is lib related or schema related! if (property.SetMethod == null) { // Repeated field have propertyType RepeatedField<X>. if (property.PropertyType.Name.Contains("RepeatedField") == true && property.PropertyType.IsGenericInstance) { // This field must be analyzed. label = FieldLabel.REPEATED; } else { continue; } } // Object which the current property references. TypeDefinition refDefinition; // Field options (directly related to protobuf schema) IRClassProperty.ILPropertyOptions opts = new IRClassProperty.ILPropertyOptions(); // Add label to the property options. opts.Label = label; // Fetch the IR type of the property. - Doesn't actually matter, the Serialize handler will overwrite this. PropertyTypeKind propType = InspectorTools.DefaultTypeMapper(property, out refDefinition); // Construct IR reference placeholder. IRTypeNode irReference = null; if (propType == PropertyTypeKind.TYPE_REF) { irReference = InspectorTools.ConstructIRType(refDefinition); // And save the reference TYPEDEFINITION for the caller to process. references.Add(refDefinition); } // Fetch the fieldNumber for this property. var tag = ExtractFieldNumber(_subjectClass, property.Name); // Add it to the options. opts.PropertyOrder = tag; // Construct the IR property and store it. var prop = new IRClassProperty() { Name = property.Name, Type = propType, ReferencedType = irReference, Options = opts, }; properties.Add(prop); } return(properties); }