std::size_t encodeCar(Car &car, char *buffer, std::uint64_t offset, std::uint64_t bufferLength)
{
    car.wrapForEncode(buffer, offset, bufferLength)
       .serialNumber(1234)
       .modelYear(2013)
       .available(BooleanType::T)
       .code(Model::A)
       .putVehicleCode(VEHICLE_CODE);

    for (std::uint64_t i = 0, size = car.someNumbersLength(); i < size; i++)
    {
        car.someNumbers(i, static_cast<std::int32_t>(i));
    }

    car.extras().clear()
       .cruiseControl(true)
       .sportsPack(true)
       .sunRoof(false);

    car.engine()
       .capacity(2000)
       .numCylinders((short)4)
       .putManufacturerCode(MANUFACTURER_CODE);

    Car::FuelFigures& fuelFigures = car.fuelFiguresCount(3);

    fuelFigures
        .next().speed(30).mpg(35.9f)
        .putUsageDescription("Urban Cycle", 11);

    fuelFigures
        .next().speed(55).mpg(49.0f)
        .putUsageDescription("Combined Cycle", 14);

    fuelFigures
        .next().speed(75).mpg(40.0f)
        .putUsageDescription("Highway Cycle", 13);

    Car::PerformanceFigures &performanceFigures = car.performanceFiguresCount(2);

    performanceFigures.next()
        .octaneRating((short)95)
        .accelerationCount(3)
            .next().mph(30).seconds(4.0f)
            .next().mph(60).seconds(7.5f)
            .next().mph(100).seconds(12.2f);

    performanceFigures.next()
        .octaneRating((short)99)
        .accelerationCount(3)
            .next().mph(30).seconds(3.8f)
            .next().mph(60).seconds(7.1f)
            .next().mph(100).seconds(11.8f);

    car.putMake(MAKE, 5)
        .putModel(MODEL, 9)
        .putActivationCode("deadbeef", 8);

    return car.encodedLength();
}
TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForEncode)
{
    std::string vehicleCode(VEHICLE_CODE, Car::vehicleCodeLength());
    std::string usageDesc1(FUEL_FIGURES_1_USAGE_DESCRIPTION, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH);
    std::string usageDesc2(FUEL_FIGURES_2_USAGE_DESCRIPTION, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH);
    std::string usageDesc3(FUEL_FIGURES_3_USAGE_DESCRIPTION, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH);
    std::string make(MAKE, MAKE_LENGTH);
    std::string model(MODEL, MODEL_LENGTH);
    std::string activationCode(ACTIVATION_CODE, ACTIVATION_CODE_LENGTH);

    char buffer[BUFFER_LEN];
    std::uint64_t baseOffset = MessageHeader::encodedLength();
    Car car;
    car.wrapForEncode(buffer, baseOffset, sizeof(buffer));

    car.putVehicleCode(vehicleCode);

    car.fuelFiguresCount(FUEL_FIGURES_COUNT)
    .next().putUsageDescription(usageDesc1)
    .next().putUsageDescription(usageDesc2)
    .next().putUsageDescription(usageDesc3);

    Car::PerformanceFigures &perfFigs = car.performanceFiguresCount(PERFORMANCE_FIGURES_COUNT);

    perfFigs.next()
    .accelerationCount(ACCELERATION_COUNT).next().next().next();

    perfFigs.next()
    .accelerationCount(ACCELERATION_COUNT).next().next().next();

    car.putMake(make)
    .putModel(model)
    .putActivationCode(activationCode);

    EXPECT_EQ(car.encodedLength(), expectedCarSize);

    EXPECT_EQ(std::string(buffer + baseOffset + offsetVehicleCode, VEHICLE_CODE_LENGTH), vehicleCode);

    EXPECT_EQ(*(std::uint8_t *)(buffer + baseOffset + offsetUsageDesc1Length), FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH);
    EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc1Data, FUEL_FIGURES_1_USAGE_DESCRIPTION_LENGTH), usageDesc1);

    EXPECT_EQ(*(std::uint8_t *)(buffer + baseOffset + offsetUsageDesc2Length), FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH);
    EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc2Data, FUEL_FIGURES_2_USAGE_DESCRIPTION_LENGTH), usageDesc2);

    EXPECT_EQ(*(std::uint8_t *)(buffer + baseOffset + offsetUsageDesc3Length), FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH);
    EXPECT_EQ(std::string(buffer + baseOffset + offsetUsageDesc3Data, FUEL_FIGURES_3_USAGE_DESCRIPTION_LENGTH), usageDesc3);

    EXPECT_EQ(*(std::uint8_t *)(buffer + baseOffset + offsetMakeLength), MAKE_LENGTH);
    EXPECT_EQ(std::string(buffer + baseOffset + offsetMakeData, MAKE_LENGTH), make);

    EXPECT_EQ(*(std::uint8_t *)(buffer + baseOffset + offsetModelLength), MODEL_LENGTH);
    EXPECT_EQ(std::string(buffer + baseOffset + offsetModelData, MODEL_LENGTH), model);

    EXPECT_EQ(*(std::uint8_t *)(buffer + baseOffset + offsetActivationCodeLength), ACTIVATION_CODE_LENGTH);
    EXPECT_EQ(std::string(buffer + baseOffset + offsetActivationCodeData, ACTIVATION_CODE_LENGTH), activationCode);
}
    virtual std::uint64_t encodeHdrAndCar()
    {
        MessageHeader hdr;
        Car car;

        hdr.wrap(m_buffer, 0, 0, sizeof(m_buffer))
            .blockLength(Car::sbeBlockLength())
            .templateId(Car::sbeTemplateId())
            .schemaId(Car::sbeSchemaId())
            .version(Car::sbeSchemaVersion());

        car.wrapForEncode(m_buffer, hdr.encodedLength(), sizeof(m_buffer))
            .serialNumber(SERIAL_NUMBER)
            .modelYear(MODEL_YEAR)
            .available(AVAILABLE)
            .code(CODE)
            .putVehicleCode(VEHICLE_CODE);

        for (std::uint64_t i = 0; i < Car::someNumbersLength(); i++)
        {
            car.someNumbers(i, static_cast<std::int32_t>(i));
        }

        car.extras().clear()
            .cruiseControl(CRUISE_CONTROL)
            .sportsPack(SPORTS_PACK)
            .sunRoof(SUNROOF);

        car.engine()
            .capacity(engineCapacity)
            .numCylinders(engineNumCylinders)
            .putManufacturerCode(MANUFACTURER_CODE);

        Car::FuelFigures& fuelFigures = car.fuelFiguresCount(FUEL_FIGURES_COUNT);

        fuelFigures
            .next().speed(fuel1Speed).mpg(fuel1Mpg);

        fuelFigures.putUsageDescription(
            FUEL_FIGURES_1_USAGE_DESCRIPTION, static_cast<int>(strlen(FUEL_FIGURES_1_USAGE_DESCRIPTION)));

        fuelFigures
            .next().speed(fuel2Speed).mpg(fuel2Mpg);
        fuelFigures.putUsageDescription(
            FUEL_FIGURES_2_USAGE_DESCRIPTION, static_cast<int>(strlen(FUEL_FIGURES_2_USAGE_DESCRIPTION)));

        fuelFigures
            .next().speed(fuel3Speed).mpg(fuel3Mpg);
        fuelFigures.putUsageDescription(
            FUEL_FIGURES_3_USAGE_DESCRIPTION, static_cast<int>(strlen(FUEL_FIGURES_3_USAGE_DESCRIPTION)));

        Car::PerformanceFigures &perfFigs = car.performanceFiguresCount(PERFORMANCE_FIGURES_COUNT);

        perfFigs.next()
            .octaneRating(perf1Octane)
            .accelerationCount(ACCELERATION_COUNT)
            .next().mph(perf1aMph).seconds(perf1aSeconds)
            .next().mph(perf1bMph).seconds(perf1bSeconds)
            .next().mph(perf1cMph).seconds(perf1cSeconds);

        perfFigs.next()
            .octaneRating(perf2Octane)
            .accelerationCount(ACCELERATION_COUNT)
            .next().mph(perf2aMph).seconds(perf2aSeconds)
            .next().mph(perf2bMph).seconds(perf2bSeconds)
            .next().mph(perf2cMph).seconds(perf2cSeconds);

        car.putMake(MAKE, static_cast<int>(strlen(MAKE)));
        car.putModel(MODEL, static_cast<int>(strlen(MODEL)));
        car.putActivationCode(ACTIVATION_CODE, static_cast<int>(strlen(ACTIVATION_CODE)));

        return hdr.encodedLength() + car.encodedLength();
    }
std::size_t decodeCar(
    Car &car, char *buffer, std::uint64_t offset, std::uint64_t actingBlockLength,
    std::uint64_t actingVersion, std::uint64_t bufferLength)
{
    car.wrapForDecode(buffer, offset, actingBlockLength, actingVersion, bufferLength);

    std::cout.setf(std::ios::fixed);

    std::cout << "\ncar.serialNumberId=" << Car::serialNumberId();
    std::cout << "\ncar.modelYearId=" << Car::modelYearId();
    std::cout << "\ncar.availableId=" << Car::availableId();
    std::cout << "\ncar.codeId=" << Car::codeId();
    std::cout << "\ncar.someNumbersId=" << Car::someNumbersId();
    std::cout << "\ncar.vehicleCodeId=" << Car::vehicleCodeId();
    std::cout << "\ncar.extrasId=" << Car::extrasId();
    std::cout << "\ncar.engineId=" << Car::engineId();
    std::cout << "\ncar.fuelFiguresId=" << Car::fuelFiguresId();
    std::cout << "\ncar.fuelFigures.speedId=" << Car::FuelFigures::speedId();
    std::cout << "\ncar.fuelFigures.mpgId=" << Car::FuelFigures::mpgId();
    std::cout << "\ncar.fuelFigures.usageDescriptionId=" << Car::FuelFigures::usageDescriptionId();
    std::cout << "\ncar.performanceFiguresId=" << Car::performanceFiguresId();
    std::cout << "\ncar.performanceFigures.octaneRatingId=" << Car::PerformanceFigures::octaneRatingId();
    std::cout << "\ncar.performanceFigures.accelerationId=" << Car::PerformanceFigures::accelerationId();
    std::cout << "\ncar.performanceFigures.acceleration.mphId=" << Car::PerformanceFigures::Acceleration::mphId();
    std::cout << "\ncar.performanceFigures.acceleration.secondsId=" << Car::PerformanceFigures::Acceleration::secondsId();
    std::cout << "\ncar.makeId=" << Car::makeId();
    std::cout << "\ncar.makeCharacterEncoding=" << Car::makeCharacterEncoding();
    std::cout << "\ncar.modelId=" << Car::modelId();
    std::cout << "\ncar.modelCharacterEncoding=" << Car::modelCharacterEncoding();
    std::cout << "\ncar.activationCodeId=" << Car::activationCodeId();
    std::cout << "\ncar.activationCodeCharacterEncoding=" << Car::activationCodeCharacterEncoding();

    std::cout << "\n";

    std::cout << "\ncar.serialNumber=" << car.serialNumber();
    std::cout << "\ncar.modelYear=" << car.modelYear();
    std::cout << "\ncar.available=" << format(car.available());
    std::cout << "\ncar.code=" << format(car.code());

    std::cout << "\ncar.someNumbers=";
    std::string separator("");
    for (std::uint64_t i = 0; i < Car::someNumbersLength(); i++)
    {
        std::cout << separator << car.someNumbers(i);
        separator = ", ";
    }

    std::cout << "\ncar.vehicleCode=";
    separator = "";
    for (std::uint64_t i = 0; i < Car::vehicleCodeLength(); i++)
    {
        std::cout << separator << car.vehicleCode(i);
        separator = ", ";
    }

    OptionalExtras &extras = car.extras();
    std::cout << "\ncar.extras.cruiseControl=" << format(extras.cruiseControl());
    std::cout << "\ncar.extras.sportsPack=" << format(extras.sportsPack());
    std::cout << "\ncar.extras.sunRoof=" << format(extras.sunRoof());

    std::cout << "\ncar.discountedModel=" << format(car.discountedModel());

    Engine &engine = car.engine();
    std::cout << "\ncar.engine.capacity=" << (int)engine.capacity();
    std::cout << "\ncar.engine.numCylinders=" << (int)engine.numCylinders();
    std::cout << "\ncar.engine.maxRpm=" << (int)engine.maxRpm();
    std::cout << "\ncar.engine.manufacturerCodeLength=" << (int)engine.manufacturerCodeLength();
    std::cout << "\ncar.engine.manufacturerCode=";
    separator = "";
    for (std::uint64_t i = 0; i < Engine::manufacturerCodeLength(); i++)
    {
        std::cout << separator << engine.manufacturerCode(i);
        separator = ", ";
    }

    char tmp[1024];
    std::uint64_t bytesCopied = engine.getFuel(tmp, sizeof(tmp));
    std::cout << "\ncar.engine.fuelLength=" << bytesCopied;
    std::cout << "\ncar.engine.fuel=" << std::string(tmp, bytesCopied);

    Car::FuelFigures &fuelFigures = car.fuelFigures();
    while (fuelFigures.hasNext())
    {
        fuelFigures.next();
        std::cout << "\ncar.fuelFigures.speed=" << (int)fuelFigures.speed();
        std::cout << "\ncar.fuelFigures.mpg=" << std::setprecision(1) << (double)fuelFigures.mpg();

        std::string usageDesc = fuelFigures.getUsageDescriptionAsString();
        std::cout << "\ncar.fuelFigures.usageDescriptionLength=" << usageDesc.length();
        std::cout << "\ncar.fuelFigures.usageDescription=" << usageDesc;
    }

    Car::PerformanceFigures &performanceFigures = car.performanceFigures();
    while (performanceFigures.hasNext())
    {
        performanceFigures.next();
        std::cout << "\ncar.performanceFigures.octaneRating=" << (std::uint64_t)performanceFigures.octaneRating();

        Car::PerformanceFigures::Acceleration &acceleration = performanceFigures.acceleration();
        while (acceleration.hasNext())
        {
            acceleration.next();
            std::cout << "\ncar.performanceFigures.acceleration.mph=" << acceleration.mph();
            std::cout << "\ncar.performanceFigures.acceleration.seconds=" << std::setprecision(1) << acceleration.seconds();
        }
    }

    bytesCopied = car.getMake(tmp, sizeof(tmp));
    std::cout << "\ncar.makeLength=" << bytesCopied;
    std::cout << "\ncar.make=" << std::string(tmp, bytesCopied);

    bytesCopied = car.getModel(tmp, sizeof(tmp));
    std::cout << "\ncar.modelLength=" << bytesCopied;
    std::cout << "\ncar.model=" << std::string(tmp, bytesCopied);

    bytesCopied = car.getActivationCode(tmp, sizeof(tmp));
    std::cout << "\ncar.activationCodeLength=" << bytesCopied;
    std::cout << "\ncar.activationCode=" << std::string(tmp, bytesCopied);

    std::cout << "\ncar.encodedLength=" << (int)car.encodedLength() << "\n";

    return car.encodedLength();
}