private String toVariableSerializationExpression(TypeDefinition baseType, Field field, VariableLiteral variableLiteral, List<Argument> serializerArguments) {
        Tracer tracer = Tracer.start("toVariableSerializationExpression");
        if ("STATIC_CALL".equals(variableLiteral.getName())) {
            return toStaticCallSerializationExpression(baseType, field, serializerArguments, variableLiteral, tracer);
        }
        // All uppercase names are not fields, but utility methods.
        if (variableLiteral.getName().equals(variableLiteral.getName().toUpperCase())) {
            return toUppercaseSerializationExpression(baseType, field, serializerArguments, variableLiteral, tracer);
        }
        // If we are accessing implicit fields, we need to rely on that referenced field's expression instead.
        if (isVariableLiteralImplicitField(field, variableLiteral)) {
            tracer = tracer.dive("is variable implicit field");
            final ComplexTypeDefinition referencedImplicitFieldsParent = getReferencedImplicitFieldsParent(field, variableLiteral);
            final ImplicitField referencedImplicitField = getReferencedImplicitField(field, variableLiteral);
            return tracer + toSerializationExpression(referencedImplicitFieldsParent, referencedImplicitField, referencedImplicitField.getSerializeExpression(), serializerArguments);
        }
        // The synthetic checksumRawData is a local field and should not be accessed as bean property.
        boolean isSerializerArg = "checksumRawData".equals(variableLiteral.getName()) || "_value".equals(variableLiteral.getName()) || "element".equals(variableLiteral.getName()) || "size".equals(variableLiteral.getName());
        boolean isTypeArg = "_type".equals(variableLiteral.getName());
        if (!isSerializerArg && !isTypeArg && serializerArguments != null) {
            for (Argument serializerArgument : serializerArguments) {
                if (serializerArgument.getName().equals(variableLiteral.getName())) {
                    isSerializerArg = true;
                    break;
                }
            }
        }
        if (isSerializerArg) {
            tracer = tracer.dive("is serializer arg");
            StringBuilder sb = new StringBuilder(variableLiteral.getName());
            if (variableLiteral.getChild().isPresent()) {
                sb.append(".");
                appendVariableExpressionRest(sb, baseType, variableLiteral.getChild().get());
            }
            return tracer + sb.toString();
        }
        if (isTypeArg) {
            tracer = tracer.dive("is type arg");
            String part = variableLiteral.getChild().get().getName();
            switch (part) {
                case "name":
                    tracer = tracer.dive("name");
                    return tracer + "\"" + field.getTypeName() + "\"";
                case "length":
                    tracer = tracer.dive("length");
                    return tracer + "\"" + ((SimpleTypeReference) field).getSizeInBits() + "\"";
                case "encoding":
                    tracer = tracer.dive("encoding");
                    if (!(field instanceof TypedField)) {
                        throw new FreemarkerException("'encoding' only supported for typed fields.");
                    }
                    TypedField typedField = (TypedField) field;
                    if (!(typedField.getType() instanceof StringTypeReference)) {
                        throw new FreemarkerException("Can only access 'encoding' for string types.");
                    }
                    final Term encodingTerm = field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"));
                    if (!(encodingTerm instanceof StringLiteral)) {
                        throw new FreemarkerException("Encoding must be a quoted string value");
                    }
                    String encoding = ((StringLiteral) encodingTerm).getValue();
                    return tracer + "\"" + encoding + "\"";
                default:
                    return tracer + "";
            }
        }
        // If it wasn't an enum, treat it as a normal property.
        if (variableLiteral.getName().equals("lengthInBits")) {
            tracer = tracer.dive("is length in bits");
            return tracer + getCTypeName(baseType.getName()) + "_length_in_bits(ctx, _message)";
        }
        if (variableLiteral.getChild().isPresent() && "length".equals(variableLiteral.getChild().get().getName())) {
            tracer = tracer.dive("is length");
            return tracer + "sizeof(_message->" + camelCaseToSnakeCase(variableLiteral.getName()) + ")";
        }
        StringBuilder sb = new StringBuilder("_message->");
        // If this is a property of a sub-type, add the sub-type name to the property.
        if (baseType != thisType) {
            tracer = tracer.dive("this is not this type");
            sb.append(camelCaseToSnakeCase(baseType.getName())).append("_");
        }

        // If this expression references enum constants we need to do things differently
        final Optional<TypeReference> typeReferenceForProperty =
            ((ComplexTypeDefinition) baseType).getTypeReferenceForProperty(variableLiteral.getName());
        if (typeReferenceForProperty.isPresent()) {
            final TypeReference typeReference = typeReferenceForProperty.get();
            if (typeReference instanceof NonSimpleTypeReference) {
                final TypeDefinition typeDefinitionForTypeReference = typeReference.asNonSimpleTypeReference().orElseThrow().getTypeDefinition();
                if ((typeDefinitionForTypeReference instanceof EnumTypeDefinition) && (variableLiteral.getChild().isPresent())) {
                    tracer = tracer.dive("is enum type definition");
                    sb.append(camelCaseToSnakeCase(variableLiteral.getName()));
                    return tracer + getCTypeName(typeDefinitionForTypeReference.getName()) + "_get_" + camelCaseToSnakeCase(variableLiteral.getChild().get().getName()) +
                        "(" + sb + ")";
                }
            }
        }
        // If it wasn't an enum, treat it as a normal property.
        appendVariableExpressionRest(sb, baseType, variableLiteral);
        return tracer + sb.toString();
    }
Ge the type-size suffix in case of simple types.

@param field the field we want to get the type-size for
@return a type-size string for the given field or an empty string if this does not apply
code-generation/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageTemplateHelper.java