// Auto generated by Craby. DO NOT EDIT.
#pragma once

#include "cxx.h"
#include "ffi.rs.h"
#include <react/bridging/Bridging.h>
#include <variant>

using namespace facebook;

namespace hwpjs {

class RustVecBuffer : public jsi::MutableBuffer {
public:
  explicit RustVecBuffer(rust::Vec<uint8_t> vec)
    : vec_(std::move(vec)) {}

  ~RustVecBuffer() override = default;

  size_t size() const override {
    return vec_.size();
  }

  uint8_t* data() override {
    return const_cast<uint8_t*>(vec_.data());
  }

private:
  rust::Vec<uint8_t> vec_;
};

} // namespace hwpjs

namespace facebook {
namespace react {

template <>
struct Bridging<std::monostate> {
  static std::monostate fromJs(jsi::Runtime& rt, const jsi::Value &value, std::shared_ptr<CallInvoker> callInvoker) {
    return std::monostate{};
  }

  static jsi::Value toJs(jsi::Runtime& rt, const std::monostate& value) {
    return jsi::Value::undefined();
  }
};

template <>
struct Bridging<rust::Str> {
  static rust::Str fromJs(jsi::Runtime& rt, const jsi::Value &value, std::shared_ptr<CallInvoker> callInvoker) {
    auto str = value.asString(rt).utf8(rt);
    return rust::Str(str.data(), str.size());
  }

  static jsi::Value toJs(jsi::Runtime& rt, const rust::Str& value) {
    return react::bridging::toJs(rt, std::string(value.data(), value.size()));
  }
};

template <>
struct Bridging<rust::String> {
  static rust::String fromJs(jsi::Runtime& rt, const jsi::Value &value, std::shared_ptr<CallInvoker> callInvoker) {
    auto str = value.asString(rt).utf8(rt);
    return rust::String(str.data(), str.size());
  }

  static jsi::Value toJs(jsi::Runtime& rt, const rust::String& value) {
    return react::bridging::toJs(rt, std::string(value.data(), value.size()));
  }
};

template <>
struct Bridging<rust::Vec<uint8_t>> {
  static rust::Vec<uint8_t> fromJs(jsi::Runtime& rt, const jsi::Value &value, std::shared_ptr<CallInvoker> callInvoker) {
    auto arrayBuffer = value.asObject(rt).getArrayBuffer(rt);
    uint8_t* data = arrayBuffer.data(rt);
    size_t size = arrayBuffer.size(rt);
    rust::Vec<uint8_t> vec;
    vec.reserve(size);

    std::memcpy(vec.data(), data, size);

    return vec;
  }

  static jsi::Value toJs(jsi::Runtime& rt, const rust::Vec<uint8_t>& vec) {
    auto buffer = std::make_shared<hwpjs::RustVecBuffer>(std::move(vec));
    return jsi::ArrayBuffer(rt, buffer);
  }
};

template <typename T>
struct Bridging<rust::Vec<T>> {
  static rust::Vec<T> fromJs(jsi::Runtime& rt, const jsi::Value &value, std::shared_ptr<CallInvoker> callInvoker) {
    auto arr = value.asObject(rt).asArray(rt);
    size_t len = arr.length(rt);
    rust::Vec<T> vec;
    vec.reserve(len);

    for (size_t i = 0; i < len; i++) {
      auto element = arr.getValueAtIndex(rt, i);
      vec.push_back(react::bridging::fromJs<T>(rt, element, callInvoker));
    }

    return vec;
  }

  static jsi::Array toJs(jsi::Runtime& rt, const rust::Vec<T>& vec) {
    auto arr = jsi::Array(rt, vec.size());

    for (size_t i = 0; i < vec.size(); i++) {
      auto jsElement = react::bridging::toJs(rt, vec[i]);
      arr.setValueAtIndex(rt, i, jsElement);
    }

    return arr;
  }
};

template <>
struct Bridging<craby::hwpjs::bridging::NullableString> {
  static craby::hwpjs::bridging::NullableString fromJs(jsi::Runtime &rt, const jsi::Value& value, std::shared_ptr<CallInvoker> callInvoker) {
    if (value.isNull()) {
      return craby::hwpjs::bridging::NullableString{true, rust::String()};
    }

    auto val = react::bridging::fromJs<rust::String>(rt, value, callInvoker);
    auto ret = craby::hwpjs::bridging::NullableString{false, val};

    return ret;
  }

  static jsi::Value toJs(jsi::Runtime &rt, craby::hwpjs::bridging::NullableString value) {
    if (value.null) {
      return jsi::Value::null();
    }

    return react::bridging::toJs(rt, value.val);
  }
};

template <>
struct Bridging<craby::hwpjs::bridging::ToMarkdownOptions> {
  static craby::hwpjs::bridging::ToMarkdownOptions fromJs(jsi::Runtime &rt, const jsi::Value& value, std::shared_ptr<CallInvoker> callInvoker) {
    auto obj = value.asObject(rt);
    auto obj$imageOutputDir = obj.getProperty(rt, "imageOutputDir");
    auto obj$image = obj.getProperty(rt, "image");
    auto obj$useHtml = obj.getProperty(rt, "useHtml");
    auto obj$includeVersion = obj.getProperty(rt, "includeVersion");
    auto obj$includePageInfo = obj.getProperty(rt, "includePageInfo");

    auto _obj$imageOutputDir = react::bridging::fromJs<craby::hwpjs::bridging::NullableString>(rt, obj$imageOutputDir, callInvoker);
    auto _obj$image = react::bridging::fromJs<craby::hwpjs::bridging::NullableString>(rt, obj$image, callInvoker);
    auto _obj$useHtml = react::bridging::fromJs<bool>(rt, obj$useHtml, callInvoker);
    auto _obj$includeVersion = react::bridging::fromJs<bool>(rt, obj$includeVersion, callInvoker);
    auto _obj$includePageInfo = react::bridging::fromJs<bool>(rt, obj$includePageInfo, callInvoker);

    craby::hwpjs::bridging::ToMarkdownOptions ret = {
      _obj$imageOutputDir,
      _obj$image,
      _obj$useHtml,
      _obj$includeVersion,
      _obj$includePageInfo
    };

    return ret;
  }

  static jsi::Value toJs(jsi::Runtime &rt, craby::hwpjs::bridging::ToMarkdownOptions value) {
    jsi::Object obj = jsi::Object(rt);
    auto _obj$imageOutputDir = react::bridging::toJs(rt, value.image_output_dir);
    auto _obj$image = react::bridging::toJs(rt, value.image);
    auto _obj$useHtml = react::bridging::toJs(rt, value.use_html);
    auto _obj$includeVersion = react::bridging::toJs(rt, value.include_version);
    auto _obj$includePageInfo = react::bridging::toJs(rt, value.include_page_info);

    obj.setProperty(rt, "imageOutputDir", _obj$imageOutputDir);
    obj.setProperty(rt, "image", _obj$image);
    obj.setProperty(rt, "useHtml", _obj$useHtml);
    obj.setProperty(rt, "includeVersion", _obj$includeVersion);
    obj.setProperty(rt, "includePageInfo", _obj$includePageInfo);

    return jsi::Value(rt, obj);
  }
};

template <>
struct Bridging<craby::hwpjs::bridging::ToMarkdownResult> {
  static craby::hwpjs::bridging::ToMarkdownResult fromJs(jsi::Runtime &rt, const jsi::Value& value, std::shared_ptr<CallInvoker> callInvoker) {
    auto obj = value.asObject(rt);
    auto obj$markdown = obj.getProperty(rt, "markdown");

    auto _obj$markdown = react::bridging::fromJs<rust::String>(rt, obj$markdown, callInvoker);

    craby::hwpjs::bridging::ToMarkdownResult ret = {
      _obj$markdown
    };

    return ret;
  }

  static jsi::Value toJs(jsi::Runtime &rt, craby::hwpjs::bridging::ToMarkdownResult value) {
    jsi::Object obj = jsi::Object(rt);
    auto _obj$markdown = react::bridging::toJs(rt, value.markdown);

    obj.setProperty(rt, "markdown", _obj$markdown);

    return jsi::Value(rt, obj);
  }
};

} // namespace react
} // namespace facebook
