Browse Source

feat: migrate to native rust structure

master
Dnomd343 1 week ago
parent
commit
cbbfb0f193
  1. 84
      src/core_ffi/rust_ffi/adapter/layout.cc
  2. 30
      src/core_ffi/rust_ffi/examples/demo.rs
  3. 30
      src/core_ffi/rust_ffi/include/interface.h
  4. 32
      src/core_ffi/rust_ffi/src/bridge.rs
  5. 153
      src/core_ffi/rust_ffi/src/layout.rs
  6. 11
      src/core_ffi/rust_ffi/src/lib.rs
  7. 23
      src/core_ffi/rust_ffi/src/short_code.rs

84
src/core_ffi/rust_ffi/adapter/layout.cc

@ -30,6 +30,90 @@ bool klotski::ffi::layout_check(const uint64_t val) {
return CommonCode::check(val);
}
rust::String klotski::ffi::layout_to_str(uint64_t val) {
const auto layout = RsLayout {val};
return layout.to_string();
}
rust::String klotski::ffi::layout_to_shorten_str(uint64_t val) {
const auto layout = RsLayout {val};
return layout.to_shorten_string();
}
uint32_t klotski::ffi::layout_to_short_code(uint64_t val) {
const auto layout = RsLayout {val};
return layout.to_short_code().code;
}
bool klotski::ffi::layout_is_horizontal_mirror(uint64_t val) {
const auto layout = RsLayout {val};
return layout.is_horizontal_mirror();
}
bool klotski::ffi::layout_is_vertical_mirror(uint64_t val) {
const auto layout = RsLayout {val};
return layout.is_vertical_mirror();
}
uint64_t klotski::ffi::layout_to_horizontal_mirror(uint64_t val) {
const auto layout = RsLayout {val};
return layout.to_horizontal_mirror().code;
}
uint64_t klotski::ffi::layout_to_vertical_mirror(uint64_t val) {
const auto layout = RsLayout {val};
return layout.to_vertical_mirror().code;
}
uint8_t klotski::ffi::layout_n_1x1(uint64_t val) {
const auto layout = RsLayout {val};
return layout.n_1x1();
}
uint8_t klotski::ffi::layout_n_1x2(uint64_t val) {
const auto layout = RsLayout {val};
return layout.n_1x2();
}
uint8_t klotski::ffi::layout_n_2x1(uint64_t val) {
const auto layout = RsLayout {val};
return layout.n_2x1();
}
uint8_t klotski::ffi::layout_type_id(uint64_t val) {
const auto layout = RsLayout {val};
return layout.type_id();
}
uint16_t klotski::ffi::layout_pattern_id(uint64_t val) {
const auto layout = RsLayout {val};
return layout.pattern_id();
}
uint8_t klotski::ffi::layout_toward_char(uint64_t val) {
const auto layout = RsLayout {val};
return layout.toward_char();
}
uint32_t klotski::ffi::layout_case_id(uint64_t val) {
const auto layout = RsLayout {val};
return layout.case_id();
}
rust::Vec<uint64_t> klotski::ffi::layout_next_cases(uint64_t val) {
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(val).to_raw_code(), 0);
rust::Vec<uint64_t> vec;
for (auto x : result) {
vec.emplace_back(x.unwrap());
}
return vec;
}
rust::String RsLayout::to_string() const noexcept {
return CommonCode::unsafe_create(code).to_string();
}

30
src/core_ffi/rust_ffi/examples/demo.rs

@ -2,25 +2,25 @@ use klotski::Layout;
use klotski::ShortCode;
fn short_code_demo() {
ShortCode::speed_up(false);
ShortCode::speed_up(true);
assert!(ShortCode::check(4091296));
let code = ShortCode::create(4091296).unwrap();
assert_eq!(code, ShortCode::from_string("4WVE1").unwrap());
assert_eq!(code, ShortCode::create(4091296).unwrap());
println!("code: {:?}", code.unwrap());
println!("string: {}", code.to_string());
println!("layout: {:?}", code.to_layout());
// ShortCode::speed_up(false);
// ShortCode::speed_up(true);
//
// assert!(ShortCode::check(4091296));
// let code = ShortCode::create(4091296).unwrap();
// assert_eq!(code, ShortCode::from_string("4WVE1").unwrap());
// assert_eq!(code, ShortCode::create(4091296).unwrap());
//
// println!("code: {:?}", code.unwrap());
// println!("string: {}", code.to_string());
//
// println!("layout: {:?}", code.to_layout());
}
fn layout_demo() {
assert!(Layout::check(0x1A9BF0C00));
let code = Layout::create(0x1A9BF0C00).unwrap();
assert_eq!(code, Layout::from_string("1A9BF0C").unwrap());
assert_eq!(code, Layout::create(0x1A9BF0C00).unwrap());
let code = Layout::new(0x1A9BF0C00).unwrap();
assert_eq!(code, Layout::from_str("1A9BF0C").unwrap());
assert_eq!(code, Layout::new(0x1A9BF0C00).unwrap());
println!("code: {:?}", code.unwrap());

30
src/core_ffi/rust_ffi/include/interface.h

@ -14,4 +14,34 @@ uint64_t layout_from_str(rust::Str s);
void short_code_speed_up(bool fast_mode);
rust::String layout_to_str(uint64_t val);
rust::String layout_to_shorten_str(uint64_t val);
uint32_t layout_to_short_code(uint64_t val);
bool layout_is_horizontal_mirror(uint64_t val);
bool layout_is_vertical_mirror(uint64_t val);
uint64_t layout_to_horizontal_mirror(uint64_t val);
uint64_t layout_to_vertical_mirror(uint64_t val);
uint8_t layout_n_1x1(uint64_t val);
uint8_t layout_n_1x2(uint64_t val);
uint8_t layout_n_2x1(uint64_t val);
uint8_t layout_type_id(uint64_t val);
uint16_t layout_pattern_id(uint64_t val);
uint8_t layout_toward_char(uint64_t val);
uint32_t layout_case_id(uint64_t val);
rust::Vec<uint64_t> layout_next_cases(uint64_t val);
} // namespace klotski::ffi

32
src/core_ffi/rust_ffi/src/bridge.rs

@ -1,5 +1,5 @@
#[cxx::bridge(namespace = "klotski::ffi")]
mod ffi {
pub(crate) mod ffi {
#[derive(Debug)]
struct RsLayout {
code: u64
@ -19,6 +19,36 @@ mod ffi {
/// only for internal use
fn layout_from_str(s: &str) -> u64;
fn layout_to_str(val: u64) -> String;
fn layout_to_shorten_str(val: u64) -> String;
fn layout_to_short_code(val: u64) -> u32;
fn layout_is_horizontal_mirror(val: u64) -> bool;
fn layout_is_vertical_mirror(val: u64) -> bool;
fn layout_to_horizontal_mirror(val: u64) -> u64;
fn layout_to_vertical_mirror(val: u64) -> u64;
fn layout_n_1x1(val: u64) -> u8;
fn layout_n_1x2(val: u64) -> u8;
fn layout_n_2x1(val: u64) -> u8;
fn layout_type_id(val: u64) -> u8;
fn layout_pattern_id(val: u64) -> u16;
fn layout_toward_char(val: u64) -> u8;
fn layout_case_id(val: u64) -> u32;
fn layout_next_cases(val: u64) -> Vec<u64>;
/// Convert Layout to string form.
fn to_string(self: &RsLayout) -> String;

153
src/core_ffi/rust_ffi/src/layout.rs

@ -0,0 +1,153 @@
use crate::ffi;
use crate::ShortCode;
/// Layout represents a valid klotski situation, which fills single `2x2` block
/// and any number of `1x1` / `1x2` / `2x1` blocks without overlapping within
/// the range of `5x4`, and ensures that at least two spaces need to remain.
/// These layout information will be stored in a 36-bit value (u64), which can
/// uniquely mark a valid klotski situation, and any valid situation can also
/// be represented by a unique value.
#[derive(Debug)]
pub struct Layout {
value: u64
}
impl Layout {
/// Check whether the klotski layout value is a valid.
pub fn check(val: u64) -> bool {
ffi::layout_check(val)
}
/// Create klotski layout without any check. Note that if an invalid value
/// is passed, unpredictable behavior may occur.
pub fn unsafe_new(val: u64) -> Self {
Self { value: val }
}
/// Create klotski layout with validity check.
pub fn new(val: u64) -> Option<Self> {
if !Self::check(val) {
return None
}
Some(Self::unsafe_new(val))
}
/// Create klotski layout from string form.
pub fn from_str(msg: &str) -> Option<Self> {
let val = ffi::layout_from_str(msg);
if val == 0x10_FFFF_FFFF {
return None;
}
Some(Self::unsafe_new(val))
}
}
impl Layout {
/// Get the original value of klotski layout.
pub fn unwrap(&self) -> u64 {
self.value
}
pub fn to_string(&self) -> String {
ffi::layout_to_str(self.value)
}
pub fn to_shorten_string(&self) -> String {
ffi::layout_to_shorten_str(self.value)
}
pub fn to_short_code(&self) -> ShortCode {
ShortCode::unsafe_new(ffi::layout_to_short_code(self.value))
}
}
impl Into<u64> for Layout {
fn into(self) -> u64 {
self.unwrap()
}
}
impl Into<String> for Layout {
fn into(self) -> String {
self.to_string()
}
}
impl Into<ShortCode> for Layout {
fn into(self) -> ShortCode {
self.to_short_code()
}
}
impl Layout {
pub fn is_horizontal_mirror(&self) -> bool {
ffi::layout_is_horizontal_mirror(self.value)
}
pub fn is_vertical_mirror(&self) -> bool {
ffi::layout_is_vertical_mirror(self.value)
}
pub fn to_vertical_mirror(&self) -> Layout {
let val = ffi::layout_to_vertical_mirror(self.value);
Layout::unsafe_new(val)
}
pub fn to_horizontal_mirror(&self) -> Layout {
let val = ffi::layout_to_horizontal_mirror(self.value);
Layout::unsafe_new(val)
}
}
impl Layout {
pub fn n_1x1(&self) -> u8 {
ffi::layout_n_1x1(self.value)
}
pub fn n_1x2(&self) -> u8 {
ffi::layout_n_1x2(self.value)
}
pub fn n_2x1(&self) -> u8 {
ffi::layout_n_2x1(self.value)
}
pub fn n_2x2(&self) -> u8 {
1
}
}
impl Layout {
pub fn type_id(&self) -> u8 {
ffi::layout_type_id(self.value)
}
pub fn pattern_id(&self) -> u16 {
ffi::layout_pattern_id(self.value)
}
pub fn toward_char(&self) -> u8 {
ffi::layout_toward_char(self.value)
}
pub fn case_id(&self) -> u32 {
ffi::layout_case_id(self.value)
}
}
impl Layout {
pub fn next_cases(&self) -> Vec<Layout> {
ffi::layout_next_cases(self.value)
.iter()
.map(|val| Layout::unsafe_new(*val))
.collect()
}
}
impl PartialEq for Layout {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
// TODO: add `Display` trait support

11
src/core_ffi/rust_ffi/src/lib.rs

@ -1,4 +1,11 @@
mod bridge;
mod layout;
mod short_code;
pub use bridge::Layout;
pub use bridge::ShortCode;
// pub use bridge::Layout;
// pub use bridge::ShortCode;
use bridge::ffi;
pub use layout::Layout;
pub use short_code::ShortCode;

23
src/core_ffi/rust_ffi/src/short_code.rs

@ -0,0 +1,23 @@
use crate::ffi;
#[derive(Debug)]
pub struct ShortCode {
code: u32
}
impl ShortCode {
// fn new(code: u32) -> Option<ShortCode> {
// if !Self::check(code) {
// return None
// }
// Some(Self::unsafe_new(code))
// }
pub fn unsafe_new(code: u32) -> ShortCode {
Self {code}
}
fn check(code: u32) -> bool {
ffi::short_code_check(code)
}
}
Loading…
Cancel
Save