Browse Source

feat: more interfaces of `RsCommonCode`

master
Dnomd343 1 month ago
parent
commit
7efd8ef352
  1. 63
      src/core_ffi/rust_ffi/adapter/common_code.cc
  2. 4
      src/core_ffi/rust_ffi/build.rs
  3. 4
      src/core_ffi/rust_ffi/include/common_code.h
  4. 74
      src/core_ffi/rust_ffi/src/common_code.rs
  5. 20
      src/core_ffi/rust_ffi/src/main.rs

63
src/core_ffi/rust_ffi/adapter/common_code.cc

@ -1,15 +1,68 @@
#include "rust_ffi/include/common_code.h" #include "rust_ffi/include/common_code.h"
#include <mover/mover.h>
#include <common_code/common_code.h> #include <common_code/common_code.h>
using klotski::codec::RawCode;
using klotski::codec::ShortCode;
using klotski::codec::CommonCode;
using klotski::mover::MaskMover;
using klotski::ffi::RsShortCode;
using klotski::ffi::RsCommonCode; using klotski::ffi::RsCommonCode;
// TODO: it seems that cxx.rs not support `std::optional`
uint64_t klotski::ffi::common_code_from_str(rust::Str s) {
std::string_view sv {s.data(), s.length()};
if (const auto ret = CommonCode::from_string(sv); ret.has_value()) {
return ret.value().unwrap();
}
return 0x10FFFFFFFF; // return invalid value for now
}
bool klotski::ffi::common_code_check(uint64_t val) {
return CommonCode::check(val);
}
rust::String RsCommonCode::to_string() const noexcept { rust::String RsCommonCode::to_string() const noexcept {
return codec::CommonCode::unsafe_create(code).to_string(); return CommonCode::unsafe_create(code).to_string();
} }
// TODO: it seems that cxx.rs not support `std::optional` rust::String RsCommonCode::to_shorten_string() const noexcept {
RsCommonCode klotski::ffi::from_string(rust::Str s) { return CommonCode::unsafe_create(code).to_string(true);
std::string_view sv {s.data(), s.length()}; }
return {codec::CommonCode::from_string(sv)->unwrap()}; // TODO: value check
RsShortCode RsCommonCode::to_short_code() const noexcept {
return {CommonCode::unsafe_create(code).to_short_code().unwrap()};
}
bool RsCommonCode::is_vertical_mirror() const noexcept {
return CommonCode::unsafe_create(code).is_vertical_mirror();
}
bool RsCommonCode::is_horizontal_mirror() const noexcept {
return CommonCode::unsafe_create(code).is_horizontal_mirror();
}
RsCommonCode RsCommonCode::to_vertical_mirror() const noexcept {
return {CommonCode::unsafe_create(code).to_vertical_mirror().unwrap()};
}
RsCommonCode RsCommonCode::to_horizontal_mirror() const noexcept {
return {CommonCode::unsafe_create(code).to_horizontal_mirror().unwrap()};
}
rust::Vec<RsCommonCode> RsCommonCode::next_cases() const noexcept {
std::vector<CommonCode> result;
auto mover = MaskMover([&result](const RawCode code, uint64_t) {
result.emplace_back(code.to_common_code());
});
mover.next_cases(CommonCode::unsafe_create(code).to_raw_code(), 0);
rust::Vec<RsCommonCode> vec;
for (auto x : result) {
vec.emplace_back(RsCommonCode(x.unwrap()));
}
return vec;
} }

4
src/core_ffi/rust_ffi/build.rs

@ -5,10 +5,12 @@ use cxx_build::CFG;
// NOTE: add `CC=clang-20 CXX=clang++-20 CXXFLAGS="-stdlib=libc++"` for cargo command // NOTE: add `CC=clang-20 CXX=clang++-20 CXXFLAGS="-stdlib=libc++"` for cargo command
// we should keep cxx crate using clang for `cxx.cc` // we should keep cxx crate using clang for `cxx.cc`
// NOTE: also, `RUSTFLAGS="-C linker=clang-20"` should be add to cargo env for using lld // NOTE: also, `RUSTFLAGS="-C linker=clang-20"` should be added to cargo env for using lld
// NOTE: add `CC=clang-20 CXX=clang++-20 CXXFLAGS="-stdlib=libc++" RUSTFLAGS="-C linker=clang-20 -C link-arg=-fuse-ld=lld-20 -C link-arg=-stdlib=libc++"` for using llvm toolchain // NOTE: add `CC=clang-20 CXX=clang++-20 CXXFLAGS="-stdlib=libc++" RUSTFLAGS="-C linker=clang-20 -C link-arg=-fuse-ld=lld-20 -C link-arg=-stdlib=libc++"` for using llvm toolchain
// NOTE: it seems that cxx_build link `libstdc++` on linux, we can add `-C link-arg=-lc++ -C link-arg=-lc++abi` for workaround, but it should be fixed in the future.
fn main() { fn main() {
let dst = cmake::Config::new("klotski") let dst = cmake::Config::new("klotski")
// .build_target("klotski_core") // .build_target("klotski_core")

4
src/core_ffi/rust_ffi/include/common_code.h

@ -4,6 +4,8 @@
namespace klotski::ffi { namespace klotski::ffi {
RsCommonCode from_string(rust::Str s); bool common_code_check(uint64_t val);
uint64_t common_code_from_str(rust::Str s);
} // namespace klotski::ffi } // namespace klotski::ffi

74
src/core_ffi/rust_ffi/src/common_code.rs

@ -2,31 +2,91 @@
mod ffi { mod ffi {
#[derive(Debug)] #[derive(Debug)]
struct RsCommonCode { struct RsCommonCode {
code: u64 code: u64,
}
#[derive(Debug)]
struct RsShortCode {
code: u32,
} }
unsafe extern "C++" { unsafe extern "C++" {
include!("rust_ffi/include/common_code.h"); include!("rust_ffi/include/common_code.h");
/// only for internal use
fn common_code_check(val: u64) -> bool;
/// only for internal use
fn common_code_from_str(s: &str) -> u64;
/// Convert CommonCode to string form.
fn to_string(self: &RsCommonCode) -> String; fn to_string(self: &RsCommonCode) -> String;
fn from_string(s: &str) -> RsCommonCode; /// Convert CommonCode to shorten string form.
fn to_shorten_string(self: &RsCommonCode) -> String;
/// Convert CommonCode to ShortCode.
fn to_short_code(self: &RsCommonCode) -> RsShortCode;
/// Whether the layout is vertically symmetrical.
fn is_vertical_mirror(self: &RsCommonCode) -> bool;
/// Whether the layout is horizontally symmetrical.
fn is_horizontal_mirror(self: &RsCommonCode) -> bool;
/// Calculate the vertically symmetrical klotski layout.
fn to_vertical_mirror(self: &RsCommonCode) -> RsCommonCode;
/// Calculate the horizontally symmetrical klotski layout.
fn to_horizontal_mirror(self: &RsCommonCode) -> RsCommonCode;
/// Obtain all next cases in CommonCode.
fn next_cases(self: &RsCommonCode) -> Vec<RsCommonCode>;
}
unsafe extern "C++" {
// include!("rust_ffi/include/short_code.h");
// fn short_code_from_str(s: &str) -> RsShortCode;
// TODO: speed_up interface
} }
} }
pub use ffi::RsShortCode as ShortCode;
pub use ffi::RsCommonCode as CommonCode; pub use ffi::RsCommonCode as CommonCode;
impl CommonCode { impl CommonCode {
/// Check the validity of the original CommonCode.
pub fn check(code: u64) -> bool {
ffi::common_code_check(code)
}
/// Create CommonCode without any check.
pub fn unsafe_create(code: u64) -> CommonCode { pub fn unsafe_create(code: u64) -> CommonCode {
CommonCode { code } CommonCode { code }
} }
/// Create CommonCode with validity check.
pub fn create(code: u64) -> Option<CommonCode> {
if Self::check(code) {
return Some(Self::unsafe_create(code));
}
None
}
/// Get the original u64 code.
pub fn unwrap(self: &CommonCode) -> u64 { pub fn unwrap(self: &CommonCode) -> u64 {
self.code self.code
} }
pub fn from_string(s: &str) -> CommonCode { /// Create CommonCode from string form.
ffi::from_string(s) pub fn from_string(s: &str) -> Option<CommonCode> {
let val = ffi::common_code_from_str(s);
if val < 0x10_FFFF_FFFF {
return Some(Self::unsafe_create(val));
}
None
} }
} }
@ -35,3 +95,9 @@ impl PartialEq for CommonCode {
self.code == other.code self.code == other.code
} }
} }
impl PartialEq for ShortCode {
fn eq(&self, other: &Self) -> bool {
self.code == other.code
}
}

20
src/core_ffi/rust_ffi/src/main.rs

@ -3,9 +3,23 @@ mod common_code;
use common_code::CommonCode; use common_code::CommonCode;
fn main() { fn main() {
let code = CommonCode::from_string("1A9BF0C"); assert!(CommonCode::check(0x1A9BF0C00));
let code = CommonCode::create(0x1A9BF0C00).unwrap();
assert_eq!(code, CommonCode::from_string("1A9BF0C").unwrap());
assert_eq!(code, CommonCode::create(0x1A9BF0C00).unwrap());
println!("code: {:?}", code.unwrap()); println!("code: {:?}", code.unwrap());
println!("str: {}", code.to_string());
println!("{}", code == CommonCode::unsafe_create(0x1A9BF0C00)); println!("string: {}", code.to_string());
println!("shorten_string: {}", code.to_shorten_string());
println!("short_code: {:?}", code.to_short_code());
println!("is_vertical_mirror: {}", code.is_vertical_mirror());
println!("is_horizontal_mirror: {}", code.is_horizontal_mirror());
println!("vertical_mirror: {:?}", code.to_vertical_mirror());
println!("horizontal_mirror: {:?}", code.to_horizontal_mirror());
println!("next_cases: {:?}", code.next_cases());
} }

Loading…
Cancel
Save