func assignFromAliasedPrimitiveType(
	sourceEndpoint *StorageConversionEndpoint,
	destinationEndpoint *StorageConversionEndpoint,
	conversionContext *StorageConversionContext) StorageTypeConversion {
	if _, sourceIsOptional := AsOptionalType(sourceEndpoint.Type()); sourceIsOptional {
		return nil
	}
	_, sourceType, ok := conversionContext.ResolveType(sourceEndpoint.Type())
	if !ok {
		return nil
	}
	sourcePrimitive, sourceIsPrimitive := AsPrimitiveType(sourceType)
	if !sourceIsPrimitive {
		return nil
	}
	primitiveEndpoint := sourceEndpoint.WithType(sourcePrimitive)
	conversion, _ := createTypeConversion(primitiveEndpoint, destinationEndpoint, conversionContext)
	if conversion == nil {
		return nil
	}
	return func(reader dst.Expr, writer func(dst.Expr) []dst.Stmt, generationContext *CodeGenerationContext) []dst.Stmt {
		actualReader := &dst.CallExpr{
			Fun:  sourcePrimitive.AsType(generationContext),
			Args: []dst.Expr{reader},
		}
		return conversion(actualReader, writer, generationContext)
	}
}
assignFromAliasedPrimitiveType will convert an alias of a primitive type into that primitive
type as long as it is not optional and we can find a conversion to consume that primitive value
package astmodel
import (
	"go/token"
	"github.com/Azure/k8s-infra/hack/generator/pkg/astbuilder"
	"github.com/dave/dst"
	"github.com/pkg/errors"
)
type StorageTypeConversion func(reader dst.Expr, writer func(dst.Expr) []dst.Stmt, generationContext *CodeGenerationContext) []dst.Stmt
type StorageTypeConversionFactory func(
	source *StorageConversionEndpoint,
	destination *StorageConversionEndpoint,
	conversionContext *StorageConversionContext) StorageTypeConversion
var typeConversionFactories []StorageTypeConversionFactory
func init() {
	typeConversionFactories = []StorageTypeConversionFactory{
		assignPrimitiveTypeFromPrimitiveType,
		assignAliasedPrimitiveTypeFromAliasedPrimitiveType,
		assignArrayFromArray,
		assignMapFromMap,
		assignEnumTypeFromEnumType,
		assignPrimitiveTypeFromEnumType,
		assignObjectTypeFromObjectType,
		assignKnownReferenceFromKnownReference,
		assignFromOptionalType,  
		assignToOptionalType,
		assignToEnumerationType,
		assignFromAliasedPrimitiveType,
		assignToAliasedPrimitiveType,
	}
}
func createTypeConversion(
	sourceEndpoint *StorageConversionEndpoint,
	destinationEndpoint *StorageConversionEndpoint,
	conversionContext *StorageConversionContext) (StorageTypeConversion, error) {
	for _, f := range typeConversionFactories {
		result := f(sourceEndpoint, destinationEndpoint, conversionContext)
		if result != nil {
			return result, nil
		}
	}
	err := errors.Errorf(
		"no conversion found to assign %q from %q",
		destinationEndpoint.name,
		sourceEndpoint.name)
	return nil, err
}
func assignToOptionalType(
	sourceEndpoint *StorageConversionEndpoint,
	destinationEndpoint *StorageConversionEndpoint,
	conversionContext *StorageConversionContext) StorageTypeConversion {
	destinationOptional, destinationIsOptional := AsOptionalType(destinationEndpoint.Type())
	if !destinationIsOptional {
		return nil
	}
	unwrappedEndpoint := destinationEndpoint.WithType(destinationOptional.element)
	conversion, _ := createTypeConversion(sourceEndpoint, unwrappedEndpoint, conversionContext)
	if conversion == nil {
		return nil
	}
	local := destinationEndpoint.CreateLocal("", "Temp")
	return func(reader dst.Expr, writer func(dst.Expr) []dst.Stmt, generationContext *CodeGenerationContext) []dst.Stmt {
		addrOfWriter := func(expr dst.Expr) []dst.Stmt {
			if _, ok := expr.(*dst.Ident); ok {
				return writer(astbuilder.AddrOf(expr))
			}
			assignment := astbuilder.SimpleAssignment(
				dst.NewIdent(local),
				token.DEFINE,
				expr)
			writing := writer(astbuilder.AddrOf(dst.NewIdent(local)))
			return astbuilder.Statements(assignment, writing)
		}
		return conversion(reader, addrOfWriter, generationContext)
	}
}
func assignFromOptionalType(
	sourceEndpoint *StorageConversionEndpoint,
	destinationEndpoint *StorageConversionEndpoint,
	conversionContext *StorageConversionContext) StorageTypeConversion {
	sourceOptional, sourceIsOptional := AsOptionalType(sourceEndpoint.Type())
	if !sourceIsOptional {
		return nil
	}
	unwrappedEndpoint := sourceEndpoint.WithType(sourceOptional.element)
	conversion, _ := createTypeConversion(unwrappedEndpoint, destinationEndpoint, conversionContext)
	if conversion == nil {
		return nil
	}
	local := sourceEndpoint.CreateLocal("", "Read")
	return func(reader dst.Expr, writer func(dst.Expr) []dst.Stmt, generationContext *CodeGenerationContext) []dst.Stmt {
		var cacheOriginal dst.Stmt
		var actualReader dst.Expr
		switch reader.(type) {
		case *dst.Ident, *dst.SelectorExpr:
			cacheOriginal = nil
			actualReader = reader
		default:
			cacheOriginal = astbuilder.SimpleAssignment(
				dst.NewIdent(local),
				token.DEFINE,
				reader)
			actualReader = dst.NewIdent(local)
		}
		checkForNil := astbuilder.NotEqual(actualReader, dst.NewIdent("nil"))
		writeActualValue := conversion(
			astbuilder.Dereference(actualReader),
			writer,
			generationContext)
		writeZeroValue := writer(
			destinationEndpoint.Type().AsZero(conversionContext.types, generationContext))
		stmt := &dst.IfStmt{
			Cond: checkForNil,
			Body: astbuilder.StatementBlock(writeActualValue...),
			Else: astbuilder.StatementBlock(writeZeroValue...),
		}
		return astbuilder.Statements(cacheOriginal, stmt)
	}
}
func assignToEnumerationType(
	sourceEndpoint *StorageConversionEndpoint,
	destinationEndpoint *StorageConversionEndpoint,
	conversionContext *StorageConversionContext) StorageTypeConversion {
	_, dstIsOpt := AsOptionalType(destinationEndpoint.Type())
	if dstIsOpt {
		return nil
	}
	dstName, dstType, ok := conversionContext.ResolveType(destinationEndpoint.Type())
	if !ok {
		return nil
	}
	dstEnum, ok := AsEnumType(dstType)
	if !ok {
		return nil
	}
	dstEp := destinationEndpoint.WithType(dstEnum.baseType)
	conversion, _ := createTypeConversion(sourceEndpoint, dstEp, conversionContext)
	if conversion == nil {
		return nil
	}
	return func(reader dst.Expr, writer func(dst.Expr) []dst.Stmt, generationContext *CodeGenerationContext) []dst.Stmt {
		convertingWriter := func(expr dst.Expr) []dst.Stmt {
			cast := &dst.CallExpr{
				Fun:  dstName.AsType(generationContext),
				Args: []dst.Expr{expr},
			}
			return writer(cast)
		}
		return conversion(
			reader,
			convertingWriter,
			generationContext)
	}
}
func assignPrimitiveTypeFromPrimitiveType(
	sourceEndpoint *StorageConversionEndpoint,
	destinationEndpoint *StorageConversionEndpoint,
	_ *StorageConversionContext) StorageTypeConversion {
	if _, sourceIsOptional := AsOptionalType(sourceEndpoint.Type()); sourceIsOptional {
		return nil
	}
	if _, destinationIsOptional := AsOptionalType(destinationEndpoint.Type()); destinationIsOptional {
		return nil
	}
	sourcePrimitive, sourceIsPrimitive := AsPrimitiveType(sourceEndpoint.Type())
	if !sourceIsPrimitive {
		return nil
	}
	destinationPrimitive, destinationIsPrimitive := AsPrimitiveType(destinationEndpoint.Type())
	if !destinationIsPrimitive {
		return nil
	}
	if !sourcePrimitive.Equals(destinationPrimitive) {
		return nil
	}
	return func(reader dst.Expr, writer func(dst.Expr) []dst.Stmt, generationContext *CodeGenerationContext) []dst.Stmt {
		return writer(reader)
	}
}
func assignAliasedPrimitiveTypeFromAliasedPrimitiveType(
	sourceEndpoint *StorageConversionEndpoint,
	destinationEndpoint *StorageConversionEndpoint,
	conversionContext *StorageConversionContext) StorageTypeConversion {
	if _, sourceIsOptional := AsOptionalType(sourceEndpoint.Type()); sourceIsOptional {
		return nil
	}
	if _, destinationIsOptional := AsOptionalType(destinationEndpoint.Type()); destinationIsOptional {
		return nil
	}
	_, sourceType, ok := conversionContext.ResolveType(sourceEndpoint.Type())
	if !ok {
		return nil
	}
	sourcePrimitive, sourceIsPrimitive := AsPrimitiveType(sourceType)
	if !sourceIsPrimitive {
		return nil
	}
	destinationName, destinationType, ok := conversionContext.ResolveType(destinationEndpoint.Type())
	if !ok {
		return nil
	}
	destinationPrimitive, destinationIsPrimitive := AsPrimitiveType(destinationType)
	if !destinationIsPrimitive {
		return nil
	}
	if !sourcePrimitive.Equals(destinationPrimitive) {
		return nil
	}
	return func(reader dst.Expr, writer func(dst.Expr) []dst.Stmt, generationContext *CodeGenerationContext) []dst.Stmt {
		return writer(&dst.CallExpr{
			Fun:  destinationName.AsType(generationContext),
			Args: []dst.Expr{reader},
		})
	}
}