klotski/
bridge.rs

1#[cxx::bridge(namespace = "klotski::ffi")]
2mod ffi {
3    #[derive(Debug)]
4    struct RsLayout {
5        code: u64
6    }
7
8    #[derive(Debug)]
9    struct RsShortCode {
10        code: u32
11    }
12
13    unsafe extern "C++" {
14        include!("rust_ffi/include/layout.h");
15
16        /// only for internal use
17        fn layout_check(val: u64) -> bool;
18
19        /// only for internal use
20        fn layout_from_str(s: &str) -> u64;
21
22        /// Convert Layout to string form.
23        fn to_string(self: &RsLayout) -> String;
24
25        /// Convert Layout to shorten string form.
26        fn to_shorten_string(self: &RsLayout) -> String;
27
28        /// Convert Layout to ShortCode.
29        fn to_short_code(self: &RsLayout) -> RsShortCode;
30
31        /// Whether the layout is vertically symmetrical.
32        fn is_vertical_mirror(self: &RsLayout) -> bool;
33
34        /// Whether the layout is horizontally symmetrical.
35        fn is_horizontal_mirror(self: &RsLayout) -> bool;
36
37        /// Calculate the vertically symmetrical klotski layout.
38        fn to_vertical_mirror(self: &RsLayout) -> RsLayout;
39
40        /// Calculate the horizontally symmetrical klotski layout.
41        fn to_horizontal_mirror(self: &RsLayout) -> RsLayout;
42
43        /// Obtain number of block 1x1.
44        fn n_1x1(self: &RsLayout) -> u8;
45
46        /// Obtain number of block 1x2.
47        fn n_1x2(self: &RsLayout) -> u8;
48
49        /// Obtain number of block 2x1.
50        fn n_2x1(self: &RsLayout) -> u8;
51
52        /// Obtain number of block 2x2.
53        fn n_2x2(self: &RsLayout) -> u8;
54
55        /// Obtain type_id value of current Layout.
56        fn type_id(self: &RsLayout) -> u8;
57
58        /// Obtain pattern_id value of current Layout.
59        fn pattern_id(self: &RsLayout) -> u16;
60
61        // TODO: add Toward enum for `toward` interface
62
63        // Obtain toward char of current Layout.
64        fn toward_char(self: &RsLayout) -> u8;
65
66        /// Obtain case_id value of current Layout.
67        fn case_id(self: &RsLayout) -> u32;
68
69        /// Obtain all next cases in Layout.
70        fn next_cases(self: &RsLayout) -> Vec<RsLayout>;
71    }
72
73    unsafe extern "C++" {
74        include!("rust_ffi/include/short_code.h");
75
76        /// only for internal use
77        fn short_code_check(val: u32) -> bool;
78
79        /// only for internal use
80        fn short_code_from_str(s: &str) -> u32;
81
82        /// Convert ShortCode to string form.
83        fn to_string(self: &RsShortCode) -> String;
84
85        /// Convert ShortCode to Layout.
86        fn to_layout(self: &RsShortCode) -> RsLayout;
87
88        /// Build the conversion index for ShortCode.
89        fn short_code_speed_up(fast_mode: bool);
90    }
91}
92
93pub use ffi::RsLayout as Layout;
94pub use ffi::RsShortCode as ShortCode;
95
96impl Layout {
97    /// Check the validity of the original Layout.
98    pub fn check(code: u64) -> bool {
99        ffi::layout_check(code)
100    }
101
102    /// Create Layout without any check.
103    pub fn unsafe_create(code: u64) -> Self {
104        Self { code }
105    }
106
107    /// Create Layout with validity check.
108    pub fn create(code: u64) -> Option<Self> {
109        if Self::check(code) {
110            return Some(Self::unsafe_create(code));
111        }
112        None
113    }
114
115    /// Get the original u64 code.
116    pub fn unwrap(self: &Self) -> u64 {
117        self.code
118    }
119
120    /// Create Layout from string form.
121    pub fn from_string(s: &str) -> Option<Self> {
122        let val = ffi::layout_from_str(s);
123        if val < 0x10_FFFF_FFFF {
124            return Some(Self::unsafe_create(val));
125        }
126        None
127    }
128}
129
130impl ShortCode {
131    /// Check the validity of the original ShortCode.
132    pub fn check(code: u32) -> bool {
133        ffi::short_code_check(code)
134    }
135
136    /// Create ShortCode without any check.
137    pub fn unsafe_create(code: u32) -> Self {
138        Self { code }
139    }
140
141    /// Create ShortCode with validity check.
142    pub fn create(code: u32) -> Option<Self> {
143        if Self::check(code) {
144            return Some(Self::unsafe_create(code));
145        }
146        None
147    }
148
149    /// Get the original u32 code.
150    pub fn unwrap(self: &Self) -> u32 {
151        self.code
152    }
153
154    /// Create ShortCode from string form.
155    pub fn from_string(s: &str) -> Option<Self> {
156        let val = ffi::short_code_from_str(s);
157        if val != 0xFFFF_FFFF {
158            return Some(Self::unsafe_create(val));
159        }
160        None
161    }
162
163    pub fn speed_up(fast_mode: bool) {
164        ffi::short_code_speed_up(fast_mode)
165    }
166}
167
168impl PartialEq for Layout {
169    fn eq(&self, other: &Self) -> bool {
170        self.code == other.code
171    }
172}
173
174impl PartialEq for ShortCode {
175    fn eq(&self, other: &Self) -> bool {
176        self.code == other.code
177    }
178}