// 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_parser/generated/mojom_files"
	"mojom/mojom_parser/generated/mojom_types"
	"mojom/mojom_parser/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

// By default we do not populate the complete type set of each top-level interface
// because doing so is expensive and we are not currently using the the data.
var populateCompleteTypeSet bool = false

// 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, false)
}

// 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, emitSerializedRuntimeTypeInfo
// and populateCompleteTypeSet.
// This function is not thread safe because it sets and accesses these global
// variables.
func serialize(d *mojom.MojomDescriptor, debug,
	emitLineAndColumnNumbersParam, emitComputedPackingDataParam, emitSerializedRuntimeTypeInfoParam,
	populateCompleteTypeSetParam 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
	savePopulateCompleteTypeSet := populateCompleteTypeSet
	populateCompleteTypeSet = populateCompleteTypeSetParam

	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
	populateCompleteTypeSet = savePopulateCompleteTypeSet
	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.ServicesByName = make(map[string]mojom_types.ServiceTypeInfo)
	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)

			addServiceTypeInfo(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
}

// addServiceTypeInfo will add a ServiceTypeInfo to the ServicesByName field of |typeInfo| corresponding
// to |intrfc| 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 addServiceTypeInfo(intrfc *mojom.MojomInterface, typeInfo *mojom_types.RuntimeTypeInfo) (isTopLevel bool) {
	isTopLevel = intrfc.ServiceName != nil
	if isTopLevel {
		serviceTypeInfo := mojom_types.ServiceTypeInfo{}
		serviceTypeInfo.TopLevelInterface = intrfc.TypeKey()
		if populateCompleteTypeSet {
			serviceTypeInfo.CompleteTypeSet = intrfc.FindReachableTypes()
		}
		typeInfo.ServicesByName[*intrfc.ServiceName] = serviceTypeInfo
	}
	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)
	}

	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
	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}}
		// We do not populate ResolvedConcreteValue because it is deprecated.
	}
}

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
}
