| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package serialization |
| |
| import ( |
| "bytes" |
| "compress/gzip" |
| "encoding/base64" |
| "fmt" |
| "mojo/public/go/bindings" |
| "mojom/mojom_tool/generated/mojom_files" |
| "mojom/mojom_tool/generated/mojom_types" |
| "mojom/mojom_tool/mojom" |
| myfmt "third_party/golang/src/fmt" |
| ) |
| |
| ////////////////////////////////////////////////// |
| /// Mojom Descriptor Serialization |
| ////////////////////////////////////////////////// |
| |
| // This variable may be set to false in order to omit emitting line and |
| // column numbers. This is useful in tests. |
| var emitLineAndColumnNumbers bool = true |
| |
| // This variable may be set to false in order to omit emitting computed |
| // packing. This is useful in tests. |
| var emitComputedPackingData bool = true |
| |
| // This variable may be set to false in order to omit emitting serialized |
| // runtime type info. This is useful in tests. |
| var emitSerializedRuntimeTypeInfo bool = true |
| |
| // Serialize serializes the MojomDescriptor into a binary form that is passed to the |
| // backend of the compiler in order to invoke the code generators. |
| // To do this we use Mojo serialization. |
| // If |debug| is true we also return a human-readable representation |
| // of the serialized mojom_types.FileGraph. |
| // This function is not thread safe. |
| func Serialize(d *mojom.MojomDescriptor, debug bool) (bytes []byte, debugString string, err error) { |
| return serialize(d, debug, true, true, true) |
| } |
| |
| // serialize() is a package-private version of the public method Serialize(). |
| // It is intended for use in tests because it allows setting of the variables |
| // emitLineAndColumnNumbers, emitComputedPackingData and emitSerializedRuntimeTypeInfo. |
| // This function is not thread safe because it sets and accesses these global |
| // variables. |
| func serialize(d *mojom.MojomDescriptor, debug, |
| emitLineAndColumnNumbersParam, emitComputedPackingDataParam, |
| emitSerializedRuntimeTypeInfoParam bool) (bytes []byte, debugString string, err error) { |
| |
| // Save the global state and then set it based on the parameters. |
| saveEmitLineAndColumnNumbers := emitLineAndColumnNumbers |
| emitLineAndColumnNumbers = emitLineAndColumnNumbersParam |
| saveEmitComputedPackingData := emitComputedPackingData |
| emitComputedPackingData = emitComputedPackingDataParam |
| saveEmitSerializedRuntimeTypeInfo := emitSerializedRuntimeTypeInfo |
| emitSerializedRuntimeTypeInfo = emitSerializedRuntimeTypeInfoParam |
| |
| fileGraph := translateDescriptor(d) |
| if debug { |
| debugString = myfmt.Sprintf("%#v", fileGraph) |
| } |
| encoder := bindings.NewEncoder() |
| encoder.SetDeterministic(true) |
| fileGraph.Encode(encoder) |
| bytes, _, err = encoder.Data() |
| |
| // Restore the original values of the global state. |
| emitLineAndColumnNumbers = saveEmitLineAndColumnNumbers |
| emitComputedPackingData = saveEmitComputedPackingData |
| emitSerializedRuntimeTypeInfo = saveEmitSerializedRuntimeTypeInfo |
| return |
| } |
| |
| // translateDescriptor translates from a mojom.MojomDescriptor (the pure Go |
| // representation used by the parser) to a mojom_files.MojomFileGraph (the |
| // Mojo Go representation used for serialization.) |
| func translateDescriptor(d *mojom.MojomDescriptor) *mojom_files.MojomFileGraph { |
| fileGraph := mojom_files.MojomFileGraph{} |
| |
| // Add |resolved_types| field. |
| fileGraph.ResolvedTypes = make(map[string]mojom_types.UserDefinedType) |
| for key, userDefinedType := range d.TypesByKey { |
| fileGraph.ResolvedTypes[key] = translateUserDefinedType(userDefinedType) |
| } |
| |
| // Add |resolved_values| field. |
| fileGraph.ResolvedValues = make(map[string]mojom_types.UserDefinedValue) |
| for key, userDefinedValue := range d.ValuesByKey { |
| fileGraph.ResolvedValues[key] = translateUserDefinedValue(userDefinedValue) |
| } |
| |
| // Add |files| field. |
| fileGraph.Files = make(map[string]mojom_files.MojomFile) |
| for name, file := range d.MojomFilesByName { |
| fileGraph.Files[name] = translateMojomFile(file, &fileGraph) |
| } |
| |
| return &fileGraph |
| } |
| |
| // translateMojomFile translates from a mojom.MojomFile (the pure Go |
| // representation used by the parser) to a mojom_files.MojomFile (the |
| // Mojo Go representation used for serialization.) |
| func translateMojomFile(f *mojom.MojomFile, fileGraph *mojom_files.MojomFileGraph) (file mojom_files.MojomFile) { |
| // file_name field |
| file.FileName = f.CanonicalFileName |
| |
| // specified_file_name_field |
| file.SpecifiedFileName = &f.SpecifiedFileName |
| |
| // module_namespace field |
| file.ModuleNamespace = &f.ModuleNamespace.Identifier |
| |
| // attributes field |
| if f.Attributes != nil { |
| file.Attributes = new([]mojom_types.Attribute) |
| for _, attr := range f.Attributes.List { |
| *(file.Attributes) = append(*(file.Attributes), translateMojomAttribute(&attr)) |
| } |
| } |
| |
| // imports field |
| if len(f.Imports) > 0 { |
| file.Imports = new([]string) |
| for _, importName := range f.Imports { |
| // We support serializing a MojomFileGraph that has not had import names |
| // resolved to canonical file names. (For example this is the case in |
| // meta-data-only mode.) |
| if importName.CanonicalFileName != "" { |
| *(file.Imports) = append(*(file.Imports), importName.CanonicalFileName) |
| } |
| } |
| if len(*file.Imports) == 0 { |
| // If we are in a mode where canonical file names are not being resolved |
| // then emit a null value for |imports| rather than an empty array. |
| file.Imports = nil |
| } |
| } |
| |
| // We will populate a RuntimeTypeInfo structure and then serialize it and |
| // the serialized bytes will form the |serialized_runtime_type_info| field |
| // of the MojomFile. |
| typeInfo := mojom_types.RuntimeTypeInfo{} |
| typeInfo.Services = make(map[string]string) |
| typeInfo.TypeMap = make(map[string]mojom_types.UserDefinedType) |
| |
| // We populate the declared_mojom_objects field |
| // and simultaneously we populate typeInfo.TypeMap. |
| |
| // Interfaces |
| if f.Interfaces != nil && len(f.Interfaces) > 0 { |
| file.DeclaredMojomObjects.Interfaces = new([]string) |
| for _, intrfc := range f.Interfaces { |
| typeKey := intrfc.TypeKey() |
| *(file.DeclaredMojomObjects.Interfaces) = append(*(file.DeclaredMojomObjects.Interfaces), typeKey) |
| |
| addServiceName(intrfc, &typeInfo) |
| typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[typeKey] |
| if intrfc.Enums != nil { |
| // Add embedded enums to typeInfo.TypeMap. |
| for _, enum := range intrfc.Enums { |
| typeKey := enum.TypeKey() |
| typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[typeKey] |
| } |
| } |
| } |
| } |
| |
| // Structs |
| if f.Structs != nil && len(f.Structs) > 0 { |
| file.DeclaredMojomObjects.Structs = new([]string) |
| for _, strct := range f.Structs { |
| typeKey := strct.TypeKey() |
| *(file.DeclaredMojomObjects.Structs) = append(*(file.DeclaredMojomObjects.Structs), typeKey) |
| typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[typeKey] |
| if strct.Enums != nil { |
| // Add embedded enums to typeInfo.TypeMap. |
| for _, enum := range strct.Enums { |
| typeKey := enum.TypeKey() |
| typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[typeKey] |
| } |
| } |
| } |
| } |
| |
| // Unions |
| if f.Unions != nil && len(f.Unions) > 0 { |
| file.DeclaredMojomObjects.Unions = new([]string) |
| for _, union := range f.Unions { |
| typeKey := union.TypeKey() |
| *(file.DeclaredMojomObjects.Unions) = append(*(file.DeclaredMojomObjects.Unions), typeKey) |
| typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[typeKey] |
| } |
| } |
| |
| // TopLevelEnums |
| if f.Enums != nil && len(f.Enums) > 0 { |
| file.DeclaredMojomObjects.TopLevelEnums = new([]string) |
| for _, enum := range f.Enums { |
| typeKey := enum.TypeKey() |
| *(file.DeclaredMojomObjects.TopLevelEnums) = append(*(file.DeclaredMojomObjects.TopLevelEnums), typeKey) |
| typeInfo.TypeMap[typeKey] = fileGraph.ResolvedTypes[typeKey] |
| } |
| } |
| |
| // TopLevelConstants |
| if f.Constants != nil && len(f.Constants) > 0 { |
| file.DeclaredMojomObjects.TopLevelConstants = new([]string) |
| for _, constant := range f.Constants { |
| *(file.DeclaredMojomObjects.TopLevelConstants) = append(*(file.DeclaredMojomObjects.TopLevelConstants), constant.ValueKey()) |
| } |
| } |
| |
| // TODO(rudominer) Do we need the EmbeddedEnums and EmbeddedConstants |
| // fields in KeysByType. It seems these fields are not currently being |
| // used in mojom_translator.py. |
| |
| // SerializedRuntimeTypeInfo |
| if emitSerializedRuntimeTypeInfo { |
| encoder := bindings.NewEncoder() |
| encoder.SetDeterministic(true) |
| typeInfo.Encode(encoder) |
| byteSlice, _, err := encoder.Data() |
| if err != nil { |
| panic(fmt.Sprintf("Error while serializing runtimeTypeInfo: %s", err.Error())) |
| } |
| var compressedBytes bytes.Buffer |
| gzipWriter, _ := gzip.NewWriterLevel(&compressedBytes, gzip.BestCompression) |
| _, err = gzipWriter.Write(byteSlice) |
| if err != nil { |
| panic(fmt.Sprintf("Error while gzipping runtimeTypeInfo: %s", err.Error())) |
| } |
| err = gzipWriter.Close() |
| if err != nil { |
| panic(fmt.Sprintf("Error while gzipping runtimeTypeInfo: %s", err.Error())) |
| } |
| byteSlice = compressedBytes.Bytes() |
| encoded := base64.StdEncoding.EncodeToString(byteSlice) |
| file.SerializedRuntimeTypeInfo = &encoded |
| } |
| |
| return |
| } |
| |
| // addServiceName will add the service name of |intrfc| to the |Services| field of |typeInfo| |
| // if |intrfc| is a top-level interface, meaning that it has a non-nil service name. In that |
| // case this method returns true. Otherwise this method will do nothing and return fals. |
| func addServiceName(intrfc *mojom.MojomInterface, typeInfo *mojom_types.RuntimeTypeInfo) (isTopLevel bool) { |
| isTopLevel = intrfc.ServiceName != nil |
| if isTopLevel { |
| typeInfo.Services[*intrfc.ServiceName] = intrfc.TypeKey() |
| } |
| return |
| } |
| |
| // translateUserDefinedType translates from a mojom.UserDefinedType (the pure Go |
| // representation used by the parser) to a mojom_types.UserDefinedType (the |
| // Mojo Go representation used for serialization.) |
| func translateUserDefinedType(t mojom.UserDefinedType) mojom_types.UserDefinedType { |
| switch p := t.(type) { |
| case *mojom.MojomStruct: |
| return &mojom_types.UserDefinedTypeStructType{translateMojomStruct(p)} |
| case *mojom.MojomInterface: |
| return translateMojomInterface(p) |
| case *mojom.MojomEnum: |
| return translateMojomEnum(p) |
| case *mojom.MojomUnion: |
| return translateMojomUnion(p) |
| default: |
| panic(fmt.Sprintf("Unexpected type: %T", t)) |
| |
| } |
| } |
| |
| func translateMojomStruct(s *mojom.MojomStruct) mojom_types.MojomStruct { |
| mojomStruct := mojom_types.MojomStruct{} |
| mojomStruct.DeclData = translateDeclarationData(&s.DeclarationData) |
| mojomStruct.DeclData.ContainedDeclarations = translateContainedDeclarations(&s.NestedDeclarations) |
| |
| for _, field := range s.FieldsInOrdinalOrder() { |
| mojomStruct.Fields = append(mojomStruct.Fields, translateStructField(field)) |
| } |
| |
| if emitComputedPackingData { |
| versionInfo := s.VersionInfo() |
| mojomStruct.VersionInfo = new([]mojom_types.StructVersion) |
| for _, version := range versionInfo { |
| (*mojomStruct.VersionInfo) = append(*mojomStruct.VersionInfo, |
| translateStructVersion(version)) |
| } |
| } |
| |
| return mojomStruct |
| } |
| |
| func translateStructVersion(v mojom.StructVersion) mojom_types.StructVersion { |
| return mojom_types.StructVersion{ |
| VersionNumber: v.VersionNumber, |
| NumFields: v.NumFields, |
| NumBytes: v.NumBytes, |
| } |
| } |
| |
| func translateStructField(f *mojom.StructField) (field mojom_types.StructField) { |
| field.DeclData = translateDeclarationData(&f.DeclarationData) |
| field.Type = translateTypeRef(f.FieldType) |
| if f.DefaultValue != nil { |
| field.DefaultValue = translateDefaultFieldValue(f.DefaultValue) |
| } |
| if emitComputedPackingData { |
| // TODO(rudominer) Check the allowed size of offsets. The type used in |
| // mojom_types.mojom might need to be changed. |
| field.Offset = int32(f.Offset()) |
| field.Bit = int8(f.Bit()) |
| field.MinVersion = f.MinVersion() |
| } |
| return |
| } |
| |
| func translateDefaultFieldValue(v mojom.ValueRef) mojom_types.DefaultFieldValue { |
| switch v := v.(type) { |
| case mojom.LiteralValue: |
| if v.IsDefault() { |
| return &mojom_types.DefaultFieldValueDefaultKeyword{mojom_types.DefaultKeyword{}} |
| } |
| return &mojom_types.DefaultFieldValueValue{translateLiteralValue(v)} |
| case *mojom.UserValueRef: |
| return &mojom_types.DefaultFieldValueValue{translateUserValueRef(v)} |
| default: |
| panic(fmt.Sprintf("Unexpected ValueRef type: %T", v)) |
| |
| } |
| } |
| |
| func translateMojomInterface(intrfc *mojom.MojomInterface) *mojom_types.UserDefinedTypeInterfaceType { |
| mojomInterface := mojom_types.UserDefinedTypeInterfaceType{} |
| |
| mojomInterface.Value.DeclData = translateDeclarationData(&intrfc.DeclarationData) |
| mojomInterface.Value.DeclData.ContainedDeclarations = translateContainedDeclarations(&intrfc.NestedDeclarations) |
| |
| mojomInterface.Value.ServiceName = intrfc.ServiceName |
| |
| mojomInterface.Value.Methods = make(map[uint32]mojom_types.MojomMethod) |
| for ordinal, method := range intrfc.MethodsByOrdinal { |
| mojomInterface.Value.Methods[ordinal] = translateMojomMethod(method) |
| } |
| if emitComputedPackingData { |
| mojomInterface.Value.CurrentVersion = intrfc.Version() |
| } |
| |
| return &mojomInterface |
| } |
| |
| func translateMojomMethod(method *mojom.MojomMethod) mojom_types.MojomMethod { |
| mojomMethod := mojom_types.MojomMethod{} |
| |
| // decl_data |
| mojomMethod.DeclData = translateDeclarationData(&method.DeclarationData) |
| |
| // parameters |
| mojomMethod.Parameters = translateMojomStruct(method.Parameters) |
| |
| // response_params |
| if method.ResponseParameters != nil { |
| responseParams := translateMojomStruct(method.ResponseParameters) |
| mojomMethod.ResponseParams = &responseParams |
| } |
| |
| // ordinal |
| mojomMethod.Ordinal = method.Ordinal |
| |
| if emitComputedPackingData { |
| mojomMethod.MinVersion = method.MinVersion() |
| } |
| |
| return mojomMethod |
| } |
| |
| func translateMojomEnum(enum *mojom.MojomEnum) *mojom_types.UserDefinedTypeEnumType { |
| mojomEnum := mojom_types.UserDefinedTypeEnumType{} |
| mojomEnum.Value.DeclData = translateDeclarationData(&enum.DeclarationData) |
| for _, value := range enum.Values { |
| mojomEnum.Value.Values = append(mojomEnum.Value.Values, translateEnumValue(value)) |
| } |
| return &mojomEnum |
| } |
| |
| func translateMojomUnion(union *mojom.MojomUnion) *mojom_types.UserDefinedTypeUnionType { |
| mojomUnion := mojom_types.UserDefinedTypeUnionType{} |
| mojomUnion.Value.DeclData = translateDeclarationData(&union.DeclarationData) |
| for _, field := range union.FieldsInTagOrder() { |
| mojomUnion.Value.Fields = append(mojomUnion.Value.Fields, |
| translateUnionField(field)) |
| } |
| return &mojomUnion |
| } |
| |
| func translateUnionField(unionField *mojom.UnionField) mojom_types.UnionField { |
| outUnionField := mojom_types.UnionField{} |
| outUnionField.DeclData = translateDeclarationData(&unionField.DeclarationData) |
| outUnionField.Type = translateTypeRef(unionField.FieldType) |
| outUnionField.Tag = unionField.Tag |
| return outUnionField |
| } |
| |
| // WARNING: Do not invoke this function on a UserDefinedValue of type BuiltInConstantValue because |
| // objects of those types do not have a type_key and do not correspond to a mojom_types.UserDefinedValue. |
| func translateUserDefinedValue(v mojom.UserDefinedValue) mojom_types.UserDefinedValue { |
| switch t := v.(type) { |
| case *mojom.UserDefinedConstant: |
| return translateUserDefinedConstant(t) |
| case *mojom.EnumValue: |
| return &mojom_types.UserDefinedValueEnumValue{translateEnumValue(t)} |
| case *mojom.BuiltInConstantValue: |
| panic("Do not invoke translateUserDefinedValue on BuiltInConstantValue.") |
| default: |
| panic(fmt.Sprintf("Unexpected UserDefinedValue type %T", v)) |
| |
| } |
| } |
| |
| func translateUserDefinedConstant(t *mojom.UserDefinedConstant) *mojom_types.UserDefinedValueDeclaredConstant { |
| declaredConstant := mojom_types.UserDefinedValueDeclaredConstant{} |
| declaredConstant.Value.Type = translateTypeRef(t.DeclaredType()) |
| declaredConstant.Value.DeclData = *translateDeclarationData(&t.DeclarationData) |
| declaredConstant.Value.Value = translateValueRef(t.ValueRef()) |
| // TODO(rudominer) implement UserDefinedValue.resolved_concrete_value. |
| // declaredConstant.ResolvedConcreteValue = |
| // translateConcreteValue(t.ValueRef().ResolvedConcreteValue())) |
| return &declaredConstant |
| } |
| |
| func translateEnumValue(v *mojom.EnumValue) mojom_types.EnumValue { |
| enumValue := mojom_types.EnumValue{} |
| enumValue.DeclData = translateDeclarationData(&v.DeclarationData) |
| enumValue.EnumTypeKey = v.EnumType().TypeKey() |
| if v.ValueRef() != nil { |
| enumValue.InitializerValue = translateValueRef(v.ValueRef()) |
| } |
| if !v.IntValueComputed { |
| panic(fmt.Sprintf("IntValueComputed is false for %v.", v)) |
| } |
| enumValue.IntValue = v.ComputedIntValue |
| return enumValue |
| } |
| |
| func translateTypeRef(typeRef mojom.TypeRef) mojom_types.Type { |
| switch t := typeRef.(type) { |
| case mojom.SimpleType: |
| return translateSimpleType(t) |
| case mojom.StringType: |
| return translateStringType(t) |
| case mojom.HandleTypeRef: |
| return translateHandleType(t) |
| case mojom.ArrayTypeRef: |
| return translateArrayType(&t) |
| case *mojom.ArrayTypeRef: |
| return translateArrayType(t) |
| case mojom.MapTypeRef: |
| return translateMapType(&t) |
| case *mojom.MapTypeRef: |
| return translateMapType(t) |
| case *mojom.UserTypeRef: |
| return translateUserTypeRef(t) |
| default: |
| panic(fmt.Sprintf("Unexpected TypeRef type %T", t)) |
| } |
| } |
| |
| func translateSimpleType(simpleType mojom.SimpleType) *mojom_types.TypeSimpleType { |
| var value mojom_types.SimpleType |
| switch simpleType { |
| case mojom.SimpleTypeBool: |
| value = mojom_types.SimpleType_Bool |
| case mojom.SimpleTypeDouble: |
| value = mojom_types.SimpleType_Double |
| case mojom.SimpleTypeFloat: |
| value = mojom_types.SimpleType_Float |
| case mojom.SimpleTypeInt8: |
| value = mojom_types.SimpleType_Int8 |
| case mojom.SimpleTypeInt16: |
| value = mojom_types.SimpleType_Int16 |
| case mojom.SimpleTypeInt32: |
| value = mojom_types.SimpleType_Int32 |
| case mojom.SimpleTypeInt64: |
| value = mojom_types.SimpleType_Int64 |
| case mojom.SimpleTypeUInt8: |
| value = mojom_types.SimpleType_Uint8 |
| case mojom.SimpleTypeUInt16: |
| value = mojom_types.SimpleType_Uint16 |
| case mojom.SimpleTypeUInt32: |
| value = mojom_types.SimpleType_Uint32 |
| case mojom.SimpleTypeUInt64: |
| value = mojom_types.SimpleType_Uint64 |
| } |
| return &mojom_types.TypeSimpleType{value} |
| } |
| |
| func translateStringType(stringType mojom.StringType) *mojom_types.TypeStringType { |
| return &mojom_types.TypeStringType{mojom_types.StringType{stringType.Nullable()}} |
| } |
| |
| func translateHandleType(handleType mojom.HandleTypeRef) *mojom_types.TypeHandleType { |
| var kind mojom_types.HandleType_Kind |
| switch handleType.HandleKind() { |
| case mojom.HandleKindUnspecified: |
| kind = mojom_types.HandleType_Kind_Unspecified |
| case mojom.HandleKindMessagePipe: |
| kind = mojom_types.HandleType_Kind_MessagePipe |
| case mojom.HandleKindDataPipeConsumer: |
| kind = mojom_types.HandleType_Kind_DataPipeConsumer |
| case mojom.HandleKindDataPipeProducer: |
| kind = mojom_types.HandleType_Kind_DataPipeProducer |
| case mojom.HandleKindSharedBuffer: |
| kind = mojom_types.HandleType_Kind_SharedBuffer |
| } |
| return &mojom_types.TypeHandleType{mojom_types.HandleType{handleType.Nullable(), kind}} |
| } |
| |
| func translateArrayType(arrayType *mojom.ArrayTypeRef) *mojom_types.TypeArrayType { |
| return &mojom_types.TypeArrayType{mojom_types.ArrayType{ |
| Nullable: arrayType.Nullable(), |
| FixedLength: int32(arrayType.FixedLength()), |
| ElementType: translateTypeRef(arrayType.ElementType())}} |
| } |
| |
| func translateMapType(mapType *mojom.MapTypeRef) *mojom_types.TypeMapType { |
| return &mojom_types.TypeMapType{mojom_types.MapType{ |
| Nullable: mapType.Nullable(), |
| KeyType: translateTypeRef(mapType.KeyType()), |
| ValueType: translateTypeRef(mapType.ValueType())}} |
| } |
| |
| func translateUserTypeRef(userType *mojom.UserTypeRef) *mojom_types.TypeTypeReference { |
| typeKey := stringPointer(userType.ResolvedType().TypeKey()) |
| identifier := stringPointer(userType.Identifier()) |
| return &mojom_types.TypeTypeReference{mojom_types.TypeReference{ |
| Nullable: userType.Nullable(), |
| IsInterfaceRequest: userType.IsInterfaceRequest(), |
| Identifier: identifier, |
| TypeKey: typeKey}} |
| } |
| |
| func translateValueRef(valueRef mojom.ValueRef) mojom_types.Value { |
| switch valueRef := valueRef.(type) { |
| case mojom.LiteralValue: |
| return translateLiteralValue(valueRef) |
| case *mojom.UserValueRef: |
| return translateUserValueRef(valueRef) |
| default: |
| panic(fmt.Sprintf("Unexpected ValueRef type %T", valueRef)) |
| } |
| } |
| |
| func translateLiteralValue(v mojom.LiteralValue) *mojom_types.ValueLiteralValue { |
| var lv mojom_types.LiteralValue |
| switch v.ValueType() { |
| case mojom.SimpleTypeBool: |
| lv = &mojom_types.LiteralValueBoolValue{v.Value().(bool)} |
| case mojom.SimpleTypeDouble: |
| lv = &mojom_types.LiteralValueDoubleValue{v.Value().(float64)} |
| case mojom.SimpleTypeFloat: |
| lv = &mojom_types.LiteralValueFloatValue{v.Value().(float32)} |
| case mojom.SimpleTypeInt8: |
| lv = &mojom_types.LiteralValueInt8Value{v.Value().(int8)} |
| case mojom.SimpleTypeInt16: |
| lv = &mojom_types.LiteralValueInt16Value{v.Value().(int16)} |
| case mojom.SimpleTypeInt32: |
| lv = &mojom_types.LiteralValueInt32Value{v.Value().(int32)} |
| case mojom.SimpleTypeInt64: |
| lv = &mojom_types.LiteralValueInt64Value{v.Value().(int64)} |
| case mojom.SimpleTypeUInt8: |
| lv = &mojom_types.LiteralValueUint8Value{v.Value().(uint8)} |
| case mojom.SimpleTypeUInt16: |
| lv = &mojom_types.LiteralValueUint16Value{v.Value().(uint16)} |
| case mojom.SimpleTypeUInt32: |
| lv = &mojom_types.LiteralValueUint32Value{v.Value().(uint32)} |
| case mojom.SimpleTypeUInt64: |
| lv = &mojom_types.LiteralValueUint64Value{v.Value().(uint64)} |
| case mojom.StringLiteralType: |
| lv = &mojom_types.LiteralValueStringValue{v.Value().(string)} |
| default: |
| panic(fmt.Sprintf("Unexpected literal value type %d", v.ValueType())) |
| } |
| return &mojom_types.ValueLiteralValue{lv} |
| } |
| |
| func translateBuiltInConstantValue(t mojom.BuiltInConstantValue) *mojom_types.ValueBuiltinValue { |
| builtInValue := mojom_types.ValueBuiltinValue{} |
| switch t { |
| case mojom.FloatInfinity: |
| builtInValue.Value = mojom_types.BuiltinConstantValue_FloatInfinity |
| case mojom.FloatNegativeInfinity: |
| builtInValue.Value = mojom_types.BuiltinConstantValue_FloatNegativeInfinity |
| case mojom.FloatNAN: |
| builtInValue.Value = mojom_types.BuiltinConstantValue_FloatNan |
| case mojom.DoubleInfinity: |
| builtInValue.Value = mojom_types.BuiltinConstantValue_DoubleInfinity |
| case mojom.DoubleNegativeInfinity: |
| builtInValue.Value = mojom_types.BuiltinConstantValue_DoubleNegativeInfinity |
| case mojom.DoubleNAN: |
| builtInValue.Value = mojom_types.BuiltinConstantValue_DoubleNan |
| default: |
| panic(fmt.Sprintf("Unrecognized BuiltInConstantValue %v", t)) |
| } |
| return &builtInValue |
| } |
| |
| func translateUserValueRef(r *mojom.UserValueRef) mojom_types.Value { |
| switch t := r.ResolvedConcreteValue().(type) { |
| case mojom.BuiltInConstantValue: |
| return translateBuiltInConstantValue(t) |
| default: |
| valueKey := stringPointer(r.ResolvedDeclaredValue().ValueKey()) |
| return &mojom_types.ValueUserValueReference{mojom_types.UserValueReference{ |
| Identifier: r.Identifier(), |
| ValueKey: valueKey}} |
| } |
| } |
| |
| func translateDeclarationData(d *mojom.DeclarationData) *mojom_types.DeclarationData { |
| declData := mojom_types.DeclarationData{} |
| |
| // attributes field |
| if d.Attributes() != nil { |
| declData.Attributes = new([]mojom_types.Attribute) |
| for _, attr := range d.Attributes().List { |
| *(declData.Attributes) = append(*(declData.Attributes), translateMojomAttribute(&attr)) |
| } |
| } |
| |
| // min_version field |
| // TODO(rudominer) Eliminate the min_version field from struct DeclarationData |
| |
| // short_name field |
| declData.ShortName = stringPointer(d.SimpleName()) |
| |
| // full_identifier field |
| switch declaredObject := d.DeclaredObject().(type) { |
| // We do not serialize the fully-qualified-name for objects that only exist |
| // as children of their container objects and are not independently |
| // referenceable. |
| case *mojom.StructField, *mojom.MojomMethod, *mojom.UnionField: |
| case *mojom.MojomStruct: |
| switch declaredObject.StructType() { |
| case mojom.StructTypeRegular: |
| declData.FullIdentifier = stringPointer(d.FullyQualifiedName()) |
| } |
| default: |
| declData.FullIdentifier = stringPointer(d.FullyQualifiedName()) |
| } |
| |
| // declared_ordinal field |
| if d.DeclaredOrdinal() < 0 { |
| declData.DeclaredOrdinal = -1 |
| } else { |
| declData.DeclaredOrdinal = int32(d.DeclaredOrdinal()) |
| } |
| |
| // declaration_order |
| if d.LexicalPosition() < 0 { |
| declData.DeclarationOrder = -1 |
| } else { |
| declData.DeclarationOrder = d.LexicalPosition() |
| } |
| |
| // container_type_key |
| containingType := d.ContainingType() |
| if containingType != nil { |
| switch d.DeclaredObject().(type) { |
| // We do not serialize the |container_type_key| field for objects that only exist |
| // as children of their container objects and are not independently |
| // referenceable. |
| case *mojom.StructField, *mojom.MojomMethod: |
| // We do not serialize the |container_type_key| field for an EnumValue |
| // because the EnumValue already has the type_key of the Enum |
| // in a different field. |
| case *mojom.EnumValue: |
| default: |
| declData.ContainerTypeKey = stringPointer(containingType.TypeKey()) |
| } |
| } |
| |
| // source_file_info |
| declData.SourceFileInfo = new(mojom_types.SourceFileInfo) |
| declData.SourceFileInfo.FileName = d.OwningFile().CanonicalFileName |
| if emitLineAndColumnNumbers { |
| declData.SourceFileInfo.LineNumber = d.LineNumber() |
| declData.SourceFileInfo.ColumnNumber = d.ColumnNumber() |
| } |
| return &declData |
| } |
| |
| // Returns nil if there are no contained declarations |
| func translateContainedDeclarations(container *mojom.NestedDeclarations) *mojom_types.ContainedDeclarations { |
| if container.Enums == nil && container.Constants == nil { |
| return nil |
| } |
| declarations := mojom_types.ContainedDeclarations{} |
| if container.Enums != nil { |
| declarations.Enums = new([]string) |
| for _, enum := range container.Enums { |
| *declarations.Enums = append(*declarations.Enums, enum.TypeKey()) |
| } |
| } |
| if container.Constants != nil { |
| declarations.Constants = new([]string) |
| for _, constant := range container.Constants { |
| *declarations.Constants = append(*declarations.Constants, constant.ValueKey()) |
| } |
| } |
| return &declarations |
| } |
| |
| func translateMojomAttribute(a *mojom.MojomAttribute) (attribute mojom_types.Attribute) { |
| return mojom_types.Attribute{a.Key, translateLiteralValue(a.Value).Value} |
| } |
| |
| // stringPointer is a convenience function for creating a pointer to a string whose value |
| // is the specified string. It may be used in situations where the compiler will |
| // not allow you to take the address of a string value directly, such as the |
| // return value of a function. It is necessary to create pointers to strings because |
| // that is how the Mojom type |string?| (i.e. nullable string) is represented in |
| // in the Mojom Go bindings. |
| func stringPointer(s string) *string { |
| return &s |
| } |