mlt-ffi 0.2.1

Diplomat FFI bindings for mlt-core
Documentation
#include "../../generated/cpp/ConvertError.hpp"
#include "../../generated/cpp/ConvertErrorKind.hpp"
#include "../../generated/cpp/MltBuffer.hpp"
#include "../../generated/cpp/MltConverter.hpp"
#include "../../generated/cpp/MltEncoderOptions.hpp"
#include "../../generated/cpp/MltWireVersion.hpp"
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <vector>

static const uint8_t MVT_FIXTURE[] = {0x1a, 0x21, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x0d, 0x08,
                                      0x01, 0x12, 0x02, 0x00, 0x00, 0x18, 0x01, 0x22, 0x03, 0x09, 0x32, 0x22,
                                      0x1a, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x02, 0x38, 0x01, 0x78, 0x02};

static const uint8_t DECODED_POINT_MVT_WITH_EXPLICIT_EXTENT[] = {
    0x1a, 0x24, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x0d, 0x08, 0x01, 0x12, 0x02, 0x00, 0x00, 0x18, 0x01,
    0x22, 0x03, 0x09, 0x32, 0x22, 0x1a, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x02, 0x38, 0x01, 0x28, 0x80, 0x20, 0x78, 0x02};

static void v2_encoding_of_a_point_layer_decodes_to_the_same_mvt_as_v1() {
    auto v1_options = MltEncoderOptions::new_();
    auto v2_options = MltEncoderOptions::new_();
    v2_options->set_wire_version(MltWireVersion::V02);
    diplomat::span<const uint8_t> mvt(MVT_FIXTURE, sizeof(MVT_FIXTURE));

    auto v1_mlt = MltConverter::mvt_to_mlt(mvt, *v1_options).ok().value();
    auto v2_mlt = MltConverter::mvt_to_mlt(mvt, *v2_options).ok().value();
    auto v1_mvt = MltConverter::mlt_to_mvt(v1_mlt->as_bytes()).ok().value();
    auto v2_mvt = MltConverter::mlt_to_mvt(v2_mlt->as_bytes()).ok().value();

    auto v1_bytes = v1_mvt->as_bytes();
    auto v2_bytes = v2_mvt->as_bytes();
    assert(std::vector<uint8_t>(v1_bytes.begin(), v1_bytes.end()) ==
           std::vector<uint8_t>(v2_bytes.begin(), v2_bytes.end()));
}

static void decoding_garbage_as_mlt_reports_invalid_input_with_the_parser_message() {
    const uint8_t garbage[] = {0xff};

    auto error = MltConverter::mlt_to_mvt(diplomat::span<const uint8_t>(garbage, 1)).err().value();

    assert(error->kind() == ConvertErrorKind::InvalidInput);
    assert(error->message() == "buffer underflow: needed 2 bytes, but only 1 remain");
}

static void encoding_garbage_as_mvt_reports_encoding_failed_with_the_parser_message() {
    const uint8_t garbage[] = {0xff};
    auto options = MltEncoderOptions::new_();

    auto error = MltConverter::mvt_to_mlt(diplomat::span<const uint8_t>(garbage, 1), *options).err().value();

    assert(error->kind() == ConvertErrorKind::EncodingFailed);
    assert(error->message() == "MVT error: protobuf decode error: unexpected end of buffer");
}

static void v1_encoding_of_a_point_layer_decodes_to_the_point_mvt_with_an_explicit_extent() {
    auto options = MltEncoderOptions::new_();
    diplomat::span<const uint8_t> mvt(MVT_FIXTURE, sizeof(MVT_FIXTURE));

    auto mlt = MltConverter::mvt_to_mlt(mvt, *options).ok().value();
    auto decoded = MltConverter::mlt_to_mvt(mlt->as_bytes()).ok().value();

    auto decoded_bytes = decoded->as_bytes();
    assert(std::vector<uint8_t>(decoded_bytes.begin(), decoded_bytes.end()) ==
           std::vector<uint8_t>(std::begin(DECODED_POINT_MVT_WITH_EXPLICIT_EXTENT),
                                std::end(DECODED_POINT_MVT_WITH_EXPLICIT_EXTENT)));
}

int main() {
    v1_encoding_of_a_point_layer_decodes_to_the_point_mvt_with_an_explicit_extent();
    v2_encoding_of_a_point_layer_decodes_to_the_same_mvt_as_v1();
    decoding_garbage_as_mlt_reports_invalid_input_with_the_parser_message();
    encoding_garbage_as_mvt_reports_encoding_failed_with_the_parser_message();

    printf("C++ round-trip test passed\n");
    return 0;
}