//
// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "Serializer.hpp"
#include "SerializerUtils.hpp"

#include <armnn/Descriptors.hpp>
#include <armnn/LstmParams.hpp>
#include <armnn/QuantizedLstmParams.hpp>
#include <armnn/utility/IgnoreUnused.hpp>
#include <armnn/utility/NumericCast.hpp>

#include <fmt/format.h>
#include <iostream>

using namespace armnn;
namespace fb = flatbuffers;
namespace serializer = armnnSerializer;

namespace armnnSerializer
{

ISerializer::ISerializer() : pSerializerImpl(new SerializerImpl())
{
}

ISerializer::~ISerializer() = default;

ISerializer* ISerializer::CreateRaw()
{
    return new ISerializer();
}

ISerializerPtr ISerializer::Create()
{
    return ISerializerPtr(CreateRaw(), &ISerializer::Destroy);
}

void ISerializer::Destroy(ISerializer* serializer)
{
    delete serializer;
}

void ISerializer::Serialize(const armnn::INetwork& inNetwork)
{
    pSerializerImpl->Serialize(inNetwork);
}

bool ISerializer::SaveSerializedToStream(std::ostream& stream)
{
    return pSerializerImpl->SaveSerializedToStream(stream);
}

serializer::ActivationFunction GetFlatBufferActivationFunction(armnn::ActivationFunction function)
{
    switch (function)
    {
        case armnn::ActivationFunction::Sigmoid:
            return serializer::ActivationFunction::ActivationFunction_Sigmoid;
        case armnn::ActivationFunction::TanH:
            return serializer::ActivationFunction::ActivationFunction_TanH;
        case armnn::ActivationFunction::Linear:
            return serializer::ActivationFunction::ActivationFunction_Linear;
        case armnn::ActivationFunction::ReLu:
            return serializer::ActivationFunction::ActivationFunction_ReLu;
        case armnn::ActivationFunction::BoundedReLu:
            return serializer::ActivationFunction::ActivationFunction_BoundedReLu;
        case armnn::ActivationFunction::LeakyReLu:
            return serializer::ActivationFunction::ActivationFunction_LeakyReLu;
        case armnn::ActivationFunction::Abs:
            return serializer::ActivationFunction::ActivationFunction_Abs;
        case armnn::ActivationFunction::Sqrt:
            return serializer::ActivationFunction::ActivationFunction_Sqrt;
        case armnn::ActivationFunction::Square:
            return serializer::ActivationFunction::ActivationFunction_Square;
        case armnn::ActivationFunction::Elu:
            return serializer::ActivationFunction::ActivationFunction_Elu;
        case armnn::ActivationFunction::HardSwish:
            return serializer::ActivationFunction::ActivationFunction_HardSwish;
        default:
            return serializer::ActivationFunction::ActivationFunction_Sigmoid;
    }
}

serializer::ArgMinMaxFunction GetFlatBufferArgMinMaxFunction(armnn::ArgMinMaxFunction function)
{
    switch (function)
    {
        case armnn::ArgMinMaxFunction::Max:
            return serializer::ArgMinMaxFunction::ArgMinMaxFunction_Max;
        case armnn::ArgMinMaxFunction::Min:
        default:
            return serializer::ArgMinMaxFunction::ArgMinMaxFunction_Min;
    }
}

uint32_t SerializerStrategy::GetSerializedId(armnn::LayerGuid guid)
{
    if (m_guidMap.empty())
    {
        m_guidMap.insert(std::make_pair(guid, m_layerId));
    }
    else if (m_guidMap.find(guid) == m_guidMap.end())
    {
        ++m_layerId;
        m_guidMap.insert(std::make_pair(guid, m_layerId));

        return m_layerId;
    }
    return m_guidMap[guid];
}

// Build FlatBuffer for Input Layer
void SerializerStrategy::SerializeInputLayer(const armnn::IConnectableLayer* layer, LayerBindingId id, const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferInputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Input);

    // Create FlatBuffer BindableBaseLayer
    auto flatBufferInputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
                                                                                flatBufferInputBaseLayer,
                                                                                id);
    // Push layer binding id to outputIds.
    m_inputIds.push_back(id);

    // Create the FlatBuffer InputLayer
    auto flatBufferInputLayer = serializer::CreateInputLayer(m_flatBufferBuilder, flatBufferInputBindableBaseLayer);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferInputLayer.o, serializer::Layer::Layer_InputLayer);
}

// Build FlatBuffer for Output Layer
void SerializerStrategy::SerializeOutputLayer(const armnn::IConnectableLayer* layer,
                                              LayerBindingId id, const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferOutputBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Output);

    // Create FlatBuffer BindableBaseLayer
    auto flatBufferOutputBindableBaseLayer = serializer::CreateBindableLayerBase(m_flatBufferBuilder,
                                                                                 flatBufferOutputBaseLayer,
                                                                                 id);
    // Push layer binding id to outputIds.
    m_outputIds.push_back(id);

    // Create the FlatBuffer OutputLayer
    auto flatBufferOutputLayer = serializer::CreateOutputLayer(m_flatBufferBuilder, flatBufferOutputBindableBaseLayer);
    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferOutputLayer.o, serializer::Layer::Layer_OutputLayer);
}

// Build FlatBuffer for Activation Layer
void SerializerStrategy::SerializeActivationLayer(const armnn::IConnectableLayer* layer,
                                                  const armnn::ActivationDescriptor& descriptor,
                                                  const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Activation);

    // Create the FlatBuffer ActivationDescriptor
    auto flatBufferDescriptor = CreateActivationDescriptor(m_flatBufferBuilder,
                                                           GetFlatBufferActivationFunction(descriptor.m_Function),
                                                           descriptor.m_A,
                                                           descriptor.m_B);

    // Create the FlatBuffer ActivationLayer
    auto flatBufferAdditionLayer = CreateActivationLayer(m_flatBufferBuilder,
                                                         flatBufferBaseLayer,
                                                         flatBufferDescriptor);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferAdditionLayer.o, serializer::Layer::Layer_ActivationLayer);
}

// Build FlatBuffer for Addition Layer
void SerializerStrategy::SerializeAdditionLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferAdditionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Addition);

    // Create the FlatBuffer AdditionLayer
    auto flatBufferAdditionLayer = serializer::CreateAdditionLayer(m_flatBufferBuilder, flatBufferAdditionBaseLayer);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferAdditionLayer.o, serializer::Layer::Layer_AdditionLayer);
}

// Build FlatBuffer for ArgMinMax Layer
void SerializerStrategy::SerializeArgMinMaxLayer(const armnn::IConnectableLayer *layer,
                                                 const armnn::ArgMinMaxDescriptor& descriptor,
                                                 const char *name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_ArgMinMax);

    // Create FlatBuffer Descriptor
    auto flatBufferDescriptor = CreateArgMinMaxDescriptor(m_flatBufferBuilder,
                                                          GetFlatBufferArgMinMaxFunction(descriptor.m_Function),
                                                          descriptor.m_Axis);

    // Create FlatBuffer ArgMinMaxLayer
    auto flatBufferLayer = CreateArgMinMaxLayer(m_flatBufferBuilder,
                                                flatBufferBaseLayer,
                                                flatBufferDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_ArgMinMaxLayer);
}

// Build FlatBuffer for BatchToSpaceNd Layer
void SerializerStrategy::SerializeBatchToSpaceNdLayer(const armnn::IConnectableLayer* layer,
                                                      const armnn::BatchToSpaceNdDescriptor& descriptor,
                                                      const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_BatchToSpaceNd);

    std::vector<unsigned int> crops;
    crops.reserve(descriptor.m_Crops.size() * 2);
    for (auto& crop : descriptor.m_Crops)
    {
        crops.push_back(crop.first);
        crops.push_back(crop.second);
    }

    auto flatBufferDescriptor =
        CreateBatchToSpaceNdDescriptor(m_flatBufferBuilder,
                                       m_flatBufferBuilder.CreateVector(descriptor.m_BlockShape),
                                       m_flatBufferBuilder.CreateVector(crops),
                                       GetFlatBufferDataLayout(descriptor.m_DataLayout));

    auto flatBufferLayer = serializer::CreateBatchToSpaceNdLayer(m_flatBufferBuilder,
                                                                 flatBufferBaseLayer,
                                                                 flatBufferDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_BatchToSpaceNdLayer);
}

void SerializerStrategy::SerializeBatchNormalizationLayer(
        const armnn::IConnectableLayer* layer,
        const armnn::BatchNormalizationDescriptor& batchNormDescriptor,
        const std::vector<armnn::ConstTensor>& constants,
        const char* name)
{
    IgnoreUnused(name);

    const armnn::ConstTensor& mean     = constants[0];
    const armnn::ConstTensor& variance = constants[1];
    const armnn::ConstTensor& beta     = constants[2];
    const armnn::ConstTensor& gamma    = constants[3];

    auto fbBatchNormalizationBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_BatchNormalization);
    auto fbBatchNormalizationDescriptor = serializer::CreateBatchNormalizationDescriptor(
                                                  m_flatBufferBuilder,
                                                  batchNormDescriptor.m_Eps,
                                                  GetFlatBufferDataLayout(batchNormDescriptor.m_DataLayout));

    auto fbMeanConstTensorInfo     = CreateConstTensorInfo(mean);
    auto fbVarianceConstTensorInfo = CreateConstTensorInfo(variance);
    auto fbBetaConstTensorInfo     = CreateConstTensorInfo(beta);
    auto fbGammaConstTensorInfo    = CreateConstTensorInfo(gamma);
    auto fbBatchNormalizationLayer = serializer::CreateBatchNormalizationLayer(m_flatBufferBuilder,
                                                                               fbBatchNormalizationBaseLayer,
                                                                               fbBatchNormalizationDescriptor,
                                                                               fbMeanConstTensorInfo,
                                                                               fbVarianceConstTensorInfo,
                                                                               fbBetaConstTensorInfo,
                                                                               fbGammaConstTensorInfo);

    CreateAnyLayer(fbBatchNormalizationLayer.o, serializer::Layer::Layer_BatchNormalizationLayer);
}

void SerializerStrategy::SerializeCastLayer(const armnn::IConnectableLayer* layer,
                                            const char* name)
{
    IgnoreUnused(name);

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Cast);
    auto fbCastLayer = serializer::CreateCastLayer(m_flatBufferBuilder, fbBaseLayer);
    CreateAnyLayer(fbCastLayer.o, serializer::Layer::Layer_CastLayer);
}

void SerializerStrategy::SerializeChannelShuffleLayer(const armnn::IConnectableLayer* layer,
                                                      const armnn::ChannelShuffleDescriptor& descriptor,
                                                      const char* name)
{
    IgnoreUnused(name);
    auto fbDescriptor = CreateChannelShuffleDescriptor(m_flatBufferBuilder,
                                                       descriptor.m_Axis,
                                                       descriptor.m_NumGroups);
    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_ChannelShuffle);
    auto fbChannelShuffleLayer = serializer::CreateChannelShuffleLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);
    CreateAnyLayer(fbChannelShuffleLayer.o, serializer::Layer::Layer_ChannelShuffleLayer);
}

void SerializerStrategy::SerializeComparisonLayer(const armnn::IConnectableLayer* layer,
                                             const armnn::ComparisonDescriptor& descriptor,
                                             const char* name)
{
    IgnoreUnused(name);

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Comparison);
    auto fbDescriptor = serializer::CreateComparisonDescriptor(
        m_flatBufferBuilder,
        GetFlatBufferComparisonOperation(descriptor.m_Operation));

    auto fbLayer = serializer::CreateComparisonLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);
    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_ComparisonLayer);
}

// Build FlatBuffer for Constant Layer
void SerializerStrategy::SerializeConstantLayer(const armnn::IConnectableLayer* layer,
                                                const std::vector<armnn::ConstTensor>& constants,
                                                const char* name)
{
    IgnoreUnused(name);

    armnn::ConstTensor input = constants[0];

    // Create FlatBuffer BaseLayer
    auto flatBufferConstantBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Constant);

    auto flatBufferConstTensorInfo = CreateConstTensorInfo(input);

    // Create the FlatBuffer ConstantLayer
    auto flatBufferLayer = CreateConstantLayer(m_flatBufferBuilder,
                                               flatBufferConstantBaseLayer,
                                               flatBufferConstTensorInfo);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_ConstantLayer);
}

// Build FlatBuffer for Convolution2dLayer
void SerializerStrategy::SerializeConvolution2dLayer(const armnn::IConnectableLayer* layer,
                                                     const armnn::Convolution2dDescriptor& descriptor,
                                                     const std::vector<armnn::ConstTensor>& constants,
                                                     const char* name)
{
    IgnoreUnused(name);

    const armnn::ConstTensor weights = constants[0];

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Convolution2d);

    auto flatBufferDescriptor = CreateConvolution2dDescriptor(m_flatBufferBuilder,
                                                              descriptor.m_PadLeft,
                                                              descriptor.m_PadRight,
                                                              descriptor.m_PadTop,
                                                              descriptor.m_PadBottom,
                                                              descriptor.m_StrideX,
                                                              descriptor.m_StrideY,
                                                              descriptor.m_DilationX,
                                                              descriptor.m_DilationY,
                                                              descriptor.m_BiasEnabled,
                                                              GetFlatBufferDataLayout(descriptor.m_DataLayout));
    auto flatBufferWeightsConstTensorInfo = CreateConstTensorInfo(weights);
    flatbuffers::Offset<serializer::ConstTensor> flatBufferBiasesConstTensorInfo;

    if (constants.size() > 1)
    {
        const armnn::ConstTensor biases = constants[1];
        flatBufferBiasesConstTensorInfo = CreateConstTensorInfo(biases);
    }

    // Create the FlatBuffer Convolution2dLayer
    auto flatBufferLayer = CreateConvolution2dLayer(m_flatBufferBuilder,
                                                    flatBufferBaseLayer,
                                                    flatBufferDescriptor,
                                                    flatBufferWeightsConstTensorInfo,
                                                    flatBufferBiasesConstTensorInfo);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution2dLayer);
}

// Build FlatBuffer for Convolution3dLayer
void SerializerStrategy::SerializeConvolution3dLayer(const armnn::IConnectableLayer* layer,
                                                     const armnn::Convolution3dDescriptor& descriptor,
                                                     const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Convolution3d);

    auto flatBufferDescriptor = CreateConvolution3dDescriptor(m_flatBufferBuilder,
                                                              descriptor.m_PadLeft,
                                                              descriptor.m_PadRight,
                                                              descriptor.m_PadTop,
                                                              descriptor.m_PadBottom,
                                                              descriptor.m_PadFront,
                                                              descriptor.m_PadBack,
                                                              descriptor.m_StrideX,
                                                              descriptor.m_StrideY,
                                                              descriptor.m_StrideZ,
                                                              descriptor.m_DilationX,
                                                              descriptor.m_DilationY,
                                                              descriptor.m_DilationZ,
                                                              descriptor.m_BiasEnabled,
                                                              GetFlatBufferDataLayout(descriptor.m_DataLayout));

    // Create the FlatBuffer Convolution3dLayer
    auto flatBufferLayer = CreateConvolution3dLayer(m_flatBufferBuilder,
                                                    flatBufferBaseLayer,
                                                    flatBufferDescriptor);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution3dLayer);
}

void SerializerStrategy::SerializeDepthToSpaceLayer(const armnn::IConnectableLayer* layer,
                                               const armnn::DepthToSpaceDescriptor& descriptor,
                                               const char* name)
{
    IgnoreUnused(name);

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_DepthToSpace);
    auto fbDescriptor = CreateDepthToSpaceDescriptor(m_flatBufferBuilder,
                                                     descriptor.m_BlockSize,
                                                     GetFlatBufferDataLayout(descriptor.m_DataLayout));

    auto fbLayer = serializer::CreateDepthToSpaceLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);

    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_DepthToSpaceLayer);
}

void SerializerStrategy::SerializeDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
                                                              const armnn::DepthwiseConvolution2dDescriptor& descriptor,
                                                              const std::vector<armnn::ConstTensor>& constants,
                                                              const char* name)
{
    IgnoreUnused(name);

    const armnn::ConstTensor& weights = constants[0];

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_DepthwiseConvolution2d);
    auto fbDescriptor = CreateDepthwiseConvolution2dDescriptor(m_flatBufferBuilder,
                                                               descriptor.m_PadLeft,
                                                               descriptor.m_PadRight,
                                                               descriptor.m_PadTop,
                                                               descriptor.m_PadBottom,
                                                               descriptor.m_StrideX,
                                                               descriptor.m_StrideY,
                                                               descriptor.m_DilationX,
                                                               descriptor.m_DilationY,
                                                               descriptor.m_BiasEnabled,
                                                               GetFlatBufferDataLayout(descriptor.m_DataLayout));

    flatbuffers::Offset<serializer::ConstTensor> fbWeightsConstTensorInfo = CreateConstTensorInfo(weights);
    flatbuffers::Offset<serializer::ConstTensor> fbBiasesConstTensorInfo;

    if (constants.size() > 1)
    {
        const armnn::ConstTensor& biases = constants[1];
        fbBiasesConstTensorInfo = CreateConstTensorInfo(biases);
    }

    auto flatBufferLayer = CreateDepthwiseConvolution2dLayer(m_flatBufferBuilder,
                                                             fbBaseLayer,
                                                             fbDescriptor,
                                                             fbWeightsConstTensorInfo,
                                                             fbBiasesConstTensorInfo);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_DepthwiseConvolution2dLayer);
}

void SerializerStrategy::SerializeDequantizeLayer(const armnn::IConnectableLayer* layer,
                                             const char* name)
{
    IgnoreUnused(name);

    auto fbDequantizeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Dequantize);
    auto fbDequantizeLayer     = serializer::CreateDequantizeLayer(m_flatBufferBuilder, fbDequantizeBaseLayer);

    CreateAnyLayer(fbDequantizeLayer.o, serializer::Layer::Layer_DequantizeLayer);
}

void SerializerStrategy::SerializeDetectionPostProcessLayer(const armnn::IConnectableLayer* layer,
                                                            const armnn::DetectionPostProcessDescriptor& descriptor,
                                                            const std::vector<armnn::ConstTensor>& constants,
                                                            const char* name)
{
    IgnoreUnused(name);

    const armnn::ConstTensor& anchors = constants[0];

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_DetectionPostProcess);
    auto fbDescriptor = CreateDetectionPostProcessDescriptor(m_flatBufferBuilder,
                                                             descriptor.m_MaxDetections,
                                                             descriptor.m_MaxClassesPerDetection,
                                                             descriptor.m_DetectionsPerClass,
                                                             descriptor.m_NmsScoreThreshold,
                                                             descriptor.m_NmsIouThreshold,
                                                             descriptor.m_NumClasses,
                                                             descriptor.m_UseRegularNms,
                                                             descriptor.m_ScaleX,
                                                             descriptor.m_ScaleY,
                                                             descriptor.m_ScaleW,
                                                             descriptor.m_ScaleH);

    flatbuffers::Offset<serializer::ConstTensor> fbAnchorsConstTensorInfo = CreateConstTensorInfo(anchors);

    auto flatBufferLayer = CreateDetectionPostProcessLayer(m_flatBufferBuilder,
                                                           fbBaseLayer,
                                                           fbDescriptor,
                                                           fbAnchorsConstTensorInfo);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_DetectionPostProcessLayer);
}

void SerializerStrategy::SerializeDivisionLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    auto fbDivisionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Division);
    auto fbDivisionLayer     = serializer::CreateDivisionLayer(m_flatBufferBuilder, fbDivisionBaseLayer);

    CreateAnyLayer(fbDivisionLayer.o, serializer::Layer::Layer_DivisionLayer);
}

void SerializerStrategy::SerializeElementwiseUnaryLayer(const armnn::IConnectableLayer* layer,
                                                   const armnn::ElementwiseUnaryDescriptor& descriptor,
                                                   const char* name)
{
    IgnoreUnused(name);

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_ElementwiseUnary);
    auto fbDescriptor = serializer::CreateElementwiseUnaryDescriptor(
        m_flatBufferBuilder,
        GetFlatBufferUnaryOperation(descriptor.m_Operation));

    auto fbLayer = serializer::CreateElementwiseUnaryLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);
    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_ElementwiseUnaryLayer);
}

void SerializerStrategy::SerializeFillLayer(const armnn::IConnectableLayer* layer,
                                       const armnn::FillDescriptor& fillDescriptor,
                                       const char* name)
{
    IgnoreUnused(name);

    auto fbFillBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Fill);

    auto fbDescriptor = serializer::CreateFillDescriptor(m_flatBufferBuilder, fillDescriptor.m_Value);

    auto fbFillLayer = serializer::CreateFillLayer(m_flatBufferBuilder, fbFillBaseLayer, fbDescriptor);

    CreateAnyLayer(fbFillLayer.o, serializer::Layer::Layer_FillLayer);
}

void SerializerStrategy::SerializeFloorLayer(const armnn::IConnectableLayer *layer, const char *name)
{
    IgnoreUnused(name);

    auto flatBufferFloorBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Floor);
    auto flatBufferFloorLayer = serializer::CreateFloorLayer(m_flatBufferBuilder, flatBufferFloorBaseLayer);

    CreateAnyLayer(flatBufferFloorLayer.o, serializer::Layer::Layer_FloorLayer);
}

void SerializerStrategy::SerializeGatherLayer(const armnn::IConnectableLayer* layer,
                                         const armnn::GatherDescriptor& gatherDescriptor,
                                         const char* name)
{
    IgnoreUnused(name);

    auto fbGatherDescriptor = CreateGatherDescriptor(m_flatBufferBuilder,
                                                     gatherDescriptor.m_Axis);
    auto fbGatherBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Gather);
    auto flatBufferLayer   = serializer::CreateGatherLayer(m_flatBufferBuilder, fbGatherBaseLayer, fbGatherDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_GatherLayer);
}

void SerializerStrategy::SerializeInstanceNormalizationLayer(
    const armnn::IConnectableLayer* layer,
    const armnn::InstanceNormalizationDescriptor& instanceNormalizationDescriptor,
    const char* name)
{
    IgnoreUnused(name);

    auto fbDescriptor = serializer::CreateInstanceNormalizationDescriptor(
            m_flatBufferBuilder,
            instanceNormalizationDescriptor.m_Gamma,
            instanceNormalizationDescriptor.m_Beta,
            instanceNormalizationDescriptor.m_Eps,
            GetFlatBufferDataLayout(instanceNormalizationDescriptor.m_DataLayout));

    auto fbBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_InstanceNormalization);
    auto fbLayer     = serializer::CreateInstanceNormalizationLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);

    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_InstanceNormalizationLayer);
}

void SerializerStrategy::SerializeL2NormalizationLayer(const armnn::IConnectableLayer* layer,
                                                  const armnn::L2NormalizationDescriptor& l2NormalizationDescriptor,
                                                  const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto fbBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_L2Normalization);

    // Create the FlatBuffer L2Normalization Descriptor
    auto fbDescriptor = serializer::CreateL2NormalizationDescriptor(
            m_flatBufferBuilder,
            GetFlatBufferDataLayout(l2NormalizationDescriptor.m_DataLayout),
            l2NormalizationDescriptor.m_Eps);

    // Create FlatBuffer layer
    auto fbLayer = serializer::CreateL2NormalizationLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);

    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_L2NormalizationLayer);
}

void SerializerStrategy::SerializeLogicalBinaryLayer(const armnn::IConnectableLayer* layer,
                                                const armnn::LogicalBinaryDescriptor& descriptor,
                                                const char* name)
{
    IgnoreUnused(name);

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_LogicalBinary);
    auto fbDescriptor = serializer::CreateLogicalBinaryDescriptor(
        m_flatBufferBuilder,
        GetFlatBufferLogicalBinaryOperation(descriptor.m_Operation));

    auto fbLayer = serializer::CreateLogicalBinaryLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);
    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_LogicalBinaryLayer);
}

void SerializerStrategy::SerializeLogSoftmaxLayer(const armnn::IConnectableLayer* layer,
                                             const armnn::LogSoftmaxDescriptor& logSoftmaxDescriptor,
                                             const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferLogSoftmaxBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_LogSoftmax);

    // Create the FlatBuffer LogSoftmaxDescriptor
    auto flatBufferLogSoftmaxDesc =
        serializer::CreateLogSoftmaxDescriptor(m_flatBufferBuilder,
                                               logSoftmaxDescriptor.m_Beta,
                                               logSoftmaxDescriptor.m_Axis);

    // Create the FlatBuffer LogSoftmaxLayer
    auto flatBufferLogSoftmaxLayer =
        serializer::CreateLogSoftmaxLayer(m_flatBufferBuilder,
                                          flatBufferLogSoftmaxBaseLayer,
                                          flatBufferLogSoftmaxDesc);

    CreateAnyLayer(flatBufferLogSoftmaxLayer.o, serializer::Layer::Layer_LogSoftmaxLayer);
}

void SerializerStrategy::SerializeLstmLayer(const armnn::IConnectableLayer* layer,
                                            const armnn::LstmDescriptor& descriptor,
                                            const std::vector<armnn::ConstTensor>& constants,
                                            const char* name)
{
    IgnoreUnused(name);

    auto fbLstmBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Lstm);

    auto fbLstmDescriptor = serializer::CreateLstmDescriptor(
        m_flatBufferBuilder,
        descriptor.m_ActivationFunc,
        descriptor.m_ClippingThresCell,
        descriptor.m_ClippingThresProj,
        descriptor.m_CifgEnabled,
        descriptor.m_PeepholeEnabled,
        descriptor.m_ProjectionEnabled,
        descriptor.m_LayerNormEnabled);

    // Index for constants vector
    std::size_t i = 0;

    // Get mandatory/basic input parameters
    auto inputToForgetWeights     = CreateConstTensorInfo(constants[i++]); //InputToForgetWeights
    auto inputToCellWeights       = CreateConstTensorInfo(constants[i++]); //InputToCellWeights
    auto inputToOutputWeights     = CreateConstTensorInfo(constants[i++]); //InputToOutputWeights
    auto recurrentToForgetWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToForgetWeights
    auto recurrentToCellWeights   = CreateConstTensorInfo(constants[i++]); //RecurrentToCellWeights
    auto recurrentToOutputWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToOutputWeights
    auto forgetGateBias           = CreateConstTensorInfo(constants[i++]); //ForgetGateBias
    auto cellBias                 = CreateConstTensorInfo(constants[i++]); //CellBias
    auto outputGateBias           = CreateConstTensorInfo(constants[i++]); //OutputGateBias



    //Define optional parameters, these will be set depending on configuration in Lstm descriptor
    flatbuffers::Offset<serializer::ConstTensor> inputToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> recurrentToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> inputGateBias;
    flatbuffers::Offset<serializer::ConstTensor> projectionWeights;
    flatbuffers::Offset<serializer::ConstTensor> projectionBias;
    flatbuffers::Offset<serializer::ConstTensor> cellToForgetWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellToOutputWeights;
    flatbuffers::Offset<serializer::ConstTensor> inputLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> forgetLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> outputLayerNormWeights;

    if (!descriptor.m_CifgEnabled)
    {
        inputToInputWeights = CreateConstTensorInfo(constants[i++]); //InputToInputWeights
        recurrentToInputWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToInputWeights
        inputGateBias = CreateConstTensorInfo(constants[i++]); //InputGateBias
    }

    if (descriptor.m_PeepholeEnabled)
    {
        if (!descriptor.m_CifgEnabled)
        {
            cellToInputWeights = CreateConstTensorInfo(constants[i++]); //CellToInputWeights
        }
        cellToForgetWeights = CreateConstTensorInfo(constants[i++]); //CellToForgetWeights
        cellToOutputWeights = CreateConstTensorInfo(constants[i++]); //CellToOutputWeights
    }

    if (descriptor.m_ProjectionEnabled)
    {
        projectionWeights = CreateConstTensorInfo(constants[i++]); //ProjectionWeights
        projectionBias = CreateConstTensorInfo(constants[i++]); //ProjectionBias
    }

    if (descriptor.m_LayerNormEnabled)
    {
        if (!descriptor.m_CifgEnabled)
        {
            inputLayerNormWeights = CreateConstTensorInfo(constants[i++]); //InputLayerNormWeights
        }
        forgetLayerNormWeights = CreateConstTensorInfo(constants[i++]); //ForgetLayerNormWeights
        cellLayerNormWeights   = CreateConstTensorInfo(constants[i++]); //CellLayerNormWeights
        outputLayerNormWeights = CreateConstTensorInfo(constants[i++]); //OutputLayerNormWeights
    }

    auto fbLstmParams = serializer::CreateLstmInputParams(
        m_flatBufferBuilder,
        inputToForgetWeights,
        inputToCellWeights,
        inputToOutputWeights,
        recurrentToForgetWeights,
        recurrentToCellWeights,
        recurrentToOutputWeights,
        forgetGateBias,
        cellBias,
        outputGateBias,
        inputToInputWeights,
        recurrentToInputWeights,
        cellToInputWeights,
        inputGateBias,
        projectionWeights,
        projectionBias,
        cellToForgetWeights,
        cellToOutputWeights,
        inputLayerNormWeights,
        forgetLayerNormWeights,
        cellLayerNormWeights,
        outputLayerNormWeights);

    auto fbLstmLayer = serializer::CreateLstmLayer(
        m_flatBufferBuilder,
        fbLstmBaseLayer,
        fbLstmDescriptor,
        fbLstmParams);

    CreateAnyLayer(fbLstmLayer.o, serializer::Layer::Layer_LstmLayer);
}

void SerializerStrategy::SerializeMaximumLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    auto fbMaximumBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Maximum);
    auto fbMaximumLayer     = serializer::CreateMaximumLayer(m_flatBufferBuilder, fbMaximumBaseLayer);

    CreateAnyLayer(fbMaximumLayer.o, serializer::Layer::Layer_MaximumLayer);
}

void SerializerStrategy::SerializeMeanLayer(const armnn::IConnectableLayer* layer,
                                       const armnn::MeanDescriptor& descriptor,
                                       const char* name)
{
    IgnoreUnused(name);

    auto fbMeanBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Mean);
    auto fbMeanDescriptor = serializer::CreateMeanDescriptor(m_flatBufferBuilder,
                                                             m_flatBufferBuilder.CreateVector(descriptor.m_Axis),
                                                             descriptor.m_KeepDims);

    auto fbMeanLayer = serializer::CreateMeanLayer(m_flatBufferBuilder,
                                                   fbMeanBaseLayer,
                                                   fbMeanDescriptor);

    CreateAnyLayer(fbMeanLayer.o, serializer::Layer::Layer_MeanLayer);
}

void SerializerStrategy::SerializeMinimumLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    auto fbMinimumBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Minimum);
    auto fbMinimumLayer     = serializer::CreateMinimumLayer(m_flatBufferBuilder, fbMinimumBaseLayer);

    CreateAnyLayer(fbMinimumLayer.o, serializer::Layer::Layer_MinimumLayer);
}

void SerializerStrategy::SerializeMergeLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    auto fbMergeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Merge);
    auto fbMergeLayer     = serializer::CreateMergeLayer(m_flatBufferBuilder, fbMergeBaseLayer);

    CreateAnyLayer(fbMergeLayer.o, serializer::Layer::Layer_MergeLayer);
}

void SerializerStrategy::SerializeConcatLayer(const armnn::IConnectableLayer* layer,
                                         const armnn::ConcatDescriptor& concatDescriptor,
                                         const char* name)
{
    IgnoreUnused(name);

    auto flatBufferConcatBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Concat);

    std::vector<flatbuffers::Offset<UintVector>> views;
    for (unsigned int v = 0; v < concatDescriptor.GetNumViews(); ++v)
    {
        const uint32_t* origin = concatDescriptor.GetViewOrigin(v);
        std::vector<uint32_t> origins;
        for (unsigned int d = 0; d < concatDescriptor.GetNumDimensions(); ++d)
        {
            origins.push_back(origin[d]);
        }
        auto view = m_flatBufferBuilder.CreateVector(origins);
        auto uintVector = CreateUintVector(m_flatBufferBuilder, view);
        views.push_back(uintVector);
    }

    auto flatBufferConcatDescriptor = CreateOriginsDescriptor(m_flatBufferBuilder,
                                                              concatDescriptor.GetConcatAxis(),
                                                              concatDescriptor.GetNumViews(),
                                                              concatDescriptor.GetNumDimensions(),
                                                              m_flatBufferBuilder.CreateVector(views));

    auto flatBufferLayer = CreateConcatLayer(m_flatBufferBuilder,
                                             flatBufferConcatBaseLayer,
                                             flatBufferConcatDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_ConcatLayer);
}

void SerializerStrategy::SerializeMultiplicationLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    auto fbMultiplicationBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Multiplication);
    auto fbMultiplicationLayer     = serializer::CreateMultiplicationLayer(m_flatBufferBuilder,
                                                                           fbMultiplicationBaseLayer);

    CreateAnyLayer(fbMultiplicationLayer.o, serializer::Layer::Layer_MultiplicationLayer);
}

void SerializerStrategy::SerializePadLayer(const armnn::IConnectableLayer* layer,
                                      const armnn::PadDescriptor& padDescriptor,
                                      const char* name)
{
    IgnoreUnused(name);

    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Pad);

    std::vector<unsigned int> padList;
    for (auto& p: padDescriptor.m_PadList)
    {
        padList.push_back(p.first);
        padList.push_back(p.second);
    }

    auto flatBufferPadDesc = serializer::CreatePadDescriptor(m_flatBufferBuilder,
                                                             m_flatBufferBuilder.CreateVector(padList),
                                                             padDescriptor.m_PadValue,
                                                             GetFlatBufferPaddingMode(padDescriptor.m_PaddingMode));

    auto flatBufferPadLayer = serializer::CreatePadLayer(m_flatBufferBuilder,
                                                         flatBufferBaseLayer,
                                                         flatBufferPadDesc);

    CreateAnyLayer(flatBufferPadLayer.o, serializer::Layer::Layer_PadLayer);
}

void SerializerStrategy::SerializePermuteLayer(const armnn::IConnectableLayer* layer,
                                          const armnn::PermuteDescriptor& permuteDescriptor,
                                          const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferPermuteBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Permute);

    std::vector<unsigned int> dimMappings;
    for (unsigned int i=0; i<permuteDescriptor.m_DimMappings.GetSize(); ++i)
    {
        dimMappings.push_back(permuteDescriptor.m_DimMappings[i]);
    }

    auto flatBufferPermuteDesc = serializer::CreatePermuteDescriptor(m_flatBufferBuilder,
                                                                     m_flatBufferBuilder.CreateVector(dimMappings));

    // Create the FlatBuffer PermuteLayer
    auto flatBufferPermuteLayer = serializer::CreatePermuteLayer(m_flatBufferBuilder,
                                                                 flatBufferPermuteBaseLayer,
                                                                 flatBufferPermuteDesc);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferPermuteLayer.o, serializer::Layer::Layer_PermuteLayer);
}

// Build FlatBuffer for Rank Layer
void SerializerStrategy::SerializeRankLayer(const armnn::IConnectableLayer* layer,
                                       const char* name)
{
    IgnoreUnused(name);
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Rank);
    auto flatBufferRankLayer = serializer::CreateRankLayer(m_flatBufferBuilder, flatBufferBaseLayer);

    CreateAnyLayer(flatBufferRankLayer.o, serializer::Layer::Layer_RankLayer);
}

void SerializerStrategy::SerializeReduceLayer(const armnn::IConnectableLayer* layer,
                                             const armnn::ReduceDescriptor& reduceDescriptor,
                                             const char*)
{
    auto fbReduceBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Reduce);
    auto fbDescriptor = CreateReduceDescriptor(m_flatBufferBuilder,
                                               reduceDescriptor.m_KeepDims,
                                               m_flatBufferBuilder.CreateVector(reduceDescriptor.m_vAxis),
                                               GetFlatBufferReduceOperation(reduceDescriptor.m_ReduceOperation));
    auto fbReduceLayer = serializer::CreateReduceLayer(m_flatBufferBuilder,
                                                       fbReduceBaseLayer,
                                                       fbDescriptor);

    CreateAnyLayer(fbReduceLayer.o, serializer::Layer::Layer_ReduceLayer);
}

// Build FlatBuffer for Reshape Layer
void SerializerStrategy::SerializeReshapeLayer(const armnn::IConnectableLayer* layer,
                                          const armnn::ReshapeDescriptor& reshapeDescriptor,
                                          const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferReshapeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Reshape);

    std::vector<unsigned int> targetShape;
    for (unsigned int i =0; i < reshapeDescriptor.m_TargetShape.GetNumDimensions(); i++)
    {
        targetShape.push_back(reshapeDescriptor.m_TargetShape[i]);
    }

    auto flatBufferReshapeDesc = serializer::CreateReshapeDescriptor(m_flatBufferBuilder,
                                                                     m_flatBufferBuilder.CreateVector(targetShape));

    // Create the FlatBuffer ReshapeLayer
    auto flatBufferReshapeLayer = serializer::CreateReshapeLayer(m_flatBufferBuilder, flatBufferReshapeBaseLayer,
                                                                 flatBufferReshapeDesc);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferReshapeLayer.o, serializer::Layer::Layer_ReshapeLayer);
}

void SerializerStrategy::SerializeResizeLayer(const armnn::IConnectableLayer* layer,
                                         const armnn::ResizeDescriptor& resizeDescriptor,
                                         const char* name)
{
    IgnoreUnused(name);

    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Resize);

    auto flatBufferDescriptor =
            CreateResizeDescriptor(m_flatBufferBuilder,
                                   resizeDescriptor.m_TargetHeight,
                                   resizeDescriptor.m_TargetWidth,
                                   GetFlatBufferResizeMethod(resizeDescriptor.m_Method),
                                   GetFlatBufferDataLayout(resizeDescriptor.m_DataLayout),
                                   resizeDescriptor.m_AlignCorners,
                                   resizeDescriptor.m_HalfPixelCenters);

    auto flatBufferLayer = serializer::CreateResizeLayer(m_flatBufferBuilder,
                                                         flatBufferBaseLayer,
                                                         flatBufferDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_ResizeLayer);
}

void SerializerStrategy::SerializeSliceLayer(const armnn::IConnectableLayer* layer,
                                        const armnn::SliceDescriptor& sliceDescriptor,
                                        const char* name)
{
    IgnoreUnused(name);

    auto fbSliceBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Slice);
    auto fbSliceDescriptor = CreateSliceDescriptor(m_flatBufferBuilder,
                                                   m_flatBufferBuilder.CreateVector(sliceDescriptor.m_Begin),
                                                   m_flatBufferBuilder.CreateVector(sliceDescriptor.m_Size));

    auto fbSliceLayer = serializer::CreateSliceLayer(m_flatBufferBuilder, fbSliceBaseLayer, fbSliceDescriptor);

    CreateAnyLayer(fbSliceLayer.o, serializer::Layer::Layer_SliceLayer);
}

// Build FlatBuffer for Softmax Layer
void SerializerStrategy::SerializeSoftmaxLayer(const armnn::IConnectableLayer* layer,
                                          const armnn::SoftmaxDescriptor& softmaxDescriptor,
                                          const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferSoftmaxBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Softmax);

    // Create the FlatBuffer SoftmaxDescriptor
    auto flatBufferSoftmaxDesc =
        serializer::CreateSoftmaxDescriptor(m_flatBufferBuilder,
                                            softmaxDescriptor.m_Beta,
                                            softmaxDescriptor.m_Axis);

    // Create the FlatBuffer SoftmaxLayer
    auto flatBufferSoftmaxLayer =
        serializer::CreateSoftmaxLayer(m_flatBufferBuilder,
                                       flatBufferSoftmaxBaseLayer,
                                       flatBufferSoftmaxDesc);

    CreateAnyLayer(flatBufferSoftmaxLayer.o, serializer::Layer::Layer_SoftmaxLayer);
}

void SerializerStrategy::SerializePooling2dLayer(const armnn::IConnectableLayer* layer,
                                            const armnn::Pooling2dDescriptor& pooling2dDescriptor,
                                            const char* name)
{
    IgnoreUnused(name);

    auto fbPooling2dBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Pooling2d);
    auto fbPooling2dDescriptor = serializer::CreatePooling2dDescriptor(
        m_flatBufferBuilder,
        GetFlatBufferPoolingAlgorithm(pooling2dDescriptor.m_PoolType),
        pooling2dDescriptor.m_PadLeft,
        pooling2dDescriptor.m_PadRight,
        pooling2dDescriptor.m_PadTop,
        pooling2dDescriptor.m_PadBottom,
        pooling2dDescriptor.m_PoolWidth,
        pooling2dDescriptor.m_PoolHeight,
        pooling2dDescriptor.m_StrideX,
        pooling2dDescriptor.m_StrideY,
        GetFlatBufferOutputShapeRounding(pooling2dDescriptor.m_OutputShapeRounding),
        GetFlatBufferPaddingMethod(pooling2dDescriptor.m_PaddingMethod),
        GetFlatBufferDataLayout(pooling2dDescriptor.m_DataLayout));

    auto fbPooling2dLayer = serializer::CreatePooling2dLayer(m_flatBufferBuilder,
                                                             fbPooling2dBaseLayer,
                                                             fbPooling2dDescriptor);

    CreateAnyLayer(fbPooling2dLayer.o, serializer::Layer::Layer_Pooling2dLayer);
}

void SerializerStrategy::SerializePreluLayer(const armnn::IConnectableLayer* layer,
                                        const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferPreluBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Prelu);

    // Create the FlatBuffer AdditionLayer
    auto flatBufferPreluLayer = serializer::CreatePreluLayer(m_flatBufferBuilder, flatBufferPreluBaseLayer);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferPreluLayer.o, serializer::Layer::Layer_PreluLayer);
}

void SerializerStrategy::SerializeQuantizeLayer(const armnn::IConnectableLayer *layer, const char *name)
{
    IgnoreUnused(name);

    auto fbQuantizeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Quantize);
    auto fbQuantizeLayer = serializer::CreateQuantizeLayer(m_flatBufferBuilder,
                                                           fbQuantizeBaseLayer);
    CreateAnyLayer(fbQuantizeLayer.o, serializer::Layer::Layer_QuantizeLayer);
}

// Build FlatBuffer for FullyConnected Layer
void SerializerStrategy::SerializeFullyConnectedLayer(const armnn::IConnectableLayer* layer,
                                                      const armnn::FullyConnectedDescriptor& fullyConnectedDescriptor,
                                                      const char*)
{
    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_FullyConnected);

    // Create FlatBuffer FullyConnectedDescriptor
    auto flatBufferDescriptor =
        serializer::CreateFullyConnectedDescriptor(m_flatBufferBuilder,
                                                   fullyConnectedDescriptor.m_BiasEnabled,
                                                   fullyConnectedDescriptor.m_TransposeWeightMatrix,
                                                   fullyConnectedDescriptor.m_ConstantWeights);

    // Create FlatBuffer FullyConnectedLayer
    auto flatBufferLayer = serializer::CreateFullyConnectedLayer(m_flatBufferBuilder,
                                                                 flatBufferBaseLayer,
                                                                 flatBufferDescriptor);

    // Add created FullyConnectedLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_FullyConnectedLayer);
}

// Build FlatBuffer for SpaceToBatchNd Layer
void SerializerStrategy::SerializeSpaceToBatchNdLayer(const armnn::IConnectableLayer* layer,
                                                 const armnn::SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor,
                                                 const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_SpaceToBatchNd);

    std::vector<unsigned int> padList;
    padList.reserve(spaceToBatchNdDescriptor.m_PadList.size()*2);
    for (auto& pad : spaceToBatchNdDescriptor.m_PadList)
    {
        padList.push_back(pad.first);
        padList.push_back(pad.second);
    }

    auto flatBufferDescriptor =
        CreateSpaceToBatchNdDescriptor(m_flatBufferBuilder,
                                       m_flatBufferBuilder.CreateVector(spaceToBatchNdDescriptor.m_BlockShape),
                                       m_flatBufferBuilder.CreateVector(padList),
                                       GetFlatBufferDataLayout(spaceToBatchNdDescriptor.m_DataLayout));

    auto flatBufferLayer = serializer::CreateSpaceToBatchNdLayer(m_flatBufferBuilder,
                                                                 flatBufferBaseLayer,
                                                                 flatBufferDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_SpaceToBatchNdLayer);
}

// Build FlatBuffer for SpaceToDepthLayer
void SerializerStrategy::SerializeSpaceToDepthLayer(const armnn::IConnectableLayer* layer,
                                               const armnn::SpaceToDepthDescriptor& spaceToDepthDescriptor,
                                               const char* name)
{
    IgnoreUnused(name);

    auto flatBufferBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_SpaceToDepth);
    auto flatBufferDescriptor =
        CreateSpaceToDepthDescriptor(m_flatBufferBuilder,
                                     spaceToDepthDescriptor.m_BlockSize,
                                     GetFlatBufferDataLayout(spaceToDepthDescriptor.m_DataLayout));

    auto flatBufferLayer = serializer::CreateSpaceToDepthLayer(m_flatBufferBuilder,
                                                               flatBufferBaseLayer,
                                                               flatBufferDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_SpaceToDepthLayer);
}

// Build FlatBuffer for Splitter Layer
void SerializerStrategy::SerializeSplitterLayer(const armnn::IConnectableLayer* layer,
                                           const armnn::ViewsDescriptor& viewsDescriptor,
                                           const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer ViewOrigins
    std::vector<flatbuffers::Offset<UintVector>> flatBufferViewOrigins;
    flatBufferViewOrigins.reserve(viewsDescriptor.GetNumViews());

    for(unsigned int vIdx = 0; vIdx < viewsDescriptor.GetNumViews(); ++vIdx)
    {
        std::vector<uint32_t> viewOrigin;
        viewOrigin.reserve(viewsDescriptor.GetNumDimensions());

        // Copy vector
        for(unsigned int dIdx = 0; dIdx < viewsDescriptor.GetNumDimensions(); ++dIdx)
        {
            viewOrigin.push_back(viewsDescriptor.GetViewOrigin(vIdx)[dIdx]);
        }

        flatBufferViewOrigins.push_back(CreateUintVector(m_flatBufferBuilder,
                                                         m_flatBufferBuilder.CreateVector(viewOrigin)));
    }

    // Create FlatBuffer OriginsDescriptor
    auto flatBufferOriginDescriptor = CreateOriginsDescriptor(m_flatBufferBuilder,
                                                              viewsDescriptor.GetOrigins().GetConcatAxis(),
                                                              viewsDescriptor.GetOrigins().GetNumViews(),
                                                              viewsDescriptor.GetOrigins().GetNumDimensions(),
                                                              m_flatBufferBuilder.CreateVector(flatBufferViewOrigins));

    // Create FlatBuffer ViewOrigins
    std::vector<flatbuffers::Offset<UintVector>> flatBufferViewSizes;
    flatBufferViewSizes.reserve(viewsDescriptor.GetNumViews());

    for(unsigned int vIdx = 0; vIdx < viewsDescriptor.GetNumViews(); ++vIdx)
    {
        std::vector<uint32_t> viewSize;
        viewSize.reserve(viewsDescriptor.GetNumDimensions());

        // Copy vector
        for(unsigned int dIdx = 0; dIdx < viewsDescriptor.GetNumDimensions(); ++dIdx)
        {
            viewSize.push_back(viewsDescriptor.GetViewSizes(vIdx)[dIdx]);
        }

        flatBufferViewSizes.push_back(CreateUintVector(m_flatBufferBuilder,
                                                       m_flatBufferBuilder.CreateVector(viewSize)));
    }

    // Create FlatBuffer ViewsDescriptor
    auto flatBufferViewsDescriptor = CreateViewsDescriptor(m_flatBufferBuilder,
                                                           flatBufferOriginDescriptor,
                                                           m_flatBufferBuilder.CreateVector(flatBufferViewSizes));

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Splitter);

    auto flatBufferSplitterLayer = serializer::CreateSplitterLayer(m_flatBufferBuilder,
                                                                   flatBufferBaseLayer,
                                                                   flatBufferViewsDescriptor);

    CreateAnyLayer(flatBufferSplitterLayer.o, serializer::Layer::Layer_SplitterLayer);
}

void SerializerStrategy::SerializeNormalizationLayer(const armnn::IConnectableLayer* layer,
                                                const armnn::NormalizationDescriptor& descriptor,
                                                const char* name)
{
    IgnoreUnused(name);

    auto fbNormalizationBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Normalization);

    auto fbNormalizationDescriptor = serializer::CreateNormalizationDescriptor(
        m_flatBufferBuilder,
        GetFlatBufferNormalizationAlgorithmChannel(descriptor.m_NormChannelType),
        GetFlatBufferNormalizationAlgorithmMethod(descriptor.m_NormMethodType),
        descriptor.m_NormSize,
        descriptor.m_Alpha,
        descriptor.m_Beta,
        descriptor.m_K,
        GetFlatBufferDataLayout(descriptor.m_DataLayout));

    auto flatBufferLayer = serializer::CreateNormalizationLayer(m_flatBufferBuilder,
                                                                fbNormalizationBaseLayer,
                                                                fbNormalizationDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_NormalizationLayer);
}

void SerializerStrategy::SerializeShapeLayer(const armnn::IConnectableLayer* layer,
                                             const char* name)
{
    IgnoreUnused(name);

    auto shapeBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Shape);
    auto shapeLayer = serializer::CreateShapeLayer(m_flatBufferBuilder, shapeBaseLayer);

    CreateAnyLayer(shapeLayer.o, serializer::Layer::Layer_ShapeLayer);
}

void SerializerStrategy::SerializeStackLayer(const armnn::IConnectableLayer* layer,
                                        const armnn::StackDescriptor& stackDescriptor,
                                        const char* name)
{
    IgnoreUnused(name);

    auto stackBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Stack);

    std::vector<unsigned int> inputShape;
    for (unsigned int i =0; i < stackDescriptor.m_InputShape.GetNumDimensions(); i++)
    {
        inputShape.push_back(stackDescriptor.m_InputShape[i]);
    }

    auto flatBufferStackDescriptor = CreateStackDescriptor(m_flatBufferBuilder,
                                                           stackDescriptor.m_Axis,
                                                           stackDescriptor.m_NumInputs,
                                                           m_flatBufferBuilder.CreateVector(inputShape));

    auto stackLayer = serializer::CreateStackLayer(m_flatBufferBuilder, stackBaseLayer, flatBufferStackDescriptor);
    CreateAnyLayer(stackLayer.o, serializer::Layer::Layer_StackLayer);
}

void SerializerStrategy::SerializeStandInLayer(const armnn::IConnectableLayer *layer,
                                          const armnn::StandInDescriptor& standInDescriptor,
                                          const char *name)
{
    IgnoreUnused(name);

    auto fbDescriptor = serializer::CreateStandInDescriptor(m_flatBufferBuilder,
                                                            standInDescriptor.m_NumInputs,
                                                            standInDescriptor.m_NumOutputs);

    auto fbBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_StandIn);
    auto fbLayer     = serializer::CreateStandInLayer(m_flatBufferBuilder, fbBaseLayer, fbDescriptor);

    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_StandInLayer);
}

void SerializerStrategy::SerializeStridedSliceLayer(const armnn::IConnectableLayer* layer,
                                               const armnn::StridedSliceDescriptor& stridedSliceDescriptor,
                                               const char* name)
{
    IgnoreUnused(name);

    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_StridedSlice);

    auto flatBufferDescriptor =
        CreateStridedSliceDescriptor(m_flatBufferBuilder,
                                     m_flatBufferBuilder.CreateVector(stridedSliceDescriptor.m_Begin),
                                     m_flatBufferBuilder.CreateVector(stridedSliceDescriptor.m_End),
                                     m_flatBufferBuilder.CreateVector(stridedSliceDescriptor.m_Stride),
                                     stridedSliceDescriptor.m_BeginMask,
                                     stridedSliceDescriptor.m_EndMask,
                                     stridedSliceDescriptor.m_ShrinkAxisMask,
                                     stridedSliceDescriptor.m_EllipsisMask,
                                     stridedSliceDescriptor.m_NewAxisMask,
                                     GetFlatBufferDataLayout(stridedSliceDescriptor.m_DataLayout));

    auto flatBufferLayer = serializer::CreateStridedSliceLayer(m_flatBufferBuilder,
                                                               flatBufferBaseLayer,
                                                               flatBufferDescriptor);

    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_StridedSliceLayer);
}

void SerializerStrategy::SerializeSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    auto fbSubtractionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Subtraction);
    auto fbSubtractionLayer = serializer::CreateSubtractionLayer(m_flatBufferBuilder, fbSubtractionBaseLayer);

    CreateAnyLayer(fbSubtractionLayer.o, serializer::Layer::Layer_SubtractionLayer);
}

void SerializerStrategy::SerializeSwitchLayer(const armnn::IConnectableLayer* layer, const char* name)
{
    IgnoreUnused(name);

    auto fbSwitchBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Switch);
    auto fbSwitchLayer = serializer::CreateSwitchLayer(m_flatBufferBuilder, fbSwitchBaseLayer);

    CreateAnyLayer(fbSwitchLayer.o, serializer::Layer::Layer_SwitchLayer);
}

void SerializerStrategy::SerializeTransposeConvolution2dLayer(
    const armnn::IConnectableLayer* layer,
    const armnn::TransposeConvolution2dDescriptor& descriptor,
    const std::vector<armnn::ConstTensor>& constants,
    const char* name)
{
    IgnoreUnused(name);

    const armnn::ConstTensor& weights = constants.at(0);

    auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Convolution2d);
    auto fbDescriptor = CreateTransposeConvolution2dDescriptor(m_flatBufferBuilder,
                                                               descriptor.m_PadLeft,
                                                               descriptor.m_PadRight,
                                                               descriptor.m_PadTop,
                                                               descriptor.m_PadBottom,
                                                               descriptor.m_StrideX,
                                                               descriptor.m_StrideY,
                                                               descriptor.m_BiasEnabled,
                                                               GetFlatBufferDataLayout(descriptor.m_DataLayout));

    // weights & biases
    auto fbWeightsConstTensorInfo = CreateConstTensorInfo(weights);
    flatbuffers::Offset<serializer::ConstTensor> fbBiasesConstTensorInfo;
    if (constants.size() > 1)
    {
        const armnn::ConstTensor& biases = constants.at(1);
        fbBiasesConstTensorInfo = CreateConstTensorInfo(biases);
    }

    auto fbLayer = CreateTransposeConvolution2dLayer(m_flatBufferBuilder,
                                                     fbBaseLayer,
                                                     fbDescriptor,
                                                     fbWeightsConstTensorInfo,
                                                     fbBiasesConstTensorInfo);

    CreateAnyLayer(fbLayer.o, serializer::Layer::Layer_TransposeConvolution2dLayer);
}

void SerializerStrategy::SerializeTransposeLayer(const armnn::IConnectableLayer* layer,
                                            const armnn::TransposeDescriptor& descriptor,
                                            const char* name)
{
    IgnoreUnused(name);

    // Create FlatBuffer BaseLayer
    auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Transpose);

    std::vector<unsigned int> dimMappings;
    for (unsigned int i=0; i<descriptor.m_DimMappings.GetSize(); ++i)
    {
        dimMappings.push_back(descriptor.m_DimMappings[i]);
    }

    auto flatBufferDesc = serializer::CreateTransposeDescriptor(m_flatBufferBuilder,
                                                                m_flatBufferBuilder.CreateVector(dimMappings));

    // Create the FlatBuffer TransposeLayer
    auto flatBufferLayer = serializer::CreateTransposeLayer(m_flatBufferBuilder,
                                                            flatBufferBaseLayer,
                                                            flatBufferDesc);

    // Add the AnyLayer to the FlatBufferLayers
    CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_TransposeLayer);
}

void SerializerStrategy::SerializeQLstmLayer(const armnn::IConnectableLayer* layer,
                                             const armnn::QLstmDescriptor& descriptor,
                                             const std::vector<armnn::ConstTensor>& constants,
                                             const char* name)
{
    IgnoreUnused(name);

    auto fbQLstmBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_QLstm);

    auto fbQLstmDescriptor = serializer::CreateQLstmDescriptor(
            m_flatBufferBuilder,
            descriptor.m_CifgEnabled,
            descriptor.m_PeepholeEnabled,
            descriptor.m_ProjectionEnabled,
            descriptor.m_LayerNormEnabled,
            descriptor.m_CellClip,
            descriptor.m_ProjectionClip,
            descriptor.m_InputIntermediateScale,
            descriptor.m_ForgetIntermediateScale,
            descriptor.m_CellIntermediateScale,
            descriptor.m_OutputIntermediateScale,
            descriptor.m_HiddenStateZeroPoint,
            descriptor.m_HiddenStateScale
            );

    // Index for constants vector
    std::size_t i = 0;

    // Mandatory params
    auto inputToForgetWeights     = CreateConstTensorInfo(constants[i++]); //InputToForgetWeights
    auto inputToCellWeights       = CreateConstTensorInfo(constants[i++]); //InputToCellWeights
    auto inputToOutputWeights     = CreateConstTensorInfo(constants[i++]); //InputToOutputWeights
    auto recurrentToForgetWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToForgetWeights
    auto recurrentToCellWeights   = CreateConstTensorInfo(constants[i++]); //RecurrentToCellWeights
    auto recurrentToOutputWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToOutputWeights
    auto forgetGateBias           = CreateConstTensorInfo(constants[i++]); //ForgetGateBias
    auto cellBias                 = CreateConstTensorInfo(constants[i++]); //CellBias
    auto outputGateBias           = CreateConstTensorInfo(constants[i++]); //OutputGateBias

    // CIFG
    flatbuffers::Offset<serializer::ConstTensor> inputToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> recurrentToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> inputGateBias;

    if (!descriptor.m_CifgEnabled)
    {
        inputToInputWeights = CreateConstTensorInfo(constants[i++]); //InputToInputWeights
        recurrentToInputWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToInputWeights
        inputGateBias = CreateConstTensorInfo(constants[i++]); //InputGateBias
    }

    // Peephole
    flatbuffers::Offset<serializer::ConstTensor> cellToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellToForgetWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellToOutputWeights;

    if (descriptor.m_PeepholeEnabled)
    {
        if (!descriptor.m_CifgEnabled)
        {
            cellToInputWeights = CreateConstTensorInfo(constants[i++]); //CellToInputWeights
        }
        cellToForgetWeights = CreateConstTensorInfo(constants[i++]); //CellToForgetWeights
        cellToOutputWeights = CreateConstTensorInfo(constants[i++]); //CellToOutputWeights
    }

    // Projection
    flatbuffers::Offset<serializer::ConstTensor> projectionWeights;
    flatbuffers::Offset<serializer::ConstTensor> projectionBias;

    if (descriptor.m_ProjectionEnabled)
    {
        projectionWeights = CreateConstTensorInfo(constants[i++]); //ProjectionWeights
        projectionBias = CreateConstTensorInfo(constants[i++]); //ProjectionBias
    }

    // Layer norm
    flatbuffers::Offset<serializer::ConstTensor> inputLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> forgetLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> outputLayerNormWeights;

    if (descriptor.m_LayerNormEnabled)
    {
        if (!descriptor.m_CifgEnabled)
        {
            inputLayerNormWeights = CreateConstTensorInfo(constants[i++]); //InputLayerNormWeights
        }
        forgetLayerNormWeights = CreateConstTensorInfo(constants[i++]); //ForgetLayerNormWeights
        cellLayerNormWeights   = CreateConstTensorInfo(constants[i++]); //CellLayerNormWeights
        outputLayerNormWeights = CreateConstTensorInfo(constants[i++]); //OutputLayerNormWeights
    }

    auto fbQLstmParams = serializer::CreateQLstmInputParams(
            m_flatBufferBuilder,
            inputToForgetWeights,
            inputToCellWeights,
            inputToOutputWeights,
            recurrentToForgetWeights,
            recurrentToCellWeights,
            recurrentToOutputWeights,
            forgetGateBias,
            cellBias,
            outputGateBias,
            inputToInputWeights,
            recurrentToInputWeights,
            inputGateBias,
            projectionWeights,
            projectionBias,
            cellToInputWeights,
            cellToForgetWeights,
            cellToOutputWeights,
            inputLayerNormWeights,
            forgetLayerNormWeights,
            cellLayerNormWeights,
            outputLayerNormWeights);

    auto fbQLstmLayer = serializer::CreateQLstmLayer(
            m_flatBufferBuilder,
            fbQLstmBaseLayer,
            fbQLstmDescriptor,
            fbQLstmParams);

    CreateAnyLayer(fbQLstmLayer.o, serializer::Layer::Layer_QLstmLayer);
}

void SerializerStrategy::SerializeQuantizedLstmLayer(const armnn::IConnectableLayer* layer,
                                                     const std::vector<armnn::ConstTensor>& constants,
                                                     const char* name)
{
    IgnoreUnused(name);

    auto fbQuantizedLstmBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_QuantizedLstm);

    // index for constants vector
    size_t i = 0;

    // Get input parameters
    auto inputToInputWeights  = CreateConstTensorInfo(constants[i++]);
    auto inputToForgetWeights = CreateConstTensorInfo(constants[i++]);
    auto inputToCellWeights   = CreateConstTensorInfo(constants[i++]);
    auto inputToOutputWeights = CreateConstTensorInfo(constants[i++]);

    auto recurrentToInputWeights  = CreateConstTensorInfo(constants[i++]);
    auto recurrentToForgetWeights = CreateConstTensorInfo(constants[i++]);
    auto recurrentToCellWeights   = CreateConstTensorInfo(constants[i++]);
    auto recurrentToOutputWeights = CreateConstTensorInfo(constants[i++]);

    auto inputGateBias  = CreateConstTensorInfo(constants[i++]);
    auto forgetGateBias = CreateConstTensorInfo(constants[i++]);
    auto cellBias       = CreateConstTensorInfo(constants[i++]);
    auto outputGateBias = CreateConstTensorInfo(constants[i++]);

    auto fbQuantizedLstmParams = serializer::CreateQuantizedLstmInputParams(
        m_flatBufferBuilder,
        inputToInputWeights,
        inputToForgetWeights,
        inputToCellWeights,
        inputToOutputWeights,
        recurrentToInputWeights,
        recurrentToForgetWeights,
        recurrentToCellWeights,
        recurrentToOutputWeights,
        inputGateBias,
        forgetGateBias,
        cellBias,
        outputGateBias);

    auto fbQuantizedLstmLayer = serializer::CreateQuantizedLstmLayer(
        m_flatBufferBuilder,
        fbQuantizedLstmBaseLayer,
        fbQuantizedLstmParams);

    CreateAnyLayer(fbQuantizedLstmLayer.o, serializer::Layer::Layer_QuantizedLstmLayer);
}

void SerializerStrategy::SerializeUnidirectionalSequenceLstmLayer(
    const armnn::IConnectableLayer* layer,
    const armnn::UnidirectionalSequenceLstmDescriptor& descriptor,
    const std::vector<armnn::ConstTensor>& constants,
    const char* name)
{
    IgnoreUnused(name);

    auto fbUnidirectionalSequenceLstmBaseLayer =
        CreateLayerBase(layer, serializer::LayerType::LayerType_UnidirectionalSequenceLstm);

    auto fbUnidirectionalSequenceLstmDescriptor = serializer::CreateUnidirectionalSequenceLstmDescriptor(
        m_flatBufferBuilder,
        descriptor.m_ActivationFunc,
        descriptor.m_ClippingThresCell,
        descriptor.m_ClippingThresProj,
        descriptor.m_CifgEnabled,
        descriptor.m_PeepholeEnabled,
        descriptor.m_ProjectionEnabled,
        descriptor.m_LayerNormEnabled,
        descriptor.m_TimeMajor);

    // Index for constants vector
    std::size_t i = 0;

    // Get mandatory/basic input parameters
    auto inputToForgetWeights     = CreateConstTensorInfo(constants[i++]); //InputToForgetWeights
    auto inputToCellWeights       = CreateConstTensorInfo(constants[i++]); //InputToCellWeights
    auto inputToOutputWeights     = CreateConstTensorInfo(constants[i++]); //InputToOutputWeights
    auto recurrentToForgetWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToForgetWeights
    auto recurrentToCellWeights   = CreateConstTensorInfo(constants[i++]); //RecurrentToCellWeights
    auto recurrentToOutputWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToOutputWeights
    auto forgetGateBias           = CreateConstTensorInfo(constants[i++]); //ForgetGateBias
    auto cellBias                 = CreateConstTensorInfo(constants[i++]); //CellBias
    auto outputGateBias           = CreateConstTensorInfo(constants[i++]); //OutputGateBias

    //Define optional parameters, these will be set depending on configuration in Lstm descriptor
    flatbuffers::Offset<serializer::ConstTensor> inputToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> recurrentToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellToInputWeights;
    flatbuffers::Offset<serializer::ConstTensor> inputGateBias;
    flatbuffers::Offset<serializer::ConstTensor> projectionWeights;
    flatbuffers::Offset<serializer::ConstTensor> projectionBias;
    flatbuffers::Offset<serializer::ConstTensor> cellToForgetWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellToOutputWeights;
    flatbuffers::Offset<serializer::ConstTensor> inputLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> forgetLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> cellLayerNormWeights;
    flatbuffers::Offset<serializer::ConstTensor> outputLayerNormWeights;

    if (!descriptor.m_CifgEnabled)
    {
        inputToInputWeights = CreateConstTensorInfo(constants[i++]); //InputToInputWeights
        recurrentToInputWeights = CreateConstTensorInfo(constants[i++]); //RecurrentToInputWeights
        inputGateBias = CreateConstTensorInfo(constants[i++]); //InputGateBias
    }

    if (descriptor.m_PeepholeEnabled)
    {
        if (!descriptor.m_CifgEnabled)
        {
            cellToInputWeights = CreateConstTensorInfo(constants[i++]); //CellToInputWeights
        }
        cellToForgetWeights = CreateConstTensorInfo(constants[i++]); //CellToForgetWeights
        cellToOutputWeights = CreateConstTensorInfo(constants[i++]); //CellToOutputWeights
    }

    if (descriptor.m_ProjectionEnabled)
    {
        projectionWeights = CreateConstTensorInfo(constants[i++]); //ProjectionWeights
        projectionBias = CreateConstTensorInfo(constants[i++]); //ProjectionBias
    }

    if (descriptor.m_LayerNormEnabled)
    {
        if (!descriptor.m_CifgEnabled)
        {
            inputLayerNormWeights = CreateConstTensorInfo(constants[i++]); //InputLayerNormWeights
        }
        forgetLayerNormWeights = CreateConstTensorInfo(constants[i++]); //ForgetLayerNormWeights
        cellLayerNormWeights   = CreateConstTensorInfo(constants[i++]); //CellLayerNormWeights
        outputLayerNormWeights = CreateConstTensorInfo(constants[i++]); //OutputLayerNormWeights
    }

    auto fbUnidirectionalSequenceLstmParams = serializer::CreateLstmInputParams(
        m_flatBufferBuilder,
        inputToForgetWeights,
        inputToCellWeights,
        inputToOutputWeights,
        recurrentToForgetWeights,
        recurrentToCellWeights,
        recurrentToOutputWeights,
        forgetGateBias,
        cellBias,
        outputGateBias,
        inputToInputWeights,
        recurrentToInputWeights,
        cellToInputWeights,
        inputGateBias,
        projectionWeights,
        projectionBias,
        cellToForgetWeights,
        cellToOutputWeights,
        inputLayerNormWeights,
        forgetLayerNormWeights,
        cellLayerNormWeights,
        outputLayerNormWeights);

    auto fbUnidirectionalSequenceLstmLayer = serializer::CreateUnidirectionalSequenceLstmLayer(
        m_flatBufferBuilder,
        fbUnidirectionalSequenceLstmBaseLayer,
        fbUnidirectionalSequenceLstmDescriptor,
        fbUnidirectionalSequenceLstmParams);

    CreateAnyLayer(fbUnidirectionalSequenceLstmLayer.o, serializer::Layer::Layer_UnidirectionalSequenceLstmLayer);
}

fb::Offset<serializer::LayerBase> SerializerStrategy::CreateLayerBase(const IConnectableLayer* layer,
                                                                     const serializer::LayerType layerType)
{

    uint32_t fbIndex = GetSerializedId(layer->GetGuid());

    std::vector<fb::Offset<serializer::InputSlot>> inputSlots = CreateInputSlots(layer);
    std::vector<fb::Offset<serializer::OutputSlot>> outputSlots = CreateOutputSlots(layer);

    return serializer::CreateLayerBase(m_flatBufferBuilder,
                                       fbIndex,
                                       m_flatBufferBuilder.CreateString(layer->GetName()),
                                       layerType,
                                       m_flatBufferBuilder.CreateVector(inputSlots),
                                       m_flatBufferBuilder.CreateVector(outputSlots));
}

void SerializerStrategy::CreateAnyLayer(const flatbuffers::Offset<void>& layer, const serializer::Layer serializerLayer)
{

    auto anyLayer = armnnSerializer::CreateAnyLayer(m_flatBufferBuilder, serializerLayer, layer);
    m_serializedLayers.push_back(anyLayer);
}

template <typename T>
flatbuffers::Offset<flatbuffers::Vector<T>> SerializerStrategy::CreateDataVector(const void* memory, unsigned int size)
{
    const T* buffer = reinterpret_cast<const T*>(memory);
    std::vector<T> vector(buffer, buffer + (size / sizeof(T)));
    auto fbVector = m_flatBufferBuilder.CreateVector(vector);
    return fbVector;
}

flatbuffers::Offset<TensorInfo>  SerializerStrategy::CreateTensorInfo(const armnn::TensorInfo& tensorInfo)
{
    // Get the dimensions
    std::vector<unsigned int> shape;
    std::vector<bool> specificity;
    // This assumes that the TensorShape constructors have ensured that the size of m_DimensionsSpecificity
    // matches the size of dimensions.
    for(unsigned int dim = 0; dim < tensorInfo.GetShape().GetNumDimensions(); ++dim)
    {
        specificity.push_back(tensorInfo.GetShape().GetDimensionSpecificity(dim));

        if (tensorInfo.GetShape().GetDimensionSpecificity(dim))
        {
            shape.push_back(tensorInfo.GetShape()[dim]);
        }
        else
        {
            shape.push_back(0);
        }
    }

    if (tensorInfo.HasPerAxisQuantization())
    {
        // Create FlatBuffer TensorInfo
        auto flatBufferTensorInfo =
            serializer::CreateTensorInfo(m_flatBufferBuilder,
                                         m_flatBufferBuilder.CreateVector(shape),
                                         GetFlatBufferDataType(tensorInfo.GetDataType()),
                                         tensorInfo.GetQuantizationScales()[0],
                                         tensorInfo.GetQuantizationOffset(),
                                         m_flatBufferBuilder.CreateVector(tensorInfo.GetQuantizationScales()),
                                         tensorInfo.GetQuantizationDim().value(),
                                         static_cast<unsigned int>
                                         (tensorInfo.GetShape().GetDimensionality()),
                                         m_flatBufferBuilder.CreateVector(specificity));
        return flatBufferTensorInfo;
    }

    // Create FlatBuffer TensorInfo
    auto flatBufferTensorInfo = serializer::CreateTensorInfo(m_flatBufferBuilder,
                                                             m_flatBufferBuilder.CreateVector(shape),
                                                             GetFlatBufferDataType(tensorInfo.GetDataType()),
                                                             tensorInfo.GetQuantizationScale(),
                                                             tensorInfo.GetQuantizationOffset(),
                                                             0,
                                                             0,
                                                             static_cast<unsigned int>
                                                             (tensorInfo.GetShape().GetDimensionality()),
                                                             m_flatBufferBuilder.CreateVector(specificity));
    return flatBufferTensorInfo;
}

flatbuffers::Offset<serializer::ConstTensor>
    SerializerStrategy::CreateConstTensorInfo(const armnn::ConstTensor& constTensor)
{
    armnn::TensorInfo tensorInfo = constTensor.GetInfo();

    flatbuffers::Offset<void> fbPayload;

    switch (tensorInfo.GetDataType())
    {
        case armnn::DataType::Signed64:
        {
            auto fbVector = CreateDataVector<int64_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
            flatbuffers::Offset<serializer::LongData> flatBuffersData = serializer::CreateLongData(
                    m_flatBufferBuilder,
                    fbVector);
            fbPayload = flatBuffersData.o;
            break;
        }
        case armnn::DataType::Float32:
        case armnn::DataType::Signed32:
        {
            auto fbVector = CreateDataVector<int32_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
            flatbuffers::Offset<serializer::IntData> flatBuffersData = serializer::CreateIntData(
                    m_flatBufferBuilder,
                    fbVector);
            fbPayload = flatBuffersData.o;
            break;
        }
        case armnn::DataType::Float16:
        case armnn::DataType::BFloat16:
        case armnn::DataType::QSymmS16:
        {
            auto fbVector = CreateDataVector<int16_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
            flatbuffers::Offset<serializer::ShortData> flatBuffersData = serializer::CreateShortData(
                    m_flatBufferBuilder,
                    fbVector);
            fbPayload = flatBuffersData.o;
            break;
        }
        case armnn::DataType::QSymmS8:
        case armnn::DataType::QAsymmS8:
        case armnn::DataType::QAsymmU8:
        case armnn::DataType::Boolean:
        default:
        {
            auto fbVector = CreateDataVector<int8_t>(constTensor.GetMemoryArea(), constTensor.GetNumBytes());
            flatbuffers::Offset<serializer::ByteData> flatBuffersData = serializer::CreateByteData(
                    m_flatBufferBuilder,
                    fbVector);
            fbPayload = flatBuffersData.o;
        }
    }
    flatbuffers::Offset<serializer::ConstTensor> flatBufferConstTensor = serializer::CreateConstTensor(
            m_flatBufferBuilder,
            CreateTensorInfo(tensorInfo),
            GetFlatBufferConstTensorData(tensorInfo.GetDataType()),
            fbPayload);
    return flatBufferConstTensor;
}

flatbuffers::Offset<armnnSerializer::FeatureCompatibilityVersions> SerializerStrategy::GetVersionTable()
{
    flatbuffers::Offset<armnnSerializer::FeatureCompatibilityVersions> versionsTable =
        serializer::CreateFeatureCompatibilityVersions(
                m_flatBufferBuilder,
                1, // Binding ids scheme version
                1, // Weights layout scheme version
                1  // Constant tensors as inputs version
            );
    return versionsTable;
}

std::vector<fb::Offset<serializer::InputSlot>>
    SerializerStrategy::CreateInputSlots(const armnn::IConnectableLayer* layer)
{
    std::vector<fb::Offset<serializer::InputSlot>> inputSlots;

    // Get the InputSlots
    for (unsigned int slotIndex = 0; slotIndex<layer->GetNumInputSlots(); ++slotIndex)
    {
        const IInputSlot& inputSlot = layer->GetInputSlot(slotIndex);

        // Get the Connection for the InputSlot
        const IOutputSlot* connection = inputSlot.GetConnection();

        // Create FlatBuffer Connection
        serializer::Connection conn(GetSerializedId(inputSlot.GetConnection()->GetOwningLayerGuid()),
                                    connection->CalculateIndexOnOwner());
        // Create FlatBuffer InputSlot
        inputSlots.push_back(serializer::CreateInputSlot(m_flatBufferBuilder, slotIndex, &conn));
    }
    return inputSlots;
}

std::vector<fb::Offset<serializer::OutputSlot>>
    SerializerStrategy::CreateOutputSlots(const armnn::IConnectableLayer* layer)
{
    std::vector<fb::Offset<serializer::OutputSlot>> outputSlots;

    // Get the OutputSlots
    for (unsigned int slotIndex = 0; slotIndex < layer->GetNumOutputSlots(); ++slotIndex)
    {
        const IOutputSlot& outputSlot = layer->GetOutputSlot(slotIndex);
        const armnn::TensorInfo& tensorInfo = outputSlot.GetTensorInfo();

        // Create FlatBuffer Outputslot
        outputSlots.push_back(serializer::CreateOutputSlot(m_flatBufferBuilder,
                                                           slotIndex,
                                                           CreateTensorInfo(tensorInfo)));
    }
    return outputSlots;
}

void SerializerStrategy::ExecuteStrategy(const armnn::IConnectableLayer* layer,
                                         const BaseDescriptor& descriptor,
                                         const std::vector<armnn::ConstTensor>& constants,
                                         const char* name,
                                         const armnn::LayerBindingId id)
{
    IgnoreUnused(constants);

    switch (layer->GetType())
    {
        case armnn::LayerType::Activation :
        {
            const armnn::ActivationDescriptor& layerDescriptor =
                    static_cast<const armnn::ActivationDescriptor&>(descriptor);
            SerializeActivationLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Addition :
        {
            SerializeAdditionLayer(layer, name);
            break;
        }
        case armnn::LayerType::ArgMinMax :
        {
            const armnn::ArgMinMaxDescriptor& layerDescriptor =
                    static_cast<const armnn::ArgMinMaxDescriptor&>(descriptor);
            SerializeArgMinMaxLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::BatchNormalization :
        {
            const armnn::BatchNormalizationDescriptor& layerDescriptor =
                    static_cast<const armnn::BatchNormalizationDescriptor&>(descriptor);
            SerializeBatchNormalizationLayer(layer,
                                             layerDescriptor,
                                             constants,
                                             name);
            break;
        }
        case armnn::LayerType::BatchToSpaceNd :
        {
            const armnn::BatchToSpaceNdDescriptor& layerDescriptor =
                    static_cast<const armnn::BatchToSpaceNdDescriptor&>(descriptor);
            SerializeBatchToSpaceNdLayer(layer,
                                         layerDescriptor,
                                         name);
            break;
        }
        case armnn::LayerType::Cast :
        {
            SerializeCastLayer(layer, name);
            break;
        }
        case armnn::LayerType::ChannelShuffle :
        {
            const armnn::ChannelShuffleDescriptor& layerDescriptor =
                                                     static_cast<const armnn::ChannelShuffleDescriptor&>(descriptor);
            SerializeChannelShuffleLayer(layer,
                                         layerDescriptor,
                                         name);
            break;
        }
        case armnn::LayerType::Comparison :
        {
            const armnn::ComparisonDescriptor& layerDescriptor =
                    static_cast<const armnn::ComparisonDescriptor&>(descriptor);
            SerializeComparisonLayer(layer,
                                     layerDescriptor,
                                     name);
            break;
        }
        case armnn::LayerType::Concat :
        {
            const armnn::ConcatDescriptor& layerDescriptor =
                    static_cast<const armnn::ConcatDescriptor&>(descriptor);
            SerializeConcatLayer(layer,
                                 layerDescriptor,
                                 name);
            break;
        }
        case armnn::LayerType::Constant :
        {
            SerializeConstantLayer(layer,
                                   constants,
                                   name);
            break;
        }
        case armnn::LayerType::Convolution2d :
        {
            const armnn::Convolution2dDescriptor& layerDescriptor =
                    static_cast<const armnn::Convolution2dDescriptor&>(descriptor);
            SerializeConvolution2dLayer(layer,
                                        layerDescriptor,
                                        constants,
                                        name);
            break;
        }
        case armnn::LayerType::Convolution3d :
        {
            const armnn::Convolution3dDescriptor& layerDescriptor =
                    static_cast<const armnn::Convolution3dDescriptor&>(descriptor);
            SerializeConvolution3dLayer(layer,
                                        layerDescriptor,
                                        name);
            break;
        }
        case armnn::LayerType::DepthToSpace :
        {
            const armnn::DepthToSpaceDescriptor& layerDescriptor =
                    static_cast<const armnn::DepthToSpaceDescriptor&>(descriptor);
            SerializeDepthToSpaceLayer(layer,
                                       layerDescriptor,
                                       name);
            break;
        }
        case armnn::LayerType::DepthwiseConvolution2d :
        {
            const armnn::DepthwiseConvolution2dDescriptor& layerDescriptor =
                    static_cast<const armnn::DepthwiseConvolution2dDescriptor&>(descriptor);
            SerializeDepthwiseConvolution2dLayer(layer,
                                                 layerDescriptor,
                                                 constants,
                                                 name);
            break;
        }
        case armnn::LayerType::Dequantize :
        {
            SerializeDequantizeLayer(layer,
                                     name);
            break;
        }
        case armnn::LayerType::DetectionPostProcess :
        {
            const armnn::DetectionPostProcessDescriptor& layerDescriptor =
                    static_cast<const armnn::DetectionPostProcessDescriptor&>(descriptor);
            SerializeDetectionPostProcessLayer(layer, layerDescriptor, constants, name);
            break;
        }
        case armnn::LayerType::Division :
        {
            SerializeDivisionLayer(layer, name);
            break;
        }
        case armnn::LayerType::ElementwiseUnary :
        {
            const armnn::ElementwiseUnaryDescriptor& layerDescriptor =
                    static_cast<const armnn::ElementwiseUnaryDescriptor&>(descriptor);
            SerializeElementwiseUnaryLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Fill :
        {
            const armnn::FillDescriptor& layerDescriptor =
                    static_cast<const armnn::FillDescriptor&>(descriptor);
            SerializeFillLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Floor :
        {
            SerializeFloorLayer(layer, name);
            break;
        }
        case armnn::LayerType::FullyConnected :
        {
            const armnn::FullyConnectedDescriptor& layerDescriptor =
                    static_cast<const armnn::FullyConnectedDescriptor&>(descriptor);
            SerializeFullyConnectedLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Gather :
        {
            const armnn::GatherDescriptor& layerDescriptor =
                    static_cast<const armnn::GatherDescriptor&>(descriptor);
            SerializeGatherLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Input:
        {
            SerializeInputLayer(layer, id, name);
            break;
        }
        case armnn::LayerType::InstanceNormalization :
        {
            const armnn::InstanceNormalizationDescriptor& layerDescriptor =
                    static_cast<const armnn::InstanceNormalizationDescriptor&>(descriptor);
            SerializeInstanceNormalizationLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::L2Normalization :
        {
            const armnn::L2NormalizationDescriptor& layerDescriptor =
                    static_cast<const armnn::L2NormalizationDescriptor&>(descriptor);
            SerializeL2NormalizationLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::LogicalBinary :
        {
            const armnn::LogicalBinaryDescriptor& layerDescriptor =
                    static_cast<const armnn::LogicalBinaryDescriptor&>(descriptor);
            SerializeLogicalBinaryLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::LogSoftmax :
        {
            const armnn::LogSoftmaxDescriptor& layerDescriptor =
                    static_cast<const armnn::LogSoftmaxDescriptor&>(descriptor);
            SerializeLogSoftmaxLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Lstm :
        {
            const armnn::LstmDescriptor& layerDescriptor =
                    static_cast<const armnn::LstmDescriptor&>(descriptor);
            SerializeLstmLayer(layer, layerDescriptor, constants, name);
            break;
        }
        case armnn::LayerType::QLstm :
        {
            const armnn::QLstmDescriptor& layerDescriptor =
                    static_cast<const armnn::QLstmDescriptor&>(descriptor);
            SerializeQLstmLayer(layer, layerDescriptor, constants, name);
            break;
        }
        case armnn::LayerType::Maximum :
        {
            SerializeMaximumLayer(layer, name);
            break;
        }
        case armnn::LayerType::Mean :
        {
            const armnn::MeanDescriptor& layerDescriptor =
                    static_cast<const armnn::MeanDescriptor&>(descriptor);
            SerializeMeanLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Merge :
        {
            SerializeMergeLayer(layer, name);
            break;
        }
        case armnn::LayerType::Minimum :
        {
            SerializeMinimumLayer(layer, name);
            break;
        }
        case armnn::LayerType::Multiplication :
        {
            SerializeMultiplicationLayer(layer, name);
            break;
        }
        case armnn::LayerType::Normalization :
        {
            const armnn::NormalizationDescriptor& layerDescriptor =
                    static_cast<const armnn::NormalizationDescriptor&>(descriptor);
            SerializeNormalizationLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Output:
        {
            SerializeOutputLayer(layer, id, name);
            break;
        }
        case armnn::LayerType::Pad :
        {
            const armnn::PadDescriptor& layerDescriptor =
                    static_cast<const armnn::PadDescriptor&>(descriptor);
            SerializePadLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Permute :
        {
            const armnn::PermuteDescriptor& layerDescriptor =
                    static_cast<const armnn::PermuteDescriptor&>(descriptor);
            SerializePermuteLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Pooling2d :
        {
            const armnn::Pooling2dDescriptor& layerDescriptor =
                    static_cast<const armnn::Pooling2dDescriptor&>(descriptor);
            SerializePooling2dLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Prelu :
        {
            SerializePreluLayer(layer, name);
            break;
        }
        case armnn::LayerType::Quantize :
        {
            SerializeQuantizeLayer(layer, name);
            break;
        }
        case armnn::LayerType::QuantizedLstm:
            SerializeQuantizedLstmLayer(layer, constants, name);
            break;
        case armnn::LayerType::Reshape:
        {
            const armnn::ReshapeDescriptor &layerDescriptor =
                    static_cast<const armnn::ReshapeDescriptor &>(descriptor);
            SerializeReshapeLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Rank:
        {
            SerializeRankLayer(layer, name);
            break;
        }
        case armnn::LayerType::Reduce:
        {
            const armnn::ReduceDescriptor& layerDescriptor =
                    static_cast<const armnn::ReduceDescriptor&>(descriptor);
            SerializeReduceLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Resize:
        {
            const armnn::ResizeDescriptor& layerDescriptor =
                    static_cast<const armnn::ResizeDescriptor&>(descriptor);
            SerializeResizeLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Shape:
        {
            SerializeShapeLayer(layer, name);
            break;
        }
        case armnn::LayerType::Slice:
        {
            const armnn::SliceDescriptor& layerDescriptor =
                    static_cast<const armnn::SliceDescriptor&>(descriptor);
            SerializeSliceLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Softmax:
        {
            const armnn::SoftmaxDescriptor& layerDescriptor =
                    static_cast<const armnn::SoftmaxDescriptor&>(descriptor);
            SerializeSoftmaxLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::SpaceToBatchNd:
        {
            const armnn::SpaceToBatchNdDescriptor& layerDescriptor =
                    static_cast<const armnn::SpaceToBatchNdDescriptor&>(descriptor);
            SerializeSpaceToBatchNdLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::SpaceToDepth:
        {
            const armnn::SpaceToDepthDescriptor& layerDescriptor =
                    static_cast<const armnn::SpaceToDepthDescriptor&>(descriptor);
            SerializeSpaceToDepthLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Splitter:
        {
            const armnn::SplitterDescriptor& layerDescriptor =
                    static_cast<const armnn::SplitterDescriptor&>(descriptor);
            SerializeSplitterLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Stack:
        {
            const armnn::StackDescriptor& layerDescriptor =
                    static_cast<const armnn::StackDescriptor&>(descriptor);
            SerializeStackLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::StandIn:
        {
            const armnn::StandInDescriptor& layerDescriptor =
                    static_cast<const armnn::StandInDescriptor&>(descriptor);
            SerializeStandInLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::StridedSlice:
        {
            const armnn::StridedSliceDescriptor& layerDescriptor =
                    static_cast<const armnn::StridedSliceDescriptor&>(descriptor);
            SerializeStridedSliceLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::Subtraction:
        {
            SerializeSubtractionLayer(layer, name);
            break;
        }
        case armnn::LayerType::Switch:
        {
            SerializeSwitchLayer(layer, name);
            break;
        }
        case armnn::LayerType::Transpose:
        {
            const armnn::TransposeDescriptor& layerDescriptor =
                    static_cast<const armnn::TransposeDescriptor&>(descriptor);
            SerializeTransposeLayer(layer, layerDescriptor, name);
            break;
        }
        case armnn::LayerType::TransposeConvolution2d:
        {
            const armnn::TransposeConvolution2dDescriptor& layerDescriptor =
                    static_cast<const armnn::TransposeConvolution2dDescriptor&>(descriptor);
            SerializeTransposeConvolution2dLayer(layer, layerDescriptor, constants, name);
            break;
        }
        case armnn::LayerType::UnidirectionalSequenceLstm :
        {
            const armnn::UnidirectionalSequenceLstmDescriptor& layerDescriptor =
                    static_cast<const armnn::UnidirectionalSequenceLstmDescriptor&>(descriptor);
            SerializeUnidirectionalSequenceLstmLayer(layer, layerDescriptor, constants, name);
            break;
        }
        default:
        {
            throw InvalidArgumentException(
                    fmt::format("A layer of unknown type was given to the serializer. Layer name: {}; Layer Id: {}",
                                layer->GetName(),
                                id));
        }
    }
}

void ISerializer::SerializerImpl::Serialize(const INetwork& inNetwork)
{
    // Iterate through to network
    inNetwork.ExecuteStrategy(m_SerializerStrategy);
    flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerStrategy.GetFlatBufferBuilder();

    // Create FlatBuffer SerializedGraph
    auto serializedGraph = serializer::CreateSerializedGraph(
            fbBuilder,
            fbBuilder.CreateVector(m_SerializerStrategy.GetSerializedLayers()),
            fbBuilder.CreateVector(m_SerializerStrategy.GetInputIds()),
            fbBuilder.CreateVector(m_SerializerStrategy.GetOutputIds()),
            m_SerializerStrategy.GetVersionTable());

    // Serialize the graph
    fbBuilder.Finish(serializedGraph);
}


bool ISerializer::SerializerImpl::SaveSerializedToStream(std::ostream& stream)
{
    flatbuffers::FlatBufferBuilder& fbBuilder = m_SerializerStrategy.GetFlatBufferBuilder();

    auto bytesToWrite = armnn::numeric_cast<std::streamsize>(fbBuilder.GetSize());
    stream.write(reinterpret_cast<const char*>(fbBuilder.GetBufferPointer()), bytesToWrite);
    return !stream.bad();
}

} // namespace armnnSerializer
