Browse Source

feat: python binder with ShortCode and CommonCode

master
Dnomd343 2 months ago
parent
commit
2ef5f16054
  1. 7
      src/core_ffi/CMakeLists.txt
  2. 51
      src/core_ffi/py_ffi/binder.cc
  3. 76
      src/core_ffi/py_ffi/codec/common_codec.cc
  4. 77
      src/core_ffi/py_ffi/codec/short_code.cc
  5. 39
      src/core_ffi/py_ffi/demo.cc
  6. 81
      src/core_ffi/py_ffi/include/py_codec.h
  7. 21
      src/core_ffi/py_ffi/include/py_exps.h

7
src/core_ffi/CMakeLists.txt

@ -11,7 +11,12 @@ if (KLSK_C_FFI)
endif()
if (KLSK_PYTHON_FFI)
pybind11_add_module(klotski_py py_ffi/demo.cc)
pybind11_add_module(klotski_py
py_ffi/binder.cc
py_ffi/codec/short_code.cc
py_ffi/codec/common_codec.cc
)
target_include_directories(klotski_py PRIVATE py_ffi/include)
target_link_libraries(klotski_py PRIVATE klotski::core)
set_target_properties(klotski_py PROPERTIES OUTPUT_NAME klotski)
endif()

51
src/core_ffi/py_ffi/binder.cc

@ -0,0 +1,51 @@
#include <pybind11/pybind11.h>
// #include <pybind11/stl.h>
// #include <pybind11/operators.h>
#include "py_exps.h"
#include "py_codec.h"
namespace py = pybind11;
using klotski::ffi::PyShortCode;
using klotski::ffi::PyCommonCode;
using klotski::ffi::PyCodecExp;
PYBIND11_MODULE(klotski, m) {
py::register_exception<PyCodecExp>(m, "CodecExp", PyExc_ValueError);
py::class_<PyShortCode>(m, "ShortCode")
.def(py::init<uint32_t>())
.def(py::init<PyCommonCode>())
.def(py::init<std::string_view>())
.def("__str__", &PyShortCode::str)
.def("__repr__", &PyShortCode::repr)
.def_property_readonly("value", &PyShortCode::value)
.def_property_readonly("common_code", &PyShortCode::common_code)
.def_static("check", static_cast<bool (*)(uint32_t)>(&PyShortCode::check))
.def_static("check", static_cast<bool (*)(std::string_view)>(&PyShortCode::check))
.def_static("speed_up", &PyShortCode::speed_up, py::arg("fast_mode") = false);
py::class_<PyCommonCode>(m, "CommonCode")
.def(py::init<uint64_t>())
.def(py::init<PyShortCode>())
.def(py::init<std::string_view>())
.def("__str__", &PyCommonCode::str)
.def("__repr__", &PyCommonCode::repr)
.def_property_readonly("value", &PyCommonCode::value)
.def_property_readonly("short_code", &PyCommonCode::short_code)
.def("string", &PyCommonCode::string, py::arg("shorten") = false)
.def_static("check", static_cast<bool (*)(uint64_t)>(&PyCommonCode::check))
.def_static("check", static_cast<bool (*)(std::string_view)>(&PyCommonCode::check));
m.attr("__version__") = "version field";
}

76
src/core_ffi/py_ffi/codec/common_codec.cc

@ -0,0 +1,76 @@
#include <format>
#include "py_exps.h"
#include "py_codec.h"
using klotski::ffi::PyCodecExp;
using klotski::ffi::PyShortCode;
using klotski::ffi::PyCommonCode;
using klotski::codec::ShortCode;
using klotski::codec::CommonCode;
// ----------------------------------------------------------------------------------------- //
uint64_t PyCommonCode::value() const {
return code_.unwrap();
}
std::string PyCommonCode::string(const bool shorten) const {
return code_.to_string(shorten);
}
PyShortCode PyCommonCode::short_code() const {
return std::bit_cast<PyShortCode>(code_.to_short_code());
}
// ----------------------------------------------------------------------------------------- //
bool PyCommonCode::check(const uint64_t code) {
return CommonCode::check(code);
}
bool PyCommonCode::check(const std::string_view code) {
// TODO: using `std::string_view` in from_string
return CommonCode::from_string(std::string {code}).has_value();
}
// ----------------------------------------------------------------------------------------- //
std::string PyCommonCode::str(const PyCommonCode code) {
return code.string(false);
}
std::string PyCommonCode::repr(const PyCommonCode code) {
return std::format("<klotski.CommonCode 0x{}>", str(code));
}
// ----------------------------------------------------------------------------------------- //
static CommonCode convert(const PyShortCode code) {
return std::bit_cast<ShortCode>(code).to_common_code();
}
static CommonCode convert(const uint64_t code) {
if (CommonCode::check(code)) {
return CommonCode::unsafe_create(code);
}
throw PyCodecExp(std::format("invalid common code -> {}", code));
}
static CommonCode convert(const std::string_view code) {
// TODO: using `std::string_view` in from_string
if (const auto str = CommonCode::from_string(std::string {code})) {
return str.value();
}
throw PyCodecExp(std::format("invalid common code -> `{}`", code));
}
PyCommonCode::PyCommonCode(const uint64_t code) : code_(convert(code)) {}
PyCommonCode::PyCommonCode(const PyShortCode code) : code_(convert(code)) {}
PyCommonCode::PyCommonCode(const std::string_view code) : code_(convert(code)) {}
// ----------------------------------------------------------------------------------------- //

77
src/core_ffi/py_ffi/codec/short_code.cc

@ -0,0 +1,77 @@
#include <format>
#include "py_exps.h"
#include "py_codec.h"
using klotski::ffi::PyCodecExp;
using klotski::ffi::PyShortCode;
using klotski::ffi::PyCommonCode;
using klotski::codec::ShortCode;
using klotski::codec::CommonCode;
// ----------------------------------------------------------------------------------------- //
uint32_t PyShortCode::value() const {
return code_.unwrap();
}
PyCommonCode PyShortCode::common_code() const {
return std::bit_cast<PyCommonCode>(code_.to_common_code());
}
// ----------------------------------------------------------------------------------------- //
bool PyShortCode::check(const uint32_t code) {
return ShortCode::check(code);
}
bool PyShortCode::check(const std::string_view code) {
// TODO: using `std::string_view` in from_string
return ShortCode::from_string(std::string {code}).has_value();
}
void PyShortCode::speed_up(const bool fast_mode) {
ShortCode::speed_up(fast_mode);
}
// ----------------------------------------------------------------------------------------- //
std::string PyShortCode::str(const PyShortCode code) {
return std::bit_cast<ShortCode>(code).to_string();
}
std::string PyShortCode::repr(const PyShortCode code) {
const auto str = code.code_.to_string();
return std::format("<klotski.ShortCode {} @{}>", code.value(), str);
}
// ----------------------------------------------------------------------------------------- //
static ShortCode convert(const PyCommonCode code) {
return std::bit_cast<CommonCode>(code).to_short_code();
}
static ShortCode convert(const uint32_t code) {
if (ShortCode::check(code)) {
return ShortCode::unsafe_create(code);
}
throw PyCodecExp(std::format("invalid short code -> {}", code));
}
static ShortCode convert(const std::string_view code) {
// TODO: using `std::string_view` in from_string
if (const auto str = ShortCode::from_string(std::string {code})) {
return str.value();
}
throw PyCodecExp(std::format("invalid short code -> `{}`", code));
}
PyShortCode::PyShortCode(const uint32_t code) : code_(convert(code)) {}
PyShortCode::PyShortCode(const PyCommonCode code) : code_(convert(code)) {}
PyShortCode::PyShortCode(const std::string_view code) : code_(convert(code)) {}
// ----------------------------------------------------------------------------------------- //

39
src/core_ffi/py_ffi/demo.cc

@ -1,39 +0,0 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <common_code/common_code.h>
namespace py = pybind11;
// class CommonCode {
// public:
// explicit CommonCode(uint64_t val) : value_(val) {}
//
// uint64_t Value() const {
// return value_;
// }
//
// static std::optional<CommonCode> Create(uint64_t val) {
// if (val == 343) {
// return CommonCode {val};
// }
// return std::nullopt;
// }
//
// private:
// uint64_t value_ {343};
// };
using klotski::codec::CommonCode;
PYBIND11_MODULE(klotski, m) {
py::class_<CommonCode>(m, "CommonCode")
// .def(py::init<uint64_t>())
.def("to_string", &CommonCode::to_string, py::arg("shorten") = false)
.def_property_readonly("value", &CommonCode::unwrap)
// .def_static("from_val", &CommonCode::Create);
.def_static("create", &CommonCode::create);
m.attr("__version__") = "version field";
}

81
src/core_ffi/py_ffi/include/py_codec.h

@ -0,0 +1,81 @@
#pragma once
#include "short_code/short_code.h"
#include "common_code/common_code.h"
namespace klotski::ffi {
using codec::ShortCode;
using codec::CommonCode;
class PyCommonCode;
// ------------------------------------------------------------------------------------- //
class PyShortCode {
public:
explicit PyShortCode(uint32_t code);
explicit PyShortCode(PyCommonCode code);
explicit PyShortCode(std::string_view code);
/// Get original value.
[[nodiscard]] uint32_t value() const;
/// Convert ShortCode to CommonCode.
[[nodiscard]] PyCommonCode common_code() const;
/// Verify ShortCode in u32 form.
static bool check(uint32_t code);
/// Verify ShortCode in string form.
static bool check(std::string_view code);
/// Build conversion index for ShortCode.
static void speed_up(bool fast_mode);
/// Wrapper of `__str__` method in Python.
static std::string str(PyShortCode code);
/// Wrapper of `__repr__` method in Python.
static std::string repr(PyShortCode code);
private:
ShortCode code_;
};
// ------------------------------------------------------------------------------------- //
class PyCommonCode {
public:
explicit PyCommonCode(uint64_t code);
explicit PyCommonCode(PyShortCode code);
explicit PyCommonCode(std::string_view code);
/// Get original value.
[[nodiscard]] uint64_t value() const;
/// Convert CommonCode to ShortCode.
[[nodiscard]] PyShortCode short_code() const;
/// Convert as string form.
[[nodiscard]] std::string string(bool shorten) const;
/// Verify CommonCode in u64 form.
static bool check(uint64_t code);
/// Verify CommonCode in string form.
static bool check(std::string_view code);
/// Wrapper of `__str__` method in Python.
static std::string str(PyCommonCode code);
/// Wrapper of `__repr__` method in Python.
static std::string repr(PyCommonCode code);
private:
CommonCode code_;
};
// ------------------------------------------------------------------------------------- //
} // namespace klotski::ffi

21
src/core_ffi/py_ffi/include/py_exps.h

@ -0,0 +1,21 @@
#pragma once
#include <exception>
namespace klotski::ffi {
class PyCodecExp final : std::exception {
public:
explicit PyCodecExp(const std::string_view &msg) : msg_(msg) {}
~PyCodecExp() override = default;
[[nodiscard]] const char* what() const noexcept override {
return msg_.c_str();
}
private:
std::string msg_;
};
} // namespace klotski::ffi
Loading…
Cancel
Save