├── tests ├── test_a.h ├── test_b.h ├── main.cpp ├── test_a.cpp ├── CMakeLists.txt └── test_b.cpp ├── src ├── lib.rs ├── lib.cpp ├── ffi.rs ├── CMakeLists.txt ├── cxxbridge.rs └── _cxxbridge.cpp ├── .gitignore ├── include ├── CMakeLists.txt ├── mmscenegraph.h ├── mmscenegraph │ ├── symbol_export.h │ ├── _cbindgen.h │ ├── _cpp.h │ └── _cxxbridge.h └── cxx.h ├── Cargo.toml ├── CMakeLists.txt ├── cmake └── modules │ └── CxxDemoExampleUtils.cmake ├── output_gcc_6_3_1.log ├── README.md ├── output_msvc_19_0_24215_1.log ├── LICENSE └── cbindgen.toml /tests/test_a.h: -------------------------------------------------------------------------------- 1 | int test_a(); 2 | -------------------------------------------------------------------------------- /tests/test_b.h: -------------------------------------------------------------------------------- 1 | int test_b(); 2 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod ffi; 2 | pub mod cxxbridge; 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /target 3 | /build_linux 4 | /build_windows 5 | /install 6 | /cmake-build-* 7 | **/*.rs.bk 8 | Cargo.lock 9 | *~ 10 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Install C++ Headers, with bindings to Rust library. 2 | # 3 | 4 | install(DIRECTORY 5 | include/ 6 | DESTINATION "include" 7 | FILES_MATCHING PATTERN "*.h") 8 | -------------------------------------------------------------------------------- /include/mmscenegraph.h: -------------------------------------------------------------------------------- 1 | #ifndef MMSCENEGRAPH_H 2 | #define MMSCENEGRAPH_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #endif // MMSCENEGRAPH_H 10 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "test_a.h" 3 | #include "test_b.h" 4 | 5 | int main() { 6 | std::cout << "---- Start Testing..." << std::endl; 7 | 8 | int x = 2 + 2; 9 | std::cout << "2 + 2 = " << x << std::endl; 10 | 11 | // Run tests. 12 | test_a(); 13 | test_b(); 14 | 15 | std::cout << "---- Finished Testing!" << std::endl; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /tests/test_a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace mmsg = mmscenegraph; 5 | 6 | int test_a() { 7 | std::cout << "---- Start Test A..." << std::endl; 8 | 9 | int scene_id = 42; 10 | mmsg::SceneGraph *scene_graph = mmsg::scene_graph_new(scene_id); 11 | mmsg::scene_graph_delete(scene_graph); 12 | 13 | std::cout << "---- Finished Test A!" << std::endl; 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /include/mmscenegraph/symbol_export.h: -------------------------------------------------------------------------------- 1 | #ifndef MMSCENEGRAPH_SYMBOL_EXPORT_H 2 | #define MMSCENEGRAPH_SYMBOL_EXPORT_H 3 | 4 | // Cross-platform symbol visibility macro. 5 | #if defined(_MSC_VER) 6 | #define MMSCENEGRAPH_SYMBOL_EXPORT __declspec(dllexport) 7 | #elif defined(__GNUC__) 8 | #define MMSCENEGRAPH_SYMBOL_EXPORT __attribute__((visibility("default"))) 9 | #else 10 | #define MMSCENEGRAPH_SYMBOL_EXPORT 11 | #endif 12 | 13 | #endif // MMSCENEGRAPH_SYMBOL_EXPORT_H 14 | -------------------------------------------------------------------------------- /src/lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace mmscenegraph { 5 | 6 | ThingC::ThingC(std::string appname) : appname(std::move(appname)) {} 7 | 8 | ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; } 9 | 10 | std::unique_ptr make_demo(rust::Str appname) { 11 | return std::unique_ptr(new ThingC(std::string(appname))); 12 | } 13 | 14 | const std::string &get_name(const ThingC &thing) { return thing.appname; } 15 | 16 | void do_thing(SharedThing state) { print_r(*state.y); } 17 | 18 | } // namespace mmscenegraph 19 | -------------------------------------------------------------------------------- /include/mmscenegraph/_cbindgen.h: -------------------------------------------------------------------------------- 1 | #ifndef MMSCENEGRAPH_CBINDGEN_H 2 | #define MMSCENEGRAPH_CBINDGEN_H 3 | 4 | /* Generated with cbindgen:0.16.0 */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "symbol_export.h" 12 | 13 | namespace mmscenegraph { 14 | 15 | /// The Scene Graph. 16 | struct SceneGraph { 17 | int id; 18 | }; 19 | 20 | extern "C" { 21 | 22 | MMSCENEGRAPH_SYMBOL_EXPORT SceneGraph *scene_graph_new(int id); 23 | 24 | MMSCENEGRAPH_SYMBOL_EXPORT void scene_graph_delete(SceneGraph *scene_graph_ptr); 25 | 26 | } // extern "C" 27 | 28 | } // namespace mmscenegraph 29 | 30 | #endif // MMSCENEGRAPH_CBINDGEN_H 31 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mmscenegraph-rs" 3 | version = "0.1.0" 4 | authors = ["David Cattermole "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [lib] 9 | name = "mmscenegraph_rs" 10 | path = "./src/lib.rs" 11 | # NOTE: 'lib' is used to link with Rust crates, 'staticlib' is used to 12 | # link with C++. 13 | crate_type = ["staticlib"] 14 | 15 | [dependencies] 16 | cxx = "=1.0.26" 17 | libc = "0.2.0" 18 | 19 | [profile.release] 20 | opt-level = 3 21 | debug = false 22 | rpath = false 23 | lto = true 24 | # NOTE: If we use 'panic = "abort"' then we are unable to produce tests. 25 | # # https://github.com/rust-lang/cargo/issues/6313 26 | # 27 | # panic = "abort" 28 | debug-assertions = false 29 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Integration Test files. 2 | # 3 | # This explains how to use the library in a executable. 4 | # 5 | 6 | include(CxxDemoExampleUtils) 7 | 8 | # Add C++ test executable 9 | add_executable(${target_test_exe} 10 | main.cpp 11 | test_a.cpp 12 | test_b.cpp) 13 | target_link_libraries(${target_test_exe} ${target_lib}) 14 | target_include_directories(${target_test_exe} 15 | PUBLIC ${CMAKE_SOURCE_DIR}/include 16 | PRIVATE ${CMAKE_SOURCE_DIR}/src 17 | ) 18 | # Required for Linux, not needed for MS Windows. 19 | set_relative_library_rpath(${target_test_exe} "../lib/") 20 | 21 | install(FILES 22 | DESTINATION "bin") 23 | install( 24 | TARGETS 25 | ${target_test_exe} 26 | ARCHIVE DESTINATION "lib" 27 | LIBRARY DESTINATION "lib" 28 | RUNTIME DESTINATION "bin") 29 | -------------------------------------------------------------------------------- /include/mmscenegraph/_cpp.h: -------------------------------------------------------------------------------- 1 | #ifndef MMSCENEGRAPH_CPP_H 2 | #define MMSCENEGRAPH_CPP_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "symbol_export.h" 8 | 9 | namespace mmscenegraph { 10 | 11 | class ThingC { 12 | public: 13 | MMSCENEGRAPH_SYMBOL_EXPORT 14 | ThingC(std::string appname); 15 | 16 | MMSCENEGRAPH_SYMBOL_EXPORT 17 | ~ThingC(); 18 | 19 | std::string appname; 20 | }; 21 | 22 | struct SharedThing; 23 | 24 | MMSCENEGRAPH_SYMBOL_EXPORT 25 | std::unique_ptr make_demo(rust::Str appname); 26 | 27 | MMSCENEGRAPH_SYMBOL_EXPORT 28 | const std::string &get_name(const ThingC &thing); 29 | 30 | MMSCENEGRAPH_SYMBOL_EXPORT 31 | void do_thing(SharedThing state); 32 | 33 | } // namespace mmscenegraph 34 | 35 | #endif // MMSCENEGRAPH_CPP_H 36 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.0) 2 | 3 | # Project configuration. 4 | project(mmscenegraph) 5 | set(PROJECT_VERSION_MAJOR 0) 6 | set(PROJECT_VERSION_MINOR 1) 7 | set(PROJECT_VERSION_PATCH 0) 8 | set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") 9 | set(PROJECT_HOMEPAGE_URL "https://github.com/david-cattermole/cxx-demo-example") 10 | set(PROJECT_DESCRIPTION "Demo project for the cxx rust crate.") 11 | set(PROJECT_AUTHOR "David Cattermole") 12 | set(PROJECT_COPYRIGHT "2020, David Cattermole.") 13 | 14 | 15 | # Static build information. 16 | set(target_lib "mmscenegraph") 17 | set(target_test_exe "mmscenegraph_tests") 18 | 19 | 20 | # Add custom modules to the module path 21 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) 22 | include(CxxDemoExampleUtils) 23 | 24 | set_cxx_standard_cpp_11() 25 | 26 | add_subdirectory(src) 27 | add_subdirectory(include) 28 | add_subdirectory(tests) 29 | -------------------------------------------------------------------------------- /src/ffi.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | #![allow(non_camel_case_types)] 3 | #![allow(non_snake_case)] 4 | #![allow(dead_code)] 5 | #![allow(unused_imports)] 6 | #![allow(unused_variables)] 7 | 8 | extern crate libc; 9 | 10 | use libc::c_char; 11 | use libc::c_float; 12 | use libc::c_int; 13 | use libc::c_uchar; 14 | use std::ffi::{CStr, CString}; 15 | use std::ptr; 16 | 17 | /// The Scene Graph. 18 | #[repr(C)] 19 | pub struct SceneGraph { 20 | id: c_int, 21 | } 22 | 23 | /// cbindgen:prefix=MMSCENEGRAPH_SYMBOL_EXPORT 24 | #[no_mangle] 25 | pub extern "C" fn scene_graph_new(id: c_int) -> *mut SceneGraph { 26 | println!("SCENEGRAPH: Add SceneGraph {:?}", id); 27 | let scene_graph = Box::new(SceneGraph { id }); 28 | Box::into_raw(scene_graph) 29 | } 30 | 31 | /// cbindgen:prefix=MMSCENEGRAPH_SYMBOL_EXPORT 32 | #[no_mangle] 33 | pub extern "C" fn scene_graph_delete(scene_graph_ptr: *mut SceneGraph) { 34 | println!("SCENEGRAPH: Remove SceneGraph {:?}", scene_graph_ptr); 35 | if scene_graph_ptr.is_null() { 36 | return; 37 | } 38 | unsafe { 39 | // Brings scene_graph_ptr into scope and then forces Rust to deallocate it 40 | // when it falls out of the function scope. 41 | Box::from_raw(scene_graph_ptr); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/test_b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "mmscenegraph.h" 4 | 5 | namespace mmsg = mmscenegraph; 6 | 7 | void read_write_buffer() { 8 | // Allocate C++ memory and pass it to Rust to be filled. 9 | std::vector buffer; 10 | buffer.reserve(42); 11 | rust::Slice slice_of_buffer(buffer.data(), buffer.capacity()); 12 | mmsg::geom::read(slice_of_buffer); 13 | 14 | // Now print the buffer contents out (inside Rust). 15 | rust::Slice const_slice_of_buffer(buffer.data(), buffer.capacity()); 16 | mmsg::geom::write(const_slice_of_buffer); 17 | } 18 | 19 | int test_b() { 20 | std::cout << "---- Start Test B..." << std::endl; 21 | 22 | auto app_name = std::string("my awesome demo"); 23 | auto x = mmsg::make_demo(app_name); 24 | auto name = mmsg::get_name(*x); 25 | std::cout << name << std::endl; 26 | 27 | auto read_op = mmsg::new_read_operation(42, 42); 28 | auto read_op_id = read_op->get_id(); 29 | auto read_op_num = read_op->get_num(); 30 | std::cout << "Read Op Id: " << read_op_id << std::endl; 31 | std::cout << "Read Op Num: " << read_op_num << std::endl; 32 | 33 | auto write_op = mmsg::new_write_operation(42, 42); 34 | auto write_op_id = write_op->get_id(); 35 | auto write_op_num = write_op->get_num(); 36 | std::cout << "Write Op Id: " << write_op_id << std::endl; 37 | std::cout << "Write Op Num: " << write_op_num << std::endl; 38 | 39 | read_write_buffer(); 40 | 41 | std::cout << "---- Finished Test B!" << std::endl; 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /cmake/modules/CxxDemoExampleUtils.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Enable c++11 3 | macro(set_cxx_standard_cpp_11) 4 | if (CMAKE_VERSION VERSION_LESS "3.1") 5 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 6 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 7 | endif () 8 | else () 9 | set (CMAKE_CXX_STANDARD 11) 10 | endif () 11 | endmacro() 12 | 13 | 14 | # Find the Rust compiled library 15 | function(find_rust_library lib_name build_dir out_linktime_file) 16 | if (MSVC) 17 | set(staticlib_name "${lib_name}.lib") 18 | 19 | # Get the Rust Library .lib (for Windows). 20 | message(STATUS "Finding: ${staticlib_name}") 21 | message(DEBUG "RUST BUILD DIR: ${build_dir}") 22 | find_path(linktime_dir ${staticlib_name} 23 | HINTS ${build_dir} 24 | PATHS ${build_dir} 25 | ) 26 | if(EXISTS ${linktime_dir}) 27 | set(${out_linktime_file} ${linktime_dir}/${staticlib_name} PARENT_SCOPE) 28 | endif() 29 | 30 | elseif (UNIX) 31 | set(archive_name "lib${lib_name}.a") 32 | 33 | # Get the Rust Library .a (for Linux). 34 | message(STATUS "Finding: ${archive_name}") 35 | message(DEBUG "RUST BUILD DIR: ${build_dir}") 36 | find_path(linktime_dir ${archive_name} 37 | HINTS ${build_dir} 38 | PATHS ${build_dir} 39 | ) 40 | if(EXISTS ${linktime_dir}) 41 | set(${out_linktime_file} ${linktime_dir}/${archive_name} PARENT_SCOPE) 42 | endif() 43 | 44 | else () 45 | message(FATAL_ERROR "Only Linux and Windows are supported.") 46 | endif () 47 | endfunction() 48 | 49 | 50 | macro(set_relative_library_rpath target relative_path) 51 | # HACK: We must change the RPATH variable for the library so that a 52 | # binary can find the shared object, even if it's not in the 53 | # $LD_LIBRARY_PATH. 54 | if (UNIX) 55 | # We must escape the '$' symbol to make sure it is passed to the 56 | # compiler. 57 | set_target_properties(${target} PROPERTIES 58 | BUILD_WITH_INSTALL_RPATH ON 59 | INSTALL_RPATH "\$ORIGIN/${relative_path}" 60 | ) 61 | endif () 62 | endmacro() 63 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Expected inputs. 3 | set(RUST_BUILD_DIR "/path/to/rust/build/directory/" CACHE PATH 4 | "The path to the compiled rust directory.") 5 | set(RUST_INCLUDE_DIR "/path/to/rust/include/directory/" CACHE PATH 6 | "The path to the generated include.") 7 | 8 | include(CxxDemoExampleUtils) 9 | 10 | # Find the Rust Library 11 | set(rust_linktime_file "NOT-FOUND") 12 | find_rust_library("mmscenegraph_rs" ${RUST_BUILD_DIR} rust_linktime_file) 13 | message(STATUS "Rust Library: " ${rust_linktime_file}) 14 | 15 | # Generate CXX Bridge files. 16 | find_program(CXXBRIDGE cxxbridge REQUIRED PATHS $ENV{HOME}/.cargo/bin) 17 | message(STATUS "Using cxxbridge: ${CXXBRIDGE}") 18 | set(cxxbridge_in ${CMAKE_SOURCE_DIR}/src/cxxbridge.rs) 19 | set(cxxbridge_source_out ${CMAKE_SOURCE_DIR}/src/_cxxbridge.cpp) 20 | set(cxxbridge_header_out ${CMAKE_SOURCE_DIR}/include/mmscenegraph/_cxxbridge.h) 21 | set(cxxbridge_args "--cxx-impl-annotations" "MMSCENEGRAPH_SYMBOL_EXPORT") 22 | add_custom_command( 23 | OUTPUT ${cxxbridge_source_out} ${cxxbridge_header_out} 24 | COMMAND ${CXXBRIDGE} ${cxxbridge_in} ${cxxbridge_args} --header --output ${cxxbridge_header_out} 25 | COMMAND ${CXXBRIDGE} ${cxxbridge_in} ${cxxbridge_args} --output ${cxxbridge_source_out} 26 | COMMENT "Generating CXX Bridge: ${cxxbridge_header_out} ${cxxbridge_source_out}" 27 | DEPENDS ${cxxbridge_in}) 28 | 29 | # Add 'mmscenegraph' library as a C++ wrapper around the Rust library. 30 | add_library(${target_lib} SHARED 31 | lib.cpp 32 | ${cxxbridge_source_out}) 33 | target_link_libraries(${target_lib} 34 | ${rust_linktime_file}) 35 | target_include_directories(${target_lib} 36 | PUBLIC ${CMAKE_SOURCE_DIR}/include 37 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/ ) 38 | target_include_directories(${target_lib} PUBLIC ${RUST_INCLUDE_DIR}) 39 | set_target_properties(${target_lib} 40 | PROPERTIES CXX_VISIBILITY_PRESET hidden) 41 | if (MSVC) 42 | target_link_libraries(${target_lib} ws2_32 userenv advapi32 shell32) 43 | if (CMAKE_BUILD_TYPE STREQUAL "Release") 44 | target_link_libraries(${target_lib} msvcrt) 45 | else () 46 | target_link_libraries(${target_lib} msvcrtd) 47 | endif() 48 | elseif (UNIX) 49 | target_link_libraries(${target_lib} pthread m dl) 50 | endif () 51 | 52 | install( 53 | TARGETS 54 | ${target_lib} 55 | ARCHIVE DESTINATION "lib" 56 | LIBRARY DESTINATION "lib" 57 | RUNTIME DESTINATION "bin") 58 | -------------------------------------------------------------------------------- /src/cxxbridge.rs: -------------------------------------------------------------------------------- 1 | #[cxx::bridge(namespace = mmscenegraph)] 2 | mod ffi { 3 | struct SharedThing { 4 | z: i32, 5 | y: Box, 6 | x: UniquePtr, 7 | } 8 | 9 | unsafe extern "C++" { 10 | include!("mmscenegraph/symbol_export.h"); 11 | include!("mmscenegraph/_cpp.h"); 12 | include!("mmscenegraph.h"); 13 | 14 | type ThingC; 15 | fn make_demo(appname: &str) -> UniquePtr; 16 | fn get_name(thing: &ThingC) -> &CxxString; 17 | fn do_thing(state: SharedThing); 18 | } 19 | 20 | extern "Rust" { 21 | type ThingR; 22 | fn print_r(r: &ThingR); 23 | 24 | type ReadOperation; 25 | fn get_id(self: &ReadOperation) -> u8; 26 | fn get_num(self: &ReadOperation) -> usize; 27 | fn new_read_operation(id: u8, num: usize) -> Box; 28 | 29 | type WriteOperation; 30 | fn get_id(self: &WriteOperation) -> u8; 31 | fn get_num(self: &WriteOperation) -> usize; 32 | fn new_write_operation(id: u8, num: usize) -> Box; 33 | } 34 | 35 | #[namespace = "mmscenegraph::geom"] 36 | extern "Rust" { 37 | fn read(buffer: &mut [u32]) -> bool; 38 | fn write(buffer: &[u32]) -> bool; 39 | } 40 | } 41 | 42 | pub struct ThingR(usize); 43 | 44 | pub struct ReadOperation { 45 | id: u8, 46 | num: usize, 47 | } 48 | 49 | fn read(buffer: &mut [u32]) -> bool { 50 | for i in 0..buffer.len() { 51 | println!("read buffer i={}", i); 52 | buffer[i] = i as u32; 53 | } 54 | true 55 | } 56 | 57 | fn write(buffer: &[u32]) -> bool { 58 | for i in 0..buffer.len() { 59 | println!("write buffer i={} value={}", i, buffer[i]); 60 | } 61 | true 62 | } 63 | 64 | fn new_read_operation(id: u8, num: usize) -> Box { 65 | println!("new_read_operation(id={0}, num={1})", id, num); 66 | Box::new(ReadOperation { id, num }) 67 | } 68 | 69 | impl ReadOperation { 70 | fn get_id(&self) -> u8 { 71 | println!("ReadOperation.get_id()"); 72 | self.id 73 | } 74 | 75 | fn get_num(&self) -> usize { 76 | println!("ReadOperation.get_num()"); 77 | self.num 78 | } 79 | } 80 | 81 | pub struct WriteOperation { 82 | id: u8, 83 | num: usize, 84 | } 85 | 86 | fn new_write_operation(id: u8, num: usize) -> Box { 87 | println!("new_write_operation(id={0}, num={1})", id, num); 88 | Box::new(WriteOperation { id, num }) 89 | } 90 | 91 | impl WriteOperation { 92 | fn get_id(&self) -> u8 { 93 | println!("WriteOperation.get_id()"); 94 | self.id 95 | } 96 | 97 | fn get_num(&self) -> usize { 98 | println!("WriteOperation.get_num()"); 99 | self.num 100 | } 101 | } 102 | 103 | fn print_r(r: &ThingR) { 104 | println!("called back with r={}", r.0); 105 | } 106 | 107 | #[allow(dead_code)] 108 | fn my_test() { 109 | let x = ffi::make_demo("demo of cxx::bridge"); 110 | println!("this is a {}", ffi::get_name(x.as_ref().unwrap())); 111 | 112 | ffi::do_thing(ffi::SharedThing { 113 | z: 222, 114 | y: Box::new(ThingR(333)), 115 | x, 116 | }); 117 | } 118 | -------------------------------------------------------------------------------- /output_gcc_6_3_1.log: -------------------------------------------------------------------------------- 1 | $ ./build_linux.bash 2 | ./build_linux.bash 3 | Compiling cc v1.0.62 4 | Compiling proc-macro2 v1.0.24 5 | Compiling unicode-xid v0.2.1 6 | Compiling syn v1.0.54 7 | Compiling cxxbridge-flags v1.0.23 (https://github.com/david-cattermole/cxx.git?rev=363c18b2982329d6e4fbc2a6e5f324f4fef03661#363c18b2) 8 | Compiling cxxbridge-macro v1.0.23 (https://github.com/david-cattermole/cxx.git?rev=363c18b2982329d6e4fbc2a6e5f324f4fef03661#363c18b2) 9 | Compiling libc v0.2.80 10 | Compiling link-cplusplus v1.0.4 11 | Compiling cxx v1.0.23 (https://github.com/david-cattermole/cxx.git?rev=363c18b2982329d6e4fbc2a6e5f324f4fef03661#363c18b2) 12 | Compiling quote v1.0.7 13 | Compiling mmscenegraph-rs v0.1.0 (/media/share/Users/catte/dev/cxx-demo-example) 14 | Finished release [optimized] target(s) in 18.52s 15 | -- The C compiler identification is GNU 6.3.1 16 | -- The CXX compiler identification is GNU 6.3.1 17 | -- Check for working C compiler: /opt/rh/devtoolset-6/root/usr/bin/gcc 18 | -- Check for working C compiler: /opt/rh/devtoolset-6/root/usr/bin/gcc - works 19 | -- Detecting C compiler ABI info 20 | -- Detecting C compiler ABI info - done 21 | -- Detecting C compile features 22 | -- Detecting C compile features - done 23 | -- Check for working CXX compiler: /opt/rh/devtoolset-6/root/usr/bin/g++ 24 | -- Check for working CXX compiler: /opt/rh/devtoolset-6/root/usr/bin/g++ - works 25 | -- Detecting CXX compiler ABI info 26 | -- Detecting CXX compiler ABI info - done 27 | -- Detecting CXX compile features 28 | -- Detecting CXX compile features - done 29 | -- Finding: libmmscenegraph_rs.a 30 | -- Rust Library: /media/dev/cxx-demo-example/target/release/libmmscenegraph_rs.a 31 | -- Using cxxbridge: /home/davidc/.cargo/bin/cxxbridge 32 | -- Configuring done 33 | -- Generating done 34 | -- Build files have been written to: /media/dev/cxx-demo-example/build_linux 35 | [ 12%] Generating CXX Bridge: /media/dev/cxx-demo-example/include/mmscenegraph/_cxxbridge.h /media/dev/cxx-demo-example/src/_cxxbridge.cpp 36 | Scanning dependencies of target mmscenegraph 37 | [ 25%] Building CXX object src/CMakeFiles/mmscenegraph.dir/lib.cpp.o 38 | [ 37%] Building CXX object src/CMakeFiles/mmscenegraph.dir/_cxxbridge.cpp.o 39 | [ 50%] Linking CXX shared library libmmscenegraph.so 40 | [ 50%] Built target mmscenegraph 41 | Scanning dependencies of target mmscenegraph_tests 42 | [ 62%] Building CXX object tests/CMakeFiles/mmscenegraph_tests.dir/main.cpp.o 43 | [ 75%] Building CXX object tests/CMakeFiles/mmscenegraph_tests.dir/test_a.cpp.o 44 | [ 87%] Building CXX object tests/CMakeFiles/mmscenegraph_tests.dir/test_b.cpp.o 45 | [100%] Linking CXX executable mmscenegraph_tests 46 | [100%] Built target mmscenegraph_tests 47 | [ 50%] Built target mmscenegraph 48 | [100%] Built target mmscenegraph_tests 49 | Install the project... 50 | -- Install configuration: "Release" 51 | -- Installing: /media/dev/cxx-demo-example/install/lib/libmmscenegraph.so 52 | -- Installing: /media/dev/cxx-demo-example/install/bin/mmscenegraph_tests 53 | 54 | $ ./install/bin/mmscenegraph_tests 55 | ---- Start Testing... 56 | 2 + 2 = 4 57 | ---- Start Test A... 58 | SCENEGRAPH: Add SceneGraph 42 59 | SCENEGRAPH: Remove SceneGraph 0x157b490 60 | ---- Finished Test A! 61 | ---- Start Test B... 62 | my awesome demo 63 | new_read_operation(id=42, num=42) 64 | ReadOperation.get_id() 65 | ReadOperation.get_num() 66 | Read Op Id: * 67 | Read Op Num: 42 68 | new_write_operation(id=42, num=42) 69 | WriteOperation.get_id() 70 | WriteOperation.get_num() 71 | Write Op Id: * 72 | Write Op Num: 42 73 | ---- Finished Test B! 74 | done with ThingC 75 | ---- Finished Testing! 76 | 77 | $ cxxbridge --version 78 | cxxbridge 1.0.23 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust CXX demo with CBindgen, and CMake on Windows and Linux 2 | 3 | This is an example project to experment and show how to use Rust and 4 | C++ together in a single shared library, using C++ strengths and Rust 5 | for it's strengths too. 6 | 7 | - C++ can call Rust functions, with native data types (such as 8 | `std::unique_ptr`). 9 | - Rust can call C++ functions, with native data types (such as 10 | `std::Box`) 11 | - C++ can call C-compatible Rust functions. 12 | 13 | # Compile and Test (GNU Linux) 14 | 15 | The build environment assumes to be running on Linux with GCC 6.3.1. 16 | 17 | ``` shell 18 | $ cd /path/to/project/root/ 19 | 20 | $ bash build_linux.bash 21 | 22 | # Run tests 23 | $ ./install/bin/mmscenegraph_tests 24 | 2 + 2 = 4 25 | SCENEGRAPH: Add SceneGraph 42 26 | SCENEGRAPH: Remove SceneGraph 0x96b5b0 27 | my awesome demo 28 | done with ThingC 29 | ``` 30 | 31 | Note: If you are using CentOS 7.8 and require the Red Hat Developer 32 | Toolset 6 (GCC 6.3.1) for compatiblity with the VFX Reference Platform CY2018, 33 | then you can use the following commands prior to running `build_linux.bash`: 34 | ``` 35 | $ export CC=/opt/rh/devtoolset-6/root/usr/bin/gcc 36 | $ export CXX=/opt/rh/devtoolset-6/root/usr/bin/g++ 37 | $ export _GLIBCXX_USE_CXX11_ABI=0 # Use the old std::string and std::list ABI. 38 | 39 | # Enable Red Hat Developer Toolset 6 40 | $ scl enable devtoolset-6 bash 41 | ``` 42 | 43 | # Compile and Test (Microsoft Windows) 44 | 45 | This has been tested on Windows 10, with Visual Studio 2015. 46 | 47 | Make sure the following commands are run in the Visual Studio 2015 enabled Command Prompt. 48 | ``` shell 49 | > cd C:\path\to\project\root\ 50 | 51 | > build_windows64.bat 52 | 53 | > install\bin\mmscenegraph_tests.exe 54 | 2 + 2 = 4 55 | SCENEGRAPH: Add SceneGraph 42 56 | SCENEGRAPH: Remove SceneGraph 0x1ffc8819410 57 | my awesome demo 58 | done with ThingC 59 | ``` 60 | 61 | # Dependencies 62 | 63 | You will need the Rust compiler and a C/C++ compiler. Below are the 64 | tested dependancy versions, for both Linux and Windows (MacOSX has not 65 | been tested). 66 | 67 | This demo targets the C++11 standard. 68 | 69 | - Linux 70 | - GCC 6.3.1 71 | - Windows 10 72 | - MSVC - Visual Studio 2015 73 | - Linux or Windows 74 | - CMake 2.8.12+ 75 | - Rust 1.48 76 | - cbindgen 77 | - cxx 1.0.26 78 | - libc 79 | - cxxbridge-cmd 1.0.26 (installed via Rust's Cargo package manager) 80 | 81 | # Project Anatomy 82 | 83 | This example project contains many different files needing to be 84 | compiled by the Rust compilier and a C++11 compliant compilier. 85 | 86 | ## Rust code 87 | 88 | The Rust code is compiled by the `cargo` command, and starts in the 89 | file `src/lib.rs`. Any files needing to be compiled, such as 90 | `src/ffi.rs` and `src/cxxbridge.rs` must be loaded using the `pub mod` 91 | keywords. 92 | 93 | Simply add more modules to add Rust functions and structs to the Rust 94 | side of the project. 95 | 96 | ## C++ Files 97 | 98 | The C++ code is compiled and linked with the Rust code, after the Rust 99 | compiler has produced a static library, the C++ compiler then links 100 | the Rust and C++ libraries together into a single Shared library (.so 101 | on Linux and .dll/.lib on Windows). 102 | 103 | Files: 104 | ``` 105 | src/lib.cpp 106 | include/mmscenegraph/_cpp.h 107 | ``` 108 | 109 | ## Library Header 110 | 111 | The `include/mmscenegraph.h` file defines the functions, data 112 | structures and data types from Rust and C++ into a C++ compatible 113 | header file. 114 | 115 | `include/mmscenegraph.h` is publically facing and has a C++ namespace 116 | `mmscenegraph`. 117 | 118 | The contents of `include/mmscenegraph.h` combines auto-generated 119 | headers, see the next section for details. 120 | 121 | ## Auto-Generated C++ code 122 | 123 | Rust source files are parsed by the commands `cbindgen` and 124 | `cxxbridge`. The commands are used to generate C++ source and header 125 | files which can then be used in a C++ compiler. 126 | 127 | The details of the `cbindgen` command is controlled by the 128 | `cbindgen.toml` configuration file, and Rust code in defined in 129 | `src/ffi.rs`. 130 | 131 | The `cxxbridge` command parses the `src/cxxbridge.rs` file and outputs 132 | `src/_cxxbridge.cpp` and `include/_cxxbridge.h` files. `cxxbridge` Can 133 | also generate a C++ shim header `include/cxx.h` to aid in the 134 | transition between C++ and Rust functions. 135 | 136 | Files: 137 | ``` 138 | src/ffi.rs 139 | src/cxxbridge.rs 140 | src/_cxxbridge.cpp 141 | include/cxx.h 142 | include/_cbindgen.h 143 | include/_cxxbridge.h 144 | cbindgen.toml 145 | ``` 146 | 147 | ## Build files 148 | 149 | This project is built by both `cargo` (for Rust code) and `cmake` (for 150 | C++ code). To combine the two programs in an easy-to-understand way, 151 | the `build_linux.bash` GNU Bash and `build_windows64.bat` Windows 152 | Batch file are provided. 153 | 154 | CMake is used to define the C++ build and must be called after all 155 | files have been generated and Rust code has been compiled. CMake 156 | 2.8.12 is the minimum supported version, due to backwards 157 | compatibility. The configuation file is `CMakeLists.txt`. 158 | 159 | `Cargo.toml` defines the Rust compiler's dependencies and build 160 | process. 161 | 162 | Files: 163 | ``` 164 | CMakeLists.txt 165 | src/CMakeLists.txt 166 | include/CMakeLists.txt 167 | tests/CMakeLists.txt 168 | Cargo.toml 169 | build_linux.bash 170 | build_windows64.bat 171 | ``` 172 | 173 | ## Tests 174 | 175 | To ensure everything is working the `tests` sub-directory contains 176 | some example client code using both the `cbindgen` and `cxx` 177 | functions. 178 | 179 | Files: 180 | ``` 181 | tests/test_a.cpp (cbindgen tests) 182 | tests/test_b.cpp (cxx tests) 183 | ``` 184 | -------------------------------------------------------------------------------- /output_msvc_19_0_24215_1.log: -------------------------------------------------------------------------------- 1 | > build_windows64.bat 2 | Package Root: C:\Users\catte\dev\cxx-demo-example\ 3 | Compiling cc v1.0.62 4 | Compiling proc-macro2 v1.0.24 5 | Compiling unicode-xid v0.2.1 6 | Compiling syn v1.0.54 7 | Compiling cxxbridge-flags v1.0.23 (https://github.com/david-cattermole/cxx.git?rev=363c18b2982329d6e4fbc2a6e5f324f4fef03661#363c18b2) 8 | Compiling cxxbridge-macro v1.0.23 (https://github.com/david-cattermole/cxx.git?rev=363c18b2982329d6e4fbc2a6e5f324f4fef03661#363c18b2) 9 | Compiling libc v0.2.80 10 | Compiling link-cplusplus v1.0.4 11 | Compiling cxx v1.0.23 (https://github.com/david-cattermole/cxx.git?rev=363c18b2982329d6e4fbc2a6e5f324f4fef03661#363c18b2) 12 | Compiling quote v1.0.7 13 | Compiling mmscenegraph-rs v0.1.0 (C:\Users\catte\dev\cxx-demo-example) 14 | Finished release [optimized] target(s) in 22.00s 15 | -- The C compiler identification is MSVC 19.0.24215.1 16 | -- The CXX compiler identification is MSVC 19.0.24215.1 17 | -- Detecting C compiler ABI info 18 | -- Detecting C compiler ABI info - done 19 | -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe - skipped 20 | -- Detecting C compile features 21 | -- Detecting C compile features - done 22 | -- Detecting CXX compiler ABI info 23 | -- Detecting CXX compiler ABI info - done 24 | -- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe - skipped 25 | -- Detecting CXX compile features 26 | -- Detecting CXX compile features - done 27 | -- Finding: mmscenegraph_rs.lib 28 | -- Rust Library: C:/Users/catte/dev/cxx-demo-example/target/release/mmscenegraph_rs.lib 29 | -- Using cxxbridge: C:/Users/catte/.cargo/bin/cxxbridge.exe 30 | -- Configuring done 31 | -- Generating done 32 | -- Build files have been written to: C:/Users/catte/dev/cxx-demo-example/build_windows 33 | 34 | Microsoft (R) Program Maintenance Utility Version 14.00.24210.0 35 | Copyright (C) Microsoft Corporation. All rights reserved. 36 | 37 | 38 | Microsoft (R) Program Maintenance Utility Version 14.00.24210.0 39 | Copyright (C) Microsoft Corporation. All rights reserved. 40 | 41 | [ 12%] Generating CXX Bridge: C:/Users/catte/dev/cxx-demo-example/include/mmscenegraph/_cxxbridge.h C:/Users/catte/dev/cxx-demo-example/src/_cxxbridge.cpp 42 | Scanning dependencies of target mmscenegraph 43 | [ 25%] Building CXX object src/CMakeFiles/mmscenegraph.dir/lib.cpp.obj 44 | lib.cpp 45 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(344): warning C4624: 'mmscenegraph::ThingR': destructor was implicitly defined as deleted 46 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(359): warning C4624: 'mmscenegraph::ReadOperation': destructor was implicitly defined as deleted 47 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(374): warning C4624: 'mmscenegraph::WriteOperation': destructor was implicitly defined as deleted 48 | [ 37%] Building CXX object src/CMakeFiles/mmscenegraph.dir/_cxxbridge.cpp.obj 49 | _cxxbridge.cpp 50 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(344): warning C4624: 'mmscenegraph::ThingR': destructor was implicitly defined as deleted 51 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(359): warning C4624: 'mmscenegraph::ReadOperation': destructor was implicitly defined as deleted 52 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(374): warning C4624: 'mmscenegraph::WriteOperation': destructor was implicitly defined as deleted 53 | [ 50%] Linking CXX shared library mmscenegraph.dll 54 | Creating library mmscenegraph.lib and object mmscenegraph.exp 55 | [ 50%] Built target mmscenegraph 56 | Scanning dependencies of target mmscenegraph_tests 57 | [ 62%] Building CXX object tests/CMakeFiles/mmscenegraph_tests.dir/main.cpp.obj 58 | main.cpp 59 | [ 75%] Building CXX object tests/CMakeFiles/mmscenegraph_tests.dir/test_a.cpp.obj 60 | test_a.cpp 61 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(344): warning C4624: 'mmscenegraph::ThingR': destructor was implicitly defined as deleted 62 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(359): warning C4624: 'mmscenegraph::ReadOperation': destructor was implicitly defined as deleted 63 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(374): warning C4624: 'mmscenegraph::WriteOperation': destructor was implicitly defined as deleted 64 | [ 87%] Building CXX object tests/CMakeFiles/mmscenegraph_tests.dir/test_b.cpp.obj 65 | test_b.cpp 66 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(344): warning C4624: 'mmscenegraph::ThingR': destructor was implicitly defined as deleted 67 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(359): warning C4624: 'mmscenegraph::ReadOperation': destructor was implicitly defined as deleted 68 | C:\Users\catte\dev\cxx-demo-example\include\mmscenegraph/_cxxbridge.h(374): warning C4624: 'mmscenegraph::WriteOperation': destructor was implicitly defined as deleted 69 | [100%] Linking CXX executable mmscenegraph_tests.exe 70 | [100%] Built target mmscenegraph_tests 71 | 72 | Microsoft (R) Program Maintenance Utility Version 14.00.24210.0 73 | Copyright (C) Microsoft Corporation. All rights reserved. 74 | 75 | [ 50%] Built target mmscenegraph 76 | [100%] Built target mmscenegraph_tests 77 | Install the project... 78 | -- Install configuration: "Release" 79 | -- Installing: C:/Users/catte/dev/cxx-demo-example/install/lib/mmscenegraph.lib 80 | -- Installing: C:/Users/catte/dev/cxx-demo-example/install/bin/mmscenegraph.dll 81 | -- Installing: C:/Users/catte/dev/cxx-demo-example/install/bin/mmscenegraph_tests.exe 82 | 83 | > install\bin\mmscenegraph_tests.exe 84 | ---- Start Testing... 85 | 2 + 2 = 4 86 | ---- Start Test A... 87 | SCENEGRAPH: Add SceneGraph 42 88 | SCENEGRAPH: Remove SceneGraph 0x16aa2d26910 89 | ---- Finished Test A! 90 | ---- Start Test B... 91 | my awesome demo 92 | new_read_operation(id=42, num=42) 93 | ReadOperation.get_id() 94 | ReadOperation.get_num() 95 | Read Op Id: * 96 | Read Op Num: 42 97 | new_write_operation(id=42, num=42) 98 | WriteOperation.get_id() 99 | WriteOperation.get_num() 100 | Write Op Id: * 101 | Write Op Num: 42 102 | ---- Finished Test B! 103 | done with ThingC 104 | ---- Finished Testing! 105 | 106 | > cxxbridge --version 107 | cxxbridge 1.0.23 108 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /include/mmscenegraph/_cxxbridge.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "mmscenegraph/symbol_export.h" 3 | #include "mmscenegraph/_cpp.h" 4 | #include "mmscenegraph.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace rust { 15 | inline namespace cxxbridge1 { 16 | // #include "rust/cxx.h" 17 | 18 | #ifndef CXXBRIDGE1_PANIC 19 | #define CXXBRIDGE1_PANIC 20 | template 21 | void panic [[noreturn]] (const char *msg); 22 | #endif // CXXBRIDGE1_PANIC 23 | 24 | namespace { 25 | template 26 | class impl; 27 | } // namespace 28 | 29 | class String; 30 | 31 | template 32 | ::std::size_t size_of(); 33 | template 34 | ::std::size_t align_of(); 35 | 36 | #ifndef CXXBRIDGE1_RUST_STR 37 | #define CXXBRIDGE1_RUST_STR 38 | class Str final { 39 | public: 40 | Str() noexcept; 41 | Str(const String &) noexcept; 42 | Str(const std::string &); 43 | Str(const char *); 44 | Str(const char *, std::size_t); 45 | 46 | Str &operator=(const Str &) noexcept = default; 47 | 48 | explicit operator std::string() const; 49 | 50 | const char *data() const noexcept; 51 | std::size_t size() const noexcept; 52 | std::size_t length() const noexcept; 53 | 54 | Str(const Str &) noexcept = default; 55 | ~Str() noexcept = default; 56 | 57 | using iterator = const char *; 58 | using const_iterator = const char *; 59 | const_iterator begin() const noexcept; 60 | const_iterator end() const noexcept; 61 | const_iterator cbegin() const noexcept; 62 | const_iterator cend() const noexcept; 63 | 64 | bool operator==(const Str &) const noexcept; 65 | bool operator!=(const Str &) const noexcept; 66 | bool operator<(const Str &) const noexcept; 67 | bool operator<=(const Str &) const noexcept; 68 | bool operator>(const Str &) const noexcept; 69 | bool operator>=(const Str &) const noexcept; 70 | 71 | void swap(Str &) noexcept; 72 | 73 | private: 74 | class uninit; 75 | Str(uninit) noexcept; 76 | friend impl; 77 | 78 | std::array repr; 79 | }; 80 | #endif // CXXBRIDGE1_RUST_STR 81 | 82 | #ifndef CXXBRIDGE1_RUST_SLICE 83 | #define CXXBRIDGE1_RUST_SLICE 84 | namespace detail { 85 | template 86 | struct copy_assignable_if {}; 87 | 88 | template <> 89 | struct copy_assignable_if { 90 | copy_assignable_if() noexcept = default; 91 | copy_assignable_if(const copy_assignable_if &) noexcept = default; 92 | copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete; 93 | copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default; 94 | }; 95 | } // namespace detail 96 | 97 | template 98 | class Slice final 99 | : private detail::copy_assignable_if::value> { 100 | public: 101 | using value_type = T; 102 | 103 | Slice() noexcept; 104 | Slice(T *, std::size_t count) noexcept; 105 | 106 | Slice &operator=(const Slice &) noexcept = default; 107 | Slice &operator=(Slice &&) noexcept = default; 108 | 109 | T *data() const noexcept; 110 | std::size_t size() const noexcept; 111 | std::size_t length() const noexcept; 112 | bool empty() const noexcept; 113 | 114 | T &operator[](std::size_t n) const noexcept; 115 | T &at(std::size_t n) const; 116 | T &front() const noexcept; 117 | T &back() const noexcept; 118 | 119 | Slice(const Slice &) noexcept = default; 120 | ~Slice() noexcept = default; 121 | 122 | class iterator; 123 | iterator begin() const noexcept; 124 | iterator end() const noexcept; 125 | 126 | void swap(Slice &) noexcept; 127 | 128 | private: 129 | class uninit; 130 | Slice(uninit) noexcept; 131 | friend impl; 132 | friend void sliceInit(void *, const void *, std::size_t) noexcept; 133 | friend void *slicePtr(const void *) noexcept; 134 | friend std::size_t sliceLen(const void *) noexcept; 135 | 136 | std::array repr; 137 | }; 138 | 139 | template 140 | class Slice::iterator final { 141 | public: 142 | using iterator_category = std::random_access_iterator_tag; 143 | using value_type = T; 144 | using difference_type = std::ptrdiff_t; 145 | using pointer = typename std::add_pointer::type; 146 | using reference = typename std::add_lvalue_reference::type; 147 | 148 | reference operator*() const noexcept; 149 | pointer operator->() const noexcept; 150 | reference operator[](difference_type) const noexcept; 151 | 152 | iterator &operator++() noexcept; 153 | iterator operator++(int) noexcept; 154 | iterator &operator--() noexcept; 155 | iterator operator--(int) noexcept; 156 | 157 | iterator &operator+=(difference_type) noexcept; 158 | iterator &operator-=(difference_type) noexcept; 159 | iterator operator+(difference_type) const noexcept; 160 | iterator operator-(difference_type) const noexcept; 161 | difference_type operator-(const iterator &) const noexcept; 162 | 163 | bool operator==(const iterator &) const noexcept; 164 | bool operator!=(const iterator &) const noexcept; 165 | bool operator<(const iterator &) const noexcept; 166 | bool operator<=(const iterator &) const noexcept; 167 | bool operator>(const iterator &) const noexcept; 168 | bool operator>=(const iterator &) const noexcept; 169 | 170 | private: 171 | friend class Slice; 172 | void *pos; 173 | std::size_t stride; 174 | }; 175 | 176 | template 177 | Slice::Slice() noexcept { 178 | sliceInit(this, reinterpret_cast(align_of()), 0); 179 | } 180 | 181 | template 182 | Slice::Slice(T *s, std::size_t count) noexcept { 183 | sliceInit(this, const_cast::type *>(s), count); 184 | } 185 | 186 | template 187 | T *Slice::data() const noexcept { 188 | return reinterpret_cast(slicePtr(this)); 189 | } 190 | 191 | template 192 | std::size_t Slice::size() const noexcept { 193 | return sliceLen(this); 194 | } 195 | 196 | template 197 | std::size_t Slice::length() const noexcept { 198 | return this->size(); 199 | } 200 | 201 | template 202 | bool Slice::empty() const noexcept { 203 | return this->size() == 0; 204 | } 205 | 206 | template 207 | T &Slice::operator[](std::size_t n) const noexcept { 208 | assert(n < this->size()); 209 | auto pos = static_cast(slicePtr(this)) + size_of() * n; 210 | return *reinterpret_cast(pos); 211 | } 212 | 213 | template 214 | T &Slice::at(std::size_t n) const { 215 | if (n >= this->size()) { 216 | panic("rust::Slice index out of range"); 217 | } 218 | return (*this)[n]; 219 | } 220 | 221 | template 222 | T &Slice::front() const noexcept { 223 | assert(!this->empty()); 224 | return (*this)[0]; 225 | } 226 | 227 | template 228 | T &Slice::back() const noexcept { 229 | assert(!this->empty()); 230 | return (*this)[this->size() - 1]; 231 | } 232 | 233 | template 234 | typename Slice::iterator::reference 235 | Slice::iterator::operator*() const noexcept { 236 | return *static_cast(this->pos); 237 | } 238 | 239 | template 240 | typename Slice::iterator::pointer 241 | Slice::iterator::operator->() const noexcept { 242 | return static_cast(this->pos); 243 | } 244 | 245 | template 246 | typename Slice::iterator::reference Slice::iterator::operator[]( 247 | typename Slice::iterator::difference_type n) const noexcept { 248 | auto pos = static_cast(this->pos) + this->stride * n; 249 | return *reinterpret_cast(pos); 250 | } 251 | 252 | template 253 | typename Slice::iterator &Slice::iterator::operator++() noexcept { 254 | this->pos = static_cast(this->pos) + this->stride; 255 | return *this; 256 | } 257 | 258 | template 259 | typename Slice::iterator Slice::iterator::operator++(int) noexcept { 260 | auto ret = iterator(*this); 261 | this->pos = static_cast(this->pos) + this->stride; 262 | return ret; 263 | } 264 | 265 | template 266 | typename Slice::iterator &Slice::iterator::operator--() noexcept { 267 | this->pos = static_cast(this->pos) - this->stride; 268 | return *this; 269 | } 270 | 271 | template 272 | typename Slice::iterator Slice::iterator::operator--(int) noexcept { 273 | auto ret = iterator(*this); 274 | this->pos = static_cast(this->pos) - this->stride; 275 | return ret; 276 | } 277 | 278 | template 279 | typename Slice::iterator &Slice::iterator::operator+=( 280 | typename Slice::iterator::difference_type n) noexcept { 281 | this->pos = static_cast(this->pos) + this->stride * n; 282 | return *this; 283 | } 284 | 285 | template 286 | typename Slice::iterator &Slice::iterator::operator-=( 287 | typename Slice::iterator::difference_type n) noexcept { 288 | this->pos = static_cast(this->pos) - this->stride * n; 289 | return *this; 290 | } 291 | 292 | template 293 | typename Slice::iterator Slice::iterator::operator+( 294 | typename Slice::iterator::difference_type n) const noexcept { 295 | auto ret = iterator(*this); 296 | ret.pos = static_cast(this->pos) + this->stride * n; 297 | return ret; 298 | } 299 | 300 | template 301 | typename Slice::iterator Slice::iterator::operator-( 302 | typename Slice::iterator::difference_type n) const noexcept { 303 | auto ret = iterator(*this); 304 | ret.pos = static_cast(this->pos) - this->stride * n; 305 | return ret; 306 | } 307 | 308 | template 309 | typename Slice::iterator::difference_type 310 | Slice::iterator::operator-(const iterator &other) const noexcept { 311 | auto diff = std::distance(static_cast(other.pos), 312 | static_cast(this->pos)); 313 | return diff / this->stride; 314 | } 315 | 316 | template 317 | bool Slice::iterator::operator==(const iterator &other) const noexcept { 318 | return this->pos == other.pos; 319 | } 320 | 321 | template 322 | bool Slice::iterator::operator!=(const iterator &other) const noexcept { 323 | return this->pos != other.pos; 324 | } 325 | 326 | template 327 | bool Slice::iterator::operator<(const iterator &other) const noexcept { 328 | return this->pos < other.pos; 329 | } 330 | 331 | template 332 | bool Slice::iterator::operator<=(const iterator &other) const noexcept { 333 | return this->pos <= other.pos; 334 | } 335 | 336 | template 337 | bool Slice::iterator::operator>(const iterator &other) const noexcept { 338 | return this->pos > other.pos; 339 | } 340 | 341 | template 342 | bool Slice::iterator::operator>=(const iterator &other) const noexcept { 343 | return this->pos >= other.pos; 344 | } 345 | 346 | template 347 | typename Slice::iterator Slice::begin() const noexcept { 348 | iterator it; 349 | it.pos = slicePtr(this); 350 | it.stride = size_of(); 351 | return it; 352 | } 353 | 354 | template 355 | typename Slice::iterator Slice::end() const noexcept { 356 | iterator it = this->begin(); 357 | it.pos = static_cast(it.pos) + it.stride * this->size(); 358 | return it; 359 | } 360 | 361 | template 362 | void Slice::swap(Slice &rhs) noexcept { 363 | std::swap(*this, rhs); 364 | } 365 | #endif // CXXBRIDGE1_RUST_SLICE 366 | 367 | #ifndef CXXBRIDGE1_RUST_BOX 368 | #define CXXBRIDGE1_RUST_BOX 369 | template 370 | class Box final { 371 | public: 372 | using element_type = T; 373 | using const_pointer = 374 | typename std::add_pointer::type>::type; 375 | using pointer = typename std::add_pointer::type; 376 | 377 | Box() = delete; 378 | Box(Box &&) noexcept; 379 | ~Box() noexcept; 380 | 381 | explicit Box(const T &); 382 | explicit Box(T &&); 383 | 384 | Box &operator=(Box &&) noexcept; 385 | 386 | const T *operator->() const noexcept; 387 | const T &operator*() const noexcept; 388 | T *operator->() noexcept; 389 | T &operator*() noexcept; 390 | 391 | template 392 | static Box in_place(Fields &&...); 393 | 394 | void swap(Box &) noexcept; 395 | 396 | static Box from_raw(T *) noexcept; 397 | 398 | T *into_raw() noexcept; 399 | 400 | /* Deprecated */ using value_type = element_type; 401 | 402 | private: 403 | class uninit; 404 | class allocation; 405 | Box(uninit) noexcept; 406 | void drop() noexcept; 407 | 408 | friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); } 409 | 410 | T *ptr; 411 | }; 412 | 413 | template 414 | class Box::uninit {}; 415 | 416 | template 417 | class Box::allocation { 418 | static T *alloc() noexcept; 419 | static void dealloc(T *) noexcept; 420 | 421 | public: 422 | allocation() noexcept : ptr(alloc()) {} 423 | ~allocation() noexcept { 424 | if (this->ptr) { 425 | dealloc(this->ptr); 426 | } 427 | } 428 | T *ptr; 429 | }; 430 | 431 | template 432 | Box::Box(Box &&other) noexcept : ptr(other.ptr) { 433 | other.ptr = nullptr; 434 | } 435 | 436 | template 437 | Box::Box(const T &val) { 438 | allocation alloc; 439 | ::new (alloc.ptr) T(val); 440 | this->ptr = alloc.ptr; 441 | alloc.ptr = nullptr; 442 | } 443 | 444 | template 445 | Box::Box(T &&val) { 446 | allocation alloc; 447 | ::new (alloc.ptr) T(std::move(val)); 448 | this->ptr = alloc.ptr; 449 | alloc.ptr = nullptr; 450 | } 451 | 452 | template 453 | Box::~Box() noexcept { 454 | if (this->ptr) { 455 | this->drop(); 456 | } 457 | } 458 | 459 | template 460 | Box &Box::operator=(Box &&other) noexcept { 461 | if (this->ptr) { 462 | this->drop(); 463 | } 464 | this->ptr = other.ptr; 465 | other.ptr = nullptr; 466 | return *this; 467 | } 468 | 469 | template 470 | const T *Box::operator->() const noexcept { 471 | return this->ptr; 472 | } 473 | 474 | template 475 | const T &Box::operator*() const noexcept { 476 | return *this->ptr; 477 | } 478 | 479 | template 480 | T *Box::operator->() noexcept { 481 | return this->ptr; 482 | } 483 | 484 | template 485 | T &Box::operator*() noexcept { 486 | return *this->ptr; 487 | } 488 | 489 | template 490 | template 491 | Box Box::in_place(Fields &&... fields) { 492 | allocation alloc; 493 | auto ptr = alloc.ptr; 494 | ::new (ptr) T{std::forward(fields)...}; 495 | alloc.ptr = nullptr; 496 | return from_raw(ptr); 497 | } 498 | 499 | template 500 | void Box::swap(Box &rhs) noexcept { 501 | using std::swap; 502 | swap(this->ptr, rhs.ptr); 503 | } 504 | 505 | template 506 | Box Box::from_raw(T *raw) noexcept { 507 | Box box = uninit{}; 508 | box.ptr = raw; 509 | return box; 510 | } 511 | 512 | template 513 | T *Box::into_raw() noexcept { 514 | T *raw = this->ptr; 515 | this->ptr = nullptr; 516 | return raw; 517 | } 518 | 519 | template 520 | Box::Box(uninit) noexcept {} 521 | #endif // CXXBRIDGE1_RUST_BOX 522 | 523 | #ifndef CXXBRIDGE1_RUST_OPAQUE 524 | #define CXXBRIDGE1_RUST_OPAQUE 525 | class Opaque { 526 | public: 527 | Opaque() = delete; 528 | Opaque(const Opaque &) = delete; 529 | ~Opaque() = delete; 530 | }; 531 | #endif // CXXBRIDGE1_RUST_OPAQUE 532 | 533 | #ifndef CXXBRIDGE1_IS_COMPLETE 534 | #define CXXBRIDGE1_IS_COMPLETE 535 | namespace detail { 536 | namespace { 537 | template 538 | struct is_complete : std::false_type {}; 539 | template 540 | struct is_complete : std::true_type {}; 541 | } // namespace 542 | } // namespace detail 543 | #endif // CXXBRIDGE1_IS_COMPLETE 544 | 545 | #ifndef CXXBRIDGE1_LAYOUT 546 | #define CXXBRIDGE1_LAYOUT 547 | class layout { 548 | template 549 | friend std::size_t size_of(); 550 | template 551 | friend std::size_t align_of(); 552 | template 553 | static typename std::enable_if::value, 554 | std::size_t>::type 555 | do_size_of() { 556 | return T::layout::size(); 557 | } 558 | template 559 | static typename std::enable_if::value, 560 | std::size_t>::type 561 | do_size_of() { 562 | return sizeof(T); 563 | } 564 | template 565 | static 566 | typename std::enable_if::value, std::size_t>::type 567 | size_of() { 568 | return do_size_of(); 569 | } 570 | template 571 | static typename std::enable_if::value, 572 | std::size_t>::type 573 | do_align_of() { 574 | return T::layout::align(); 575 | } 576 | template 577 | static typename std::enable_if::value, 578 | std::size_t>::type 579 | do_align_of() { 580 | return alignof(T); 581 | } 582 | template 583 | static 584 | typename std::enable_if::value, std::size_t>::type 585 | align_of() { 586 | return do_align_of(); 587 | } 588 | }; 589 | 590 | template 591 | std::size_t size_of() { 592 | return layout::size_of(); 593 | } 594 | 595 | template 596 | std::size_t align_of() { 597 | return layout::align_of(); 598 | } 599 | #endif // CXXBRIDGE1_LAYOUT 600 | } // namespace cxxbridge1 601 | } // namespace rust 602 | 603 | namespace mmscenegraph { 604 | struct SharedThing; 605 | using ThingC = ::mmscenegraph::ThingC; 606 | struct ThingR; 607 | struct ReadOperation; 608 | struct WriteOperation; 609 | } 610 | 611 | namespace mmscenegraph { 612 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$SharedThing 613 | #define CXXBRIDGE1_STRUCT_mmscenegraph$SharedThing 614 | struct SharedThing final { 615 | ::std::int32_t z; 616 | ::rust::Box<::mmscenegraph::ThingR> y; 617 | ::std::unique_ptr<::mmscenegraph::ThingC> x; 618 | 619 | using IsRelocatable = ::std::true_type; 620 | }; 621 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$SharedThing 622 | 623 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$ThingR 624 | #define CXXBRIDGE1_STRUCT_mmscenegraph$ThingR 625 | struct ThingR final : public ::rust::Opaque { 626 | ~ThingR() = delete; 627 | 628 | private: 629 | friend ::rust::layout; 630 | struct layout { 631 | static ::std::size_t size() noexcept; 632 | static ::std::size_t align() noexcept; 633 | }; 634 | }; 635 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$ThingR 636 | 637 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$ReadOperation 638 | #define CXXBRIDGE1_STRUCT_mmscenegraph$ReadOperation 639 | struct ReadOperation final : public ::rust::Opaque { 640 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::uint8_t get_id() const noexcept; 641 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::size_t get_num() const noexcept; 642 | ~ReadOperation() = delete; 643 | 644 | private: 645 | friend ::rust::layout; 646 | struct layout { 647 | static ::std::size_t size() noexcept; 648 | static ::std::size_t align() noexcept; 649 | }; 650 | }; 651 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$ReadOperation 652 | 653 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$WriteOperation 654 | #define CXXBRIDGE1_STRUCT_mmscenegraph$WriteOperation 655 | struct WriteOperation final : public ::rust::Opaque { 656 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::uint8_t get_id() const noexcept; 657 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::size_t get_num() const noexcept; 658 | ~WriteOperation() = delete; 659 | 660 | private: 661 | friend ::rust::layout; 662 | struct layout { 663 | static ::std::size_t size() noexcept; 664 | static ::std::size_t align() noexcept; 665 | }; 666 | }; 667 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$WriteOperation 668 | 669 | MMSCENEGRAPH_SYMBOL_EXPORT void print_r(const ::mmscenegraph::ThingR &r) noexcept; 670 | 671 | MMSCENEGRAPH_SYMBOL_EXPORT ::rust::Box<::mmscenegraph::ReadOperation> new_read_operation(::std::uint8_t id, ::std::size_t num) noexcept; 672 | 673 | MMSCENEGRAPH_SYMBOL_EXPORT ::rust::Box<::mmscenegraph::WriteOperation> new_write_operation(::std::uint8_t id, ::std::size_t num) noexcept; 674 | 675 | namespace geom { 676 | MMSCENEGRAPH_SYMBOL_EXPORT bool read(::rust::Slice<::std::uint32_t> buffer) noexcept; 677 | 678 | MMSCENEGRAPH_SYMBOL_EXPORT bool write(::rust::Slice buffer) noexcept; 679 | } // namespace geom 680 | } // namespace mmscenegraph 681 | -------------------------------------------------------------------------------- /cbindgen.toml: -------------------------------------------------------------------------------- 1 | # # The language to output bindings in 2 | # # 3 | # # possible values: "C", "C++" 4 | # # 5 | # # default: "C++" 6 | language = "C++" 7 | 8 | 9 | # # Options for wrapping the contents of the header: 10 | 11 | # # # An optional string of text to output at the beginning of the generated file 12 | # # # default: doesn't emit anything 13 | # # header = "/* Add header text here. */" 14 | 15 | # # An optional string of text to output at the end of the generated file 16 | # # default: doesn't emit anything 17 | # trailer = "/* Add trailer text here. */" 18 | 19 | # An optional name to use as an include guard 20 | # default: doesn't emit an include guard 21 | include_guard = "MMSCENEGRAPH_CBINDGEN_H" 22 | 23 | # # Whether to add a `#pragma once` guard 24 | # # default: doesn't emit a `#pragma once` 25 | # pragma_once = true 26 | 27 | # # An optional string of text to output between major sections of the generated 28 | # # file as a warning against manual editing 29 | # # 30 | # # default: doesn't emit anything 31 | # autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" 32 | 33 | # Whether to include a comment with the version of cbindgen used to generate the file 34 | # default: false 35 | include_version = true 36 | 37 | # An optional namespace to output around the generated bindings 38 | # default: doesn't emit a namespace 39 | namespace = "mmscenegraph" 40 | 41 | # # An optional list of namespaces to output around the generated bindings 42 | # # default: [] 43 | # namespaces = ["mozilla", "wr"] 44 | 45 | # # An optional list of namespaces to declare as using with "using namespace" 46 | # # default: [] 47 | # using_namespaces = ["mozilla", "wr"] 48 | 49 | # # A list of sys headers to #include (with angle brackets) 50 | # # default: [] 51 | # sys_includes = ["stdio", "string"] 52 | 53 | # A list of headers to #include (with quotes) 54 | # default: [] 55 | includes = ["symbol_export.h"] 56 | 57 | # # Whether cbindgen's default C/C++ standard imports should be suppressed. These 58 | # # imports are included by default because our generated headers tend to require 59 | # # them (e.g. for uint32_t). Currently, the generated imports are: 60 | # # 61 | # # * for C: , , , , 62 | # # 63 | # # * for C++: , , , , (depending on config) 64 | # # 65 | # # default: false 66 | # no_includes = false 67 | 68 | # Whether to make a C header C++ compatible. 69 | # These will wrap generated functions into a `extern "C"` block, e.g. 70 | # 71 | # #ifdef __cplusplus 72 | # extern "C" { 73 | # #endif // __cplusplus 74 | # 75 | # // Generated functions. 76 | # 77 | # #ifdef __cplusplus 78 | # } // extern "C" 79 | # #endif // __cplusplus 80 | # 81 | # default: false 82 | cpp_compat = true 83 | 84 | # # A list of lines to add verbatim after the includes block 85 | # after_includes = "#define VERSION 1" 86 | 87 | 88 | # # Code Style Options 89 | 90 | # # The style to use for curly braces 91 | # # 92 | # # possible values: "SameLine", "NextLine" 93 | # # 94 | # # default: "SameLine" 95 | # braces = "SameLine" 96 | 97 | # The desired length of a line to use when formatting lines 98 | # default: 100 99 | line_length = 80 100 | 101 | # The amount of spaces to indent by 102 | # default: 2 103 | tab_width = 2 104 | 105 | # # How the generated documentation should be commented. 106 | # # 107 | # # possible values: 108 | # # * "c": /* like this */ 109 | # # * "c99": // like this 110 | # # * "c++": /// like this 111 | # # * "doxy": like C, but with leading *'s on each line 112 | # # * "auto": "c++" if that's the language, "doxy" otherwise 113 | # # 114 | # # default: "auto" 115 | # documentation_style = "doxy" 116 | 117 | 118 | 119 | # # Codegen Options 120 | 121 | # # When generating a C header, the kind of declaration style to use for structs 122 | # # or enums. 123 | # # 124 | # # possible values: 125 | # # * "type": typedef struct { ... } MyType; 126 | # # * "tag": struct MyType { ... }; 127 | # # * "both": typedef struct MyType { ... } MyType; 128 | # # 129 | # # default: "both" 130 | # style = "both" 131 | 132 | # # A list of substitutions for converting cfg's to ifdefs. cfgs which aren't 133 | # # defined here will just be discarded. 134 | # # 135 | # # e.g. 136 | # # `#[cfg(target = "freebsd")] ...` 137 | # # becomes 138 | # # `#if defined(DEFINE_FREEBSD) ... #endif` 139 | # [defines] 140 | # "target_os = freebsd" = "DEFINE_FREEBSD" 141 | # "feature = serde" = "DEFINE_SERDE" 142 | 143 | 144 | [export] 145 | # A list of additional items to always include in the generated bindings if they're 146 | # found but otherwise don't appear to be used by the public API. 147 | # 148 | # default: [] 149 | # include = ["MyOrphanStruct", "MyGreatTypeRename"] 150 | 151 | # A list of items to not include in the generated bindings 152 | # default: [] 153 | exclude = ["SharedThing", "do_thing", "get_name", "make_demo"] 154 | 155 | # # A prefix to add before the name of every item 156 | # # default: no prefix is added 157 | # prefix = "mmsg_" 158 | 159 | # # Types of items that we'll generate. If empty, then all types of item are emitted. 160 | # # 161 | # # possible items: (TODO: explain these in detail) 162 | # # * "constants": 163 | # # * "globals": 164 | # # * "enums": 165 | # # * "structs": 166 | # # * "unions": 167 | # # * "typedefs": 168 | # # * "opaque": 169 | # # * "functions": 170 | # # 171 | # # default: [] 172 | # item_types = ["enums", "structs", "opaque", "functions"] 173 | 174 | # # Whether applying rules in export.rename prevents export.prefix from applying. 175 | # # 176 | # # e.g. given this toml: 177 | # # 178 | # # [export] 179 | # # prefix = "capi_" 180 | # # [export.rename] 181 | # # "MyType" = "my_cool_type" 182 | # # 183 | # # You get the following results: 184 | # # 185 | # # renaming_overrides_prefixing = true: 186 | # # "MyType" => "my_cool_type" 187 | # # 188 | # # renaming_overrides_prefixing = false: 189 | # # "MyType => capi_my_cool_type" 190 | # # 191 | # # default: false 192 | # renaming_overrides_prefixing = true 193 | 194 | # # Table of name conversions to apply to item names (lhs becomes rhs) 195 | # [export.rename] 196 | # "MyType" = "my_cool_type" 197 | # "my_function" = "BetterFunctionName" 198 | 199 | # # Table of things to prepend to the body of any struct, union, or enum that has the 200 | # # given name. This can be used to add things like methods which don't change ABI, 201 | # # mark fields private, etc 202 | # [export.pre_body] 203 | # "MyType" = """ 204 | # MyType() = delete; 205 | # private: 206 | # """ 207 | 208 | # # Table of things to append to the body of any struct, union, or enum that has the 209 | # # given name. This can be used to add things like methods which don't change ABI. 210 | # [export.body] 211 | # "MyType" = """ 212 | # void cppMethod() const; 213 | # """ 214 | 215 | # [layout] 216 | # # A string that should come before the name of any type which has been marked 217 | # # as `#[repr(packed)]`. For instance, "__attribute__((packed))" would be a 218 | # # reasonable value if targeting gcc/clang. A more portable solution would 219 | # # involve emitting the name of a macro which you define in a platform-specific 220 | # # way. e.g. "PACKED" 221 | # # 222 | # # default: `#[repr(packed)]` types will be treated as opaque, since it would 223 | # # be unsafe for C callers to use a incorrectly laid-out union. 224 | # packed = "PACKED" 225 | 226 | # # A string that should come before the name of any type which has been marked 227 | # # as `#[repr(align(n))]`. This string must be a function-like macro which takes 228 | # # a single argument (the requested alignment, `n`). For instance, a macro 229 | # # `#define`d as `ALIGNED(n)` in `header` which translates to 230 | # # `__attribute__((aligned(n)))` would be a reasonable value if targeting 231 | # # gcc/clang. 232 | # # 233 | # # default: `#[repr(align(n))]` types will be treated as opaque, since it 234 | # # could be unsafe for C callers to use a incorrectly-aligned union. 235 | # aligned_n = "ALIGNED" 236 | 237 | 238 | # [fn] 239 | # # An optional prefix to put before every function declaration 240 | # # default: no prefix added 241 | # prefix = "WR_START_FUNC" 242 | 243 | # # An optional postfix to put after any function declaration 244 | # # default: no postix added 245 | # postfix = "WR_END_FUNC" 246 | 247 | # # How to format function arguments 248 | # # 249 | # # possible values: 250 | # # * "horizontal": place all arguments on the same line 251 | # # * "vertical": place each argument on its own line 252 | # # * "auto": only use vertical if horizontal would exceed line_length 253 | # # 254 | # # default: "auto" 255 | # args = "horizontal" 256 | 257 | # # An optional string that should prefix function declarations which have been 258 | # # marked as `#[must_use]`. For instance, "__attribute__((warn_unused_result))" 259 | # # would be a reasonable value if targeting gcc/clang. A more portable solution 260 | # # would involve emitting the name of a macro which you define in a 261 | # # platform-specific way. e.g. "MUST_USE_FUNC" 262 | # # default: nothing is emitted for must_use functions 263 | # must_use = "MUST_USE_FUNC" 264 | 265 | # # An optional string that, if present, will be used to generate Swift function 266 | # # and method signatures for generated functions, for example "CF_SWIFT_NAME". 267 | # # If no such macro is available in your toolchain, you can define one using the 268 | # # `header` option in cbindgen.toml 269 | # # default: no swift_name function attributes are generated 270 | # swift_name_macro = "CF_SWIFT_NAME" 271 | 272 | # # A rule to use to rename function argument names. The renaming assumes the input 273 | # # is the Rust standard snake_case, however it accepts all the different rename_args 274 | # # inputs. This means many options here are no-ops or redundant. 275 | # # 276 | # # possible values (that actually do something): 277 | # # * "CamelCase": my_arg => myArg 278 | # # * "PascalCase": my_arg => MyArg 279 | # # * "GeckoCase": my_arg => aMyArg 280 | # # * "ScreamingSnakeCase": my_arg => MY_ARG 281 | # # * "None": apply no renaming 282 | # # 283 | # # technically possible values (that shouldn't have a purpose here): 284 | # # * "SnakeCase": apply no renaming 285 | # # * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?) 286 | # # * "UpperCase": same as ScreamingSnakeCase in this context 287 | # # * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context 288 | # # 289 | # # default: "None" 290 | # rename_args = "PascalCase" 291 | 292 | # # This rule specifies if the order of functions will be sorted in some way. 293 | # # 294 | # # "Name": sort by the name of the function 295 | # # "None": keep order in which the functions have been parsed 296 | # # 297 | # # default: "Name" 298 | # sort_by = "None" 299 | 300 | # [struct] 301 | # # A rule to use to rename struct field names. The renaming assumes the input is 302 | # # the Rust standard snake_case, however it acccepts all the different rename_args 303 | # # inputs. This means many options here are no-ops or redundant. 304 | # # 305 | # # possible values (that actually do something): 306 | # # * "CamelCase": my_arg => myArg 307 | # # * "PascalCase": my_arg => MyArg 308 | # # * "GeckoCase": my_arg => mMyArg 309 | # # * "ScreamingSnakeCase": my_arg => MY_ARG 310 | # # * "None": apply no renaming 311 | # # 312 | # # technically possible values (that shouldn't have a purpose here): 313 | # # * "SnakeCase": apply no renaming 314 | # # * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?) 315 | # # * "UpperCase": same as ScreamingSnakeCase in this context 316 | # # * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context 317 | # # 318 | # # default: "None" 319 | # rename_fields = "PascalCase" 320 | 321 | # # An optional string that should come before the name of any struct which has been 322 | # # marked as `#[must_use]`. For instance, "__attribute__((warn_unused))" 323 | # # would be a reasonable value if targeting gcc/clang. A more portable solution 324 | # # would involve emitting the name of a macro which you define in a 325 | # # platform-specific way. e.g. "MUST_USE_STRUCT" 326 | # # 327 | # # default: nothing is emitted for must_use structs 328 | # must_use = "MUST_USE_STRUCT" 329 | 330 | # # Whether a Rust type with associated consts should emit those consts inside the 331 | # # type's body. Otherwise they will be emitted trailing and with the type's name 332 | # # prefixed. This does nothing if the target is C, or if 333 | # # [const]allow_static_const = false 334 | # # 335 | # # default: false 336 | # # associated_constants_in_body: false 337 | 338 | # # Whether to derive a simple constructor that takes a value for every field. 339 | # # default: false 340 | # derive_constructor = true 341 | 342 | # # Whether to derive an operator== for all structs 343 | # # default: false 344 | # derive_eq = false 345 | 346 | # # Whether to derive an operator!= for all structs 347 | # # default: false 348 | # derive_neq = false 349 | 350 | # # Whether to derive an operator< for all structs 351 | # # default: false 352 | # derive_lt = false 353 | 354 | # # Whether to derive an operator<= for all structs 355 | # # default: false 356 | # derive_lte = false 357 | 358 | # # Whether to derive an operator> for all structs 359 | # # default: false 360 | # derive_gt = false 361 | 362 | # # Whether to derive an operator>= for all structs 363 | # # default: false 364 | # derive_gte = false 365 | 366 | 367 | 368 | 369 | 370 | # [enum] 371 | # # A rule to use to rename enum variants, and the names of any fields those 372 | # # variants have. This should probably be split up into two separate options, but 373 | # # for now, they're the same! See the documentation for `[struct]rename_fields` 374 | # # for how this applies to fields. Renaming of the variant assumes that the input 375 | # # is the Rust standard PascalCase. In the case of QualifiedScreamingSnakeCase, 376 | # # it also assumed that the enum's name is PascalCase. 377 | # # 378 | # # possible values (that actually do something): 379 | # # * "CamelCase": MyVariant => myVariant 380 | # # * "SnakeCase": MyVariant => my_variant 381 | # # * "ScreamingSnakeCase": MyVariant => MY_VARIANT 382 | # # * "QualifiedScreamingSnakeCase": MyVariant => ENUM_NAME_MY_VARIANT 383 | # # * "LowerCase": MyVariant => myvariant 384 | # # * "UpperCase": MyVariant => MYVARIANT 385 | # # * "None": apply no renaming 386 | # # 387 | # # technically possible values (that shouldn't have a purpose for the variants): 388 | # # * "PascalCase": apply no renaming 389 | # # * "GeckoCase": apply no renaming 390 | # # 391 | # # default: "None" 392 | # rename_variants = "None" 393 | 394 | # # Whether an extra "sentinel" enum variant should be added to all generated enums. 395 | # # Firefox uses this for their IPC serialization library. 396 | # # 397 | # # WARNING: if the sentinel is ever passed into Rust, behaviour will be Undefined. 398 | # # Rust does not know about this value, and will assume it cannot happen. 399 | # # 400 | # # default: false 401 | # add_sentinel = false 402 | 403 | # # Whether enum variant names should be prefixed with the name of the enum. 404 | # # default: false 405 | # prefix_with_name = false 406 | 407 | # # Whether to emit enums using "enum class" when targeting C++. 408 | # # default: true 409 | # enum_class = true 410 | 411 | # # Whether to generate static `::MyVariant(..)` constructors and `bool IsMyVariant()` 412 | # # methods for enums with fields. 413 | # # 414 | # # default: false 415 | # derive_helper_methods = false 416 | 417 | # # Whether to generate `const MyVariant& AsMyVariant() const` methods for enums with fields. 418 | # # default: false 419 | # derive_const_casts = false 420 | 421 | # # Whether to generate `MyVariant& AsMyVariant()` methods for enums with fields 422 | # # default: false 423 | # derive_mut_casts = false 424 | 425 | # # The name of the macro/function to use for asserting `IsMyVariant()` in the body of 426 | # # derived `AsMyVariant()` cast methods. 427 | # # 428 | # # default: "assert" (but also causes `` to be included by default) 429 | # cast_assert_name = "MOZ_RELEASE_ASSERT" 430 | 431 | # # An optional string that should come before the name of any enum which has been 432 | # # marked as `#[must_use]`. For instance, "__attribute__((warn_unused))" 433 | # # would be a reasonable value if targeting gcc/clang. A more portable solution 434 | # # would involve emitting the name of a macro which you define in a 435 | # # platform-specific way. e.g. "MUST_USE_ENUM" 436 | # # 437 | # # Note that this refers to the *output* type. That means this will not apply to an enum 438 | # # with fields, as it will be emitted as a struct. `[struct]must_use` will apply there. 439 | # # 440 | # # default: nothing is emitted for must_use enums 441 | # must_use = "MUST_USE_ENUM" 442 | 443 | # # Whether enums with fields should generate destructors. This exists so that generic 444 | # # enums can be properly instantiated with payloads that are C++ types with 445 | # # destructors. This isn't necessary for structs because C++ has rules to 446 | # # automatically derive the correct constructors and destructors for those types. 447 | # # 448 | # # Care should be taken with this option, as Rust and C++ cannot 449 | # # properly interoperate with eachother's notions of destructors. Also, this may 450 | # # change the ABI for the type. Either your destructor-full enums must live 451 | # # exclusively within C++, or they must only be passed by-reference between 452 | # # C++ and Rust. 453 | # # 454 | # # default: false 455 | # derive_tagged_enum_destructor = false 456 | 457 | # # Whether enums with fields should generate copy-constructor. See the discussion on 458 | # # derive_tagged_enum_destructor for why this is both useful and very dangerous. 459 | # # 460 | # # default: false 461 | # derive_tagged_enum_copy_constructor = false 462 | # # Whether enums with fields should generate copy-assignment operators. 463 | # # 464 | # # This depends on also deriving copy-constructors, and it is highly encouraged 465 | # # for this to be set to true. 466 | # # 467 | # # default: false 468 | # derive_tagged_enum_copy_assignment = false 469 | 470 | # # Whether enums with fields should generate an empty, private destructor. 471 | # # This allows the auto-generated constructor functions to compile, if there are 472 | # # non-trivially constructible members. This falls in the same family of 473 | # # dangerousness as `derive_tagged_enum_copy_constructor` and co. 474 | # # 475 | # # default: false 476 | # private_default_tagged_enum_constructor = false 477 | 478 | 479 | 480 | 481 | 482 | # [const] 483 | # # Whether a generated constant can be a static const in C++ mode. I have no 484 | # # idea why you would turn this off. 485 | # # 486 | # # default: true 487 | # allow_static_const = true 488 | 489 | # # Whether a generated constant can be constexpr in C++ mode. 490 | # # 491 | # # default: false 492 | # allow_constexpr = false 493 | 494 | 495 | 496 | 497 | 498 | # [macro_expansion] 499 | # # Whether bindings should be generated for instances of the bitflags! macro. 500 | # # default: false 501 | # bitflags = true 502 | 503 | 504 | 505 | 506 | 507 | 508 | # # Options for how your Rust library should be parsed 509 | 510 | # [parse] 511 | # # Whether to parse dependent crates and include their types in the output 512 | # # default: false 513 | # parse_deps = true 514 | 515 | # # A white list of crate names that are allowed to be parsed. If this is defined, 516 | # # only crates found in this list will ever be parsed. 517 | # # 518 | # # default: there is no whitelist (NOTE: this is the opposite of []) 519 | # include = ["webrender", "webrender_traits"] 520 | 521 | # # A black list of crate names that are not allowed to be parsed. 522 | # # default: [] 523 | # exclude = ["libc"] 524 | 525 | # # Whether to use a new temporary target directory when running `rustc --pretty=expanded`. 526 | # # This may be required for some build processes. 527 | # # 528 | # # default: false 529 | # clean = false 530 | 531 | # # Which crates other than the top-level binding crate we should generate 532 | # # bindings for. 533 | # # 534 | # # default: [] 535 | # extra_bindings = ["my_awesome_dep"] 536 | 537 | # [parse.expand] 538 | # # A list of crate names that should be run through `cargo expand` before 539 | # # parsing to expand any macros. Note that if a crate is named here, it 540 | # # will always be parsed, even if the blacklist/whitelist says it shouldn't be. 541 | # # 542 | # # default: [] 543 | # crates = ["euclid"] 544 | 545 | # # If enabled, use the `--all-features` option when expanding. Ignored when 546 | # # `features` is set. For backwards-compatibility, this is forced on if 547 | # # `expand = ["euclid"]` shorthand is used. 548 | # # 549 | # # default: false 550 | # all_features = false 551 | 552 | # # When `all_features` is disabled and this is also disabled, use the 553 | # # `--no-default-features` option when expanding. 554 | # # 555 | # # default: true 556 | # default_features = true 557 | 558 | # # A list of feature names that should be used when running `cargo expand`. This 559 | # # combines with `default_features` like in your `Cargo.toml`. Note that the features 560 | # # listed here are features for the current crate being built, *not* the crates 561 | # # being expanded. The crate's `Cargo.toml` must take care of enabling the 562 | # # appropriate features in its dependencies 563 | # # 564 | # # default: [] 565 | # features = ["cbindgen"] 566 | -------------------------------------------------------------------------------- /src/_cxxbridge.cpp: -------------------------------------------------------------------------------- 1 | #include "mmscenegraph/symbol_export.h" 2 | #include "mmscenegraph/_cpp.h" 3 | #include "mmscenegraph.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace rust { 14 | inline namespace cxxbridge1 { 15 | // #include "rust/cxx.h" 16 | 17 | #ifndef CXXBRIDGE1_PANIC 18 | #define CXXBRIDGE1_PANIC 19 | template 20 | void panic [[noreturn]] (const char *msg); 21 | #endif // CXXBRIDGE1_PANIC 22 | 23 | namespace { 24 | template 25 | class impl; 26 | } // namespace 27 | 28 | class String; 29 | 30 | template 31 | ::std::size_t size_of(); 32 | template 33 | ::std::size_t align_of(); 34 | 35 | #ifndef CXXBRIDGE1_RUST_STR 36 | #define CXXBRIDGE1_RUST_STR 37 | class Str final { 38 | public: 39 | Str() noexcept; 40 | Str(const String &) noexcept; 41 | Str(const std::string &); 42 | Str(const char *); 43 | Str(const char *, std::size_t); 44 | 45 | Str &operator=(const Str &) noexcept = default; 46 | 47 | explicit operator std::string() const; 48 | 49 | const char *data() const noexcept; 50 | std::size_t size() const noexcept; 51 | std::size_t length() const noexcept; 52 | 53 | Str(const Str &) noexcept = default; 54 | ~Str() noexcept = default; 55 | 56 | using iterator = const char *; 57 | using const_iterator = const char *; 58 | const_iterator begin() const noexcept; 59 | const_iterator end() const noexcept; 60 | const_iterator cbegin() const noexcept; 61 | const_iterator cend() const noexcept; 62 | 63 | bool operator==(const Str &) const noexcept; 64 | bool operator!=(const Str &) const noexcept; 65 | bool operator<(const Str &) const noexcept; 66 | bool operator<=(const Str &) const noexcept; 67 | bool operator>(const Str &) const noexcept; 68 | bool operator>=(const Str &) const noexcept; 69 | 70 | void swap(Str &) noexcept; 71 | 72 | private: 73 | class uninit; 74 | Str(uninit) noexcept; 75 | friend impl; 76 | 77 | std::array repr; 78 | }; 79 | #endif // CXXBRIDGE1_RUST_STR 80 | 81 | #ifndef CXXBRIDGE1_RUST_SLICE 82 | #define CXXBRIDGE1_RUST_SLICE 83 | namespace detail { 84 | template 85 | struct copy_assignable_if {}; 86 | 87 | template <> 88 | struct copy_assignable_if { 89 | copy_assignable_if() noexcept = default; 90 | copy_assignable_if(const copy_assignable_if &) noexcept = default; 91 | copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete; 92 | copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default; 93 | }; 94 | } // namespace detail 95 | 96 | template 97 | class Slice final 98 | : private detail::copy_assignable_if::value> { 99 | public: 100 | using value_type = T; 101 | 102 | Slice() noexcept; 103 | Slice(T *, std::size_t count) noexcept; 104 | 105 | Slice &operator=(const Slice &) noexcept = default; 106 | Slice &operator=(Slice &&) noexcept = default; 107 | 108 | T *data() const noexcept; 109 | std::size_t size() const noexcept; 110 | std::size_t length() const noexcept; 111 | bool empty() const noexcept; 112 | 113 | T &operator[](std::size_t n) const noexcept; 114 | T &at(std::size_t n) const; 115 | T &front() const noexcept; 116 | T &back() const noexcept; 117 | 118 | Slice(const Slice &) noexcept = default; 119 | ~Slice() noexcept = default; 120 | 121 | class iterator; 122 | iterator begin() const noexcept; 123 | iterator end() const noexcept; 124 | 125 | void swap(Slice &) noexcept; 126 | 127 | private: 128 | class uninit; 129 | Slice(uninit) noexcept; 130 | friend impl; 131 | friend void sliceInit(void *, const void *, std::size_t) noexcept; 132 | friend void *slicePtr(const void *) noexcept; 133 | friend std::size_t sliceLen(const void *) noexcept; 134 | 135 | std::array repr; 136 | }; 137 | 138 | template 139 | class Slice::iterator final { 140 | public: 141 | using iterator_category = std::random_access_iterator_tag; 142 | using value_type = T; 143 | using difference_type = std::ptrdiff_t; 144 | using pointer = typename std::add_pointer::type; 145 | using reference = typename std::add_lvalue_reference::type; 146 | 147 | reference operator*() const noexcept; 148 | pointer operator->() const noexcept; 149 | reference operator[](difference_type) const noexcept; 150 | 151 | iterator &operator++() noexcept; 152 | iterator operator++(int) noexcept; 153 | iterator &operator--() noexcept; 154 | iterator operator--(int) noexcept; 155 | 156 | iterator &operator+=(difference_type) noexcept; 157 | iterator &operator-=(difference_type) noexcept; 158 | iterator operator+(difference_type) const noexcept; 159 | iterator operator-(difference_type) const noexcept; 160 | difference_type operator-(const iterator &) const noexcept; 161 | 162 | bool operator==(const iterator &) const noexcept; 163 | bool operator!=(const iterator &) const noexcept; 164 | bool operator<(const iterator &) const noexcept; 165 | bool operator<=(const iterator &) const noexcept; 166 | bool operator>(const iterator &) const noexcept; 167 | bool operator>=(const iterator &) const noexcept; 168 | 169 | private: 170 | friend class Slice; 171 | void *pos; 172 | std::size_t stride; 173 | }; 174 | 175 | template 176 | Slice::Slice() noexcept { 177 | sliceInit(this, reinterpret_cast(align_of()), 0); 178 | } 179 | 180 | template 181 | Slice::Slice(T *s, std::size_t count) noexcept { 182 | sliceInit(this, const_cast::type *>(s), count); 183 | } 184 | 185 | template 186 | T *Slice::data() const noexcept { 187 | return reinterpret_cast(slicePtr(this)); 188 | } 189 | 190 | template 191 | std::size_t Slice::size() const noexcept { 192 | return sliceLen(this); 193 | } 194 | 195 | template 196 | std::size_t Slice::length() const noexcept { 197 | return this->size(); 198 | } 199 | 200 | template 201 | bool Slice::empty() const noexcept { 202 | return this->size() == 0; 203 | } 204 | 205 | template 206 | T &Slice::operator[](std::size_t n) const noexcept { 207 | assert(n < this->size()); 208 | auto pos = static_cast(slicePtr(this)) + size_of() * n; 209 | return *reinterpret_cast(pos); 210 | } 211 | 212 | template 213 | T &Slice::at(std::size_t n) const { 214 | if (n >= this->size()) { 215 | panic("rust::Slice index out of range"); 216 | } 217 | return (*this)[n]; 218 | } 219 | 220 | template 221 | T &Slice::front() const noexcept { 222 | assert(!this->empty()); 223 | return (*this)[0]; 224 | } 225 | 226 | template 227 | T &Slice::back() const noexcept { 228 | assert(!this->empty()); 229 | return (*this)[this->size() - 1]; 230 | } 231 | 232 | template 233 | typename Slice::iterator::reference 234 | Slice::iterator::operator*() const noexcept { 235 | return *static_cast(this->pos); 236 | } 237 | 238 | template 239 | typename Slice::iterator::pointer 240 | Slice::iterator::operator->() const noexcept { 241 | return static_cast(this->pos); 242 | } 243 | 244 | template 245 | typename Slice::iterator::reference Slice::iterator::operator[]( 246 | typename Slice::iterator::difference_type n) const noexcept { 247 | auto pos = static_cast(this->pos) + this->stride * n; 248 | return *reinterpret_cast(pos); 249 | } 250 | 251 | template 252 | typename Slice::iterator &Slice::iterator::operator++() noexcept { 253 | this->pos = static_cast(this->pos) + this->stride; 254 | return *this; 255 | } 256 | 257 | template 258 | typename Slice::iterator Slice::iterator::operator++(int) noexcept { 259 | auto ret = iterator(*this); 260 | this->pos = static_cast(this->pos) + this->stride; 261 | return ret; 262 | } 263 | 264 | template 265 | typename Slice::iterator &Slice::iterator::operator--() noexcept { 266 | this->pos = static_cast(this->pos) - this->stride; 267 | return *this; 268 | } 269 | 270 | template 271 | typename Slice::iterator Slice::iterator::operator--(int) noexcept { 272 | auto ret = iterator(*this); 273 | this->pos = static_cast(this->pos) - this->stride; 274 | return ret; 275 | } 276 | 277 | template 278 | typename Slice::iterator &Slice::iterator::operator+=( 279 | typename Slice::iterator::difference_type n) noexcept { 280 | this->pos = static_cast(this->pos) + this->stride * n; 281 | return *this; 282 | } 283 | 284 | template 285 | typename Slice::iterator &Slice::iterator::operator-=( 286 | typename Slice::iterator::difference_type n) noexcept { 287 | this->pos = static_cast(this->pos) - this->stride * n; 288 | return *this; 289 | } 290 | 291 | template 292 | typename Slice::iterator Slice::iterator::operator+( 293 | typename Slice::iterator::difference_type n) const noexcept { 294 | auto ret = iterator(*this); 295 | ret.pos = static_cast(this->pos) + this->stride * n; 296 | return ret; 297 | } 298 | 299 | template 300 | typename Slice::iterator Slice::iterator::operator-( 301 | typename Slice::iterator::difference_type n) const noexcept { 302 | auto ret = iterator(*this); 303 | ret.pos = static_cast(this->pos) - this->stride * n; 304 | return ret; 305 | } 306 | 307 | template 308 | typename Slice::iterator::difference_type 309 | Slice::iterator::operator-(const iterator &other) const noexcept { 310 | auto diff = std::distance(static_cast(other.pos), 311 | static_cast(this->pos)); 312 | return diff / this->stride; 313 | } 314 | 315 | template 316 | bool Slice::iterator::operator==(const iterator &other) const noexcept { 317 | return this->pos == other.pos; 318 | } 319 | 320 | template 321 | bool Slice::iterator::operator!=(const iterator &other) const noexcept { 322 | return this->pos != other.pos; 323 | } 324 | 325 | template 326 | bool Slice::iterator::operator<(const iterator &other) const noexcept { 327 | return this->pos < other.pos; 328 | } 329 | 330 | template 331 | bool Slice::iterator::operator<=(const iterator &other) const noexcept { 332 | return this->pos <= other.pos; 333 | } 334 | 335 | template 336 | bool Slice::iterator::operator>(const iterator &other) const noexcept { 337 | return this->pos > other.pos; 338 | } 339 | 340 | template 341 | bool Slice::iterator::operator>=(const iterator &other) const noexcept { 342 | return this->pos >= other.pos; 343 | } 344 | 345 | template 346 | typename Slice::iterator Slice::begin() const noexcept { 347 | iterator it; 348 | it.pos = slicePtr(this); 349 | it.stride = size_of(); 350 | return it; 351 | } 352 | 353 | template 354 | typename Slice::iterator Slice::end() const noexcept { 355 | iterator it = this->begin(); 356 | it.pos = static_cast(it.pos) + it.stride * this->size(); 357 | return it; 358 | } 359 | 360 | template 361 | void Slice::swap(Slice &rhs) noexcept { 362 | std::swap(*this, rhs); 363 | } 364 | #endif // CXXBRIDGE1_RUST_SLICE 365 | 366 | #ifndef CXXBRIDGE1_RUST_BOX 367 | #define CXXBRIDGE1_RUST_BOX 368 | template 369 | class Box final { 370 | public: 371 | using element_type = T; 372 | using const_pointer = 373 | typename std::add_pointer::type>::type; 374 | using pointer = typename std::add_pointer::type; 375 | 376 | Box() = delete; 377 | Box(Box &&) noexcept; 378 | ~Box() noexcept; 379 | 380 | explicit Box(const T &); 381 | explicit Box(T &&); 382 | 383 | Box &operator=(Box &&) noexcept; 384 | 385 | const T *operator->() const noexcept; 386 | const T &operator*() const noexcept; 387 | T *operator->() noexcept; 388 | T &operator*() noexcept; 389 | 390 | template 391 | static Box in_place(Fields &&...); 392 | 393 | void swap(Box &) noexcept; 394 | 395 | static Box from_raw(T *) noexcept; 396 | 397 | T *into_raw() noexcept; 398 | 399 | /* Deprecated */ using value_type = element_type; 400 | 401 | private: 402 | class uninit; 403 | class allocation; 404 | Box(uninit) noexcept; 405 | void drop() noexcept; 406 | 407 | friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); } 408 | 409 | T *ptr; 410 | }; 411 | 412 | template 413 | class Box::uninit {}; 414 | 415 | template 416 | class Box::allocation { 417 | static T *alloc() noexcept; 418 | static void dealloc(T *) noexcept; 419 | 420 | public: 421 | allocation() noexcept : ptr(alloc()) {} 422 | ~allocation() noexcept { 423 | if (this->ptr) { 424 | dealloc(this->ptr); 425 | } 426 | } 427 | T *ptr; 428 | }; 429 | 430 | template 431 | Box::Box(Box &&other) noexcept : ptr(other.ptr) { 432 | other.ptr = nullptr; 433 | } 434 | 435 | template 436 | Box::Box(const T &val) { 437 | allocation alloc; 438 | ::new (alloc.ptr) T(val); 439 | this->ptr = alloc.ptr; 440 | alloc.ptr = nullptr; 441 | } 442 | 443 | template 444 | Box::Box(T &&val) { 445 | allocation alloc; 446 | ::new (alloc.ptr) T(std::move(val)); 447 | this->ptr = alloc.ptr; 448 | alloc.ptr = nullptr; 449 | } 450 | 451 | template 452 | Box::~Box() noexcept { 453 | if (this->ptr) { 454 | this->drop(); 455 | } 456 | } 457 | 458 | template 459 | Box &Box::operator=(Box &&other) noexcept { 460 | if (this->ptr) { 461 | this->drop(); 462 | } 463 | this->ptr = other.ptr; 464 | other.ptr = nullptr; 465 | return *this; 466 | } 467 | 468 | template 469 | const T *Box::operator->() const noexcept { 470 | return this->ptr; 471 | } 472 | 473 | template 474 | const T &Box::operator*() const noexcept { 475 | return *this->ptr; 476 | } 477 | 478 | template 479 | T *Box::operator->() noexcept { 480 | return this->ptr; 481 | } 482 | 483 | template 484 | T &Box::operator*() noexcept { 485 | return *this->ptr; 486 | } 487 | 488 | template 489 | template 490 | Box Box::in_place(Fields &&... fields) { 491 | allocation alloc; 492 | auto ptr = alloc.ptr; 493 | ::new (ptr) T{std::forward(fields)...}; 494 | alloc.ptr = nullptr; 495 | return from_raw(ptr); 496 | } 497 | 498 | template 499 | void Box::swap(Box &rhs) noexcept { 500 | using std::swap; 501 | swap(this->ptr, rhs.ptr); 502 | } 503 | 504 | template 505 | Box Box::from_raw(T *raw) noexcept { 506 | Box box = uninit{}; 507 | box.ptr = raw; 508 | return box; 509 | } 510 | 511 | template 512 | T *Box::into_raw() noexcept { 513 | T *raw = this->ptr; 514 | this->ptr = nullptr; 515 | return raw; 516 | } 517 | 518 | template 519 | Box::Box(uninit) noexcept {} 520 | #endif // CXXBRIDGE1_RUST_BOX 521 | 522 | #ifndef CXXBRIDGE1_RUST_OPAQUE 523 | #define CXXBRIDGE1_RUST_OPAQUE 524 | class Opaque { 525 | public: 526 | Opaque() = delete; 527 | Opaque(const Opaque &) = delete; 528 | ~Opaque() = delete; 529 | }; 530 | #endif // CXXBRIDGE1_RUST_OPAQUE 531 | 532 | #ifndef CXXBRIDGE1_IS_COMPLETE 533 | #define CXXBRIDGE1_IS_COMPLETE 534 | namespace detail { 535 | namespace { 536 | template 537 | struct is_complete : std::false_type {}; 538 | template 539 | struct is_complete : std::true_type {}; 540 | } // namespace 541 | } // namespace detail 542 | #endif // CXXBRIDGE1_IS_COMPLETE 543 | 544 | #ifndef CXXBRIDGE1_LAYOUT 545 | #define CXXBRIDGE1_LAYOUT 546 | class layout { 547 | template 548 | friend std::size_t size_of(); 549 | template 550 | friend std::size_t align_of(); 551 | template 552 | static typename std::enable_if::value, 553 | std::size_t>::type 554 | do_size_of() { 555 | return T::layout::size(); 556 | } 557 | template 558 | static typename std::enable_if::value, 559 | std::size_t>::type 560 | do_size_of() { 561 | return sizeof(T); 562 | } 563 | template 564 | static 565 | typename std::enable_if::value, std::size_t>::type 566 | size_of() { 567 | return do_size_of(); 568 | } 569 | template 570 | static typename std::enable_if::value, 571 | std::size_t>::type 572 | do_align_of() { 573 | return T::layout::align(); 574 | } 575 | template 576 | static typename std::enable_if::value, 577 | std::size_t>::type 578 | do_align_of() { 579 | return alignof(T); 580 | } 581 | template 582 | static 583 | typename std::enable_if::value, std::size_t>::type 584 | align_of() { 585 | return do_align_of(); 586 | } 587 | }; 588 | 589 | template 590 | std::size_t size_of() { 591 | return layout::size_of(); 592 | } 593 | 594 | template 595 | std::size_t align_of() { 596 | return layout::align_of(); 597 | } 598 | #endif // CXXBRIDGE1_LAYOUT 599 | 600 | namespace { 601 | template struct deleter_if { 602 | template void operator()(T *) {} 603 | }; 604 | 605 | template <> struct deleter_if { 606 | template void operator()(T *ptr) { ptr->~T(); } 607 | }; 608 | } // namespace 609 | } // namespace cxxbridge1 610 | } // namespace rust 611 | 612 | namespace mmscenegraph { 613 | struct SharedThing; 614 | using ThingC = ::mmscenegraph::ThingC; 615 | struct ThingR; 616 | struct ReadOperation; 617 | struct WriteOperation; 618 | } 619 | 620 | namespace mmscenegraph { 621 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$SharedThing 622 | #define CXXBRIDGE1_STRUCT_mmscenegraph$SharedThing 623 | struct SharedThing final { 624 | ::std::int32_t z; 625 | ::rust::Box<::mmscenegraph::ThingR> y; 626 | ::std::unique_ptr<::mmscenegraph::ThingC> x; 627 | 628 | using IsRelocatable = ::std::true_type; 629 | }; 630 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$SharedThing 631 | 632 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$ThingR 633 | #define CXXBRIDGE1_STRUCT_mmscenegraph$ThingR 634 | struct ThingR final : public ::rust::Opaque { 635 | ~ThingR() = delete; 636 | 637 | private: 638 | friend ::rust::layout; 639 | struct layout { 640 | static ::std::size_t size() noexcept; 641 | static ::std::size_t align() noexcept; 642 | }; 643 | }; 644 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$ThingR 645 | 646 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$ReadOperation 647 | #define CXXBRIDGE1_STRUCT_mmscenegraph$ReadOperation 648 | struct ReadOperation final : public ::rust::Opaque { 649 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::uint8_t get_id() const noexcept; 650 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::size_t get_num() const noexcept; 651 | ~ReadOperation() = delete; 652 | 653 | private: 654 | friend ::rust::layout; 655 | struct layout { 656 | static ::std::size_t size() noexcept; 657 | static ::std::size_t align() noexcept; 658 | }; 659 | }; 660 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$ReadOperation 661 | 662 | #ifndef CXXBRIDGE1_STRUCT_mmscenegraph$WriteOperation 663 | #define CXXBRIDGE1_STRUCT_mmscenegraph$WriteOperation 664 | struct WriteOperation final : public ::rust::Opaque { 665 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::uint8_t get_id() const noexcept; 666 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::size_t get_num() const noexcept; 667 | ~WriteOperation() = delete; 668 | 669 | private: 670 | friend ::rust::layout; 671 | struct layout { 672 | static ::std::size_t size() noexcept; 673 | static ::std::size_t align() noexcept; 674 | }; 675 | }; 676 | #endif // CXXBRIDGE1_STRUCT_mmscenegraph$WriteOperation 677 | 678 | extern "C" { 679 | MMSCENEGRAPH_SYMBOL_EXPORT ::mmscenegraph::ThingC *mmscenegraph$cxxbridge1$make_demo(::rust::Str appname) noexcept { 680 | ::std::unique_ptr<::mmscenegraph::ThingC> (*make_demo$)(::rust::Str) = ::mmscenegraph::make_demo; 681 | return make_demo$(appname).release(); 682 | } 683 | 684 | MMSCENEGRAPH_SYMBOL_EXPORT const ::std::string *mmscenegraph$cxxbridge1$get_name(const ::mmscenegraph::ThingC &thing) noexcept { 685 | const ::std::string &(*get_name$)(const ::mmscenegraph::ThingC &) = ::mmscenegraph::get_name; 686 | return &get_name$(thing); 687 | } 688 | 689 | MMSCENEGRAPH_SYMBOL_EXPORT void mmscenegraph$cxxbridge1$do_thing(::mmscenegraph::SharedThing *state) noexcept { 690 | void (*do_thing$)(::mmscenegraph::SharedThing) = ::mmscenegraph::do_thing; 691 | do_thing$(::std::move(*state)); 692 | } 693 | ::std::size_t mmscenegraph$cxxbridge1$ThingR$operator$sizeof() noexcept; 694 | ::std::size_t mmscenegraph$cxxbridge1$ThingR$operator$alignof() noexcept; 695 | 696 | void mmscenegraph$cxxbridge1$print_r(const ::mmscenegraph::ThingR &r) noexcept; 697 | ::std::size_t mmscenegraph$cxxbridge1$ReadOperation$operator$sizeof() noexcept; 698 | ::std::size_t mmscenegraph$cxxbridge1$ReadOperation$operator$alignof() noexcept; 699 | 700 | ::std::uint8_t mmscenegraph$cxxbridge1$ReadOperation$get_id(const ::mmscenegraph::ReadOperation &self) noexcept; 701 | 702 | ::std::size_t mmscenegraph$cxxbridge1$ReadOperation$get_num(const ::mmscenegraph::ReadOperation &self) noexcept; 703 | 704 | ::mmscenegraph::ReadOperation *mmscenegraph$cxxbridge1$new_read_operation(::std::uint8_t id, ::std::size_t num) noexcept; 705 | ::std::size_t mmscenegraph$cxxbridge1$WriteOperation$operator$sizeof() noexcept; 706 | ::std::size_t mmscenegraph$cxxbridge1$WriteOperation$operator$alignof() noexcept; 707 | 708 | ::std::uint8_t mmscenegraph$cxxbridge1$WriteOperation$get_id(const ::mmscenegraph::WriteOperation &self) noexcept; 709 | 710 | ::std::size_t mmscenegraph$cxxbridge1$WriteOperation$get_num(const ::mmscenegraph::WriteOperation &self) noexcept; 711 | 712 | ::mmscenegraph::WriteOperation *mmscenegraph$cxxbridge1$new_write_operation(::std::uint8_t id, ::std::size_t num) noexcept; 713 | } // extern "C" 714 | 715 | namespace geom { 716 | extern "C" { 717 | bool mmscenegraph$geom$cxxbridge1$read(::rust::Slice<::std::uint32_t> buffer) noexcept; 718 | 719 | bool mmscenegraph$geom$cxxbridge1$write(::rust::Slice buffer) noexcept; 720 | } // extern "C" 721 | } // namespace geom 722 | 723 | ::std::size_t ThingR::layout::size() noexcept { 724 | return mmscenegraph$cxxbridge1$ThingR$operator$sizeof(); 725 | } 726 | 727 | ::std::size_t ThingR::layout::align() noexcept { 728 | return mmscenegraph$cxxbridge1$ThingR$operator$alignof(); 729 | } 730 | 731 | MMSCENEGRAPH_SYMBOL_EXPORT void print_r(const ::mmscenegraph::ThingR &r) noexcept { 732 | mmscenegraph$cxxbridge1$print_r(r); 733 | } 734 | 735 | ::std::size_t ReadOperation::layout::size() noexcept { 736 | return mmscenegraph$cxxbridge1$ReadOperation$operator$sizeof(); 737 | } 738 | 739 | ::std::size_t ReadOperation::layout::align() noexcept { 740 | return mmscenegraph$cxxbridge1$ReadOperation$operator$alignof(); 741 | } 742 | 743 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::uint8_t ReadOperation::get_id() const noexcept { 744 | return mmscenegraph$cxxbridge1$ReadOperation$get_id(*this); 745 | } 746 | 747 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::size_t ReadOperation::get_num() const noexcept { 748 | return mmscenegraph$cxxbridge1$ReadOperation$get_num(*this); 749 | } 750 | 751 | MMSCENEGRAPH_SYMBOL_EXPORT ::rust::Box<::mmscenegraph::ReadOperation> new_read_operation(::std::uint8_t id, ::std::size_t num) noexcept { 752 | return ::rust::Box<::mmscenegraph::ReadOperation>::from_raw(mmscenegraph$cxxbridge1$new_read_operation(id, num)); 753 | } 754 | 755 | ::std::size_t WriteOperation::layout::size() noexcept { 756 | return mmscenegraph$cxxbridge1$WriteOperation$operator$sizeof(); 757 | } 758 | 759 | ::std::size_t WriteOperation::layout::align() noexcept { 760 | return mmscenegraph$cxxbridge1$WriteOperation$operator$alignof(); 761 | } 762 | 763 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::uint8_t WriteOperation::get_id() const noexcept { 764 | return mmscenegraph$cxxbridge1$WriteOperation$get_id(*this); 765 | } 766 | 767 | MMSCENEGRAPH_SYMBOL_EXPORT ::std::size_t WriteOperation::get_num() const noexcept { 768 | return mmscenegraph$cxxbridge1$WriteOperation$get_num(*this); 769 | } 770 | 771 | MMSCENEGRAPH_SYMBOL_EXPORT ::rust::Box<::mmscenegraph::WriteOperation> new_write_operation(::std::uint8_t id, ::std::size_t num) noexcept { 772 | return ::rust::Box<::mmscenegraph::WriteOperation>::from_raw(mmscenegraph$cxxbridge1$new_write_operation(id, num)); 773 | } 774 | 775 | namespace geom { 776 | MMSCENEGRAPH_SYMBOL_EXPORT bool read(::rust::Slice<::std::uint32_t> buffer) noexcept { 777 | return mmscenegraph$geom$cxxbridge1$read(buffer); 778 | } 779 | 780 | MMSCENEGRAPH_SYMBOL_EXPORT bool write(::rust::Slice buffer) noexcept { 781 | return mmscenegraph$geom$cxxbridge1$write(buffer); 782 | } 783 | } // namespace geom 784 | } // namespace mmscenegraph 785 | 786 | extern "C" { 787 | ::mmscenegraph::ThingR *cxxbridge1$box$mmscenegraph$ThingR$alloc() noexcept; 788 | void cxxbridge1$box$mmscenegraph$ThingR$dealloc(::mmscenegraph::ThingR *) noexcept; 789 | void cxxbridge1$box$mmscenegraph$ThingR$drop(::rust::Box<::mmscenegraph::ThingR> *ptr) noexcept; 790 | 791 | static_assert(::rust::detail::is_complete<::mmscenegraph::ThingC>::value, "definition of ThingC is required"); 792 | static_assert(sizeof(::std::unique_ptr<::mmscenegraph::ThingC>) == sizeof(void *), ""); 793 | static_assert(alignof(::std::unique_ptr<::mmscenegraph::ThingC>) == alignof(void *), ""); 794 | void cxxbridge1$unique_ptr$mmscenegraph$ThingC$null(::std::unique_ptr<::mmscenegraph::ThingC> *ptr) noexcept { 795 | ::new (ptr) ::std::unique_ptr<::mmscenegraph::ThingC>(); 796 | } 797 | void cxxbridge1$unique_ptr$mmscenegraph$ThingC$raw(::std::unique_ptr<::mmscenegraph::ThingC> *ptr, ::mmscenegraph::ThingC *raw) noexcept { 798 | ::new (ptr) ::std::unique_ptr<::mmscenegraph::ThingC>(raw); 799 | } 800 | const ::mmscenegraph::ThingC *cxxbridge1$unique_ptr$mmscenegraph$ThingC$get(const ::std::unique_ptr<::mmscenegraph::ThingC>& ptr) noexcept { 801 | return ptr.get(); 802 | } 803 | ::mmscenegraph::ThingC *cxxbridge1$unique_ptr$mmscenegraph$ThingC$release(::std::unique_ptr<::mmscenegraph::ThingC>& ptr) noexcept { 804 | return ptr.release(); 805 | } 806 | void cxxbridge1$unique_ptr$mmscenegraph$ThingC$drop(::std::unique_ptr<::mmscenegraph::ThingC> *ptr) noexcept { 807 | ::rust::deleter_if<::rust::detail::is_complete<::mmscenegraph::ThingC>::value>{}(ptr); 808 | } 809 | 810 | ::mmscenegraph::ReadOperation *cxxbridge1$box$mmscenegraph$ReadOperation$alloc() noexcept; 811 | void cxxbridge1$box$mmscenegraph$ReadOperation$dealloc(::mmscenegraph::ReadOperation *) noexcept; 812 | void cxxbridge1$box$mmscenegraph$ReadOperation$drop(::rust::Box<::mmscenegraph::ReadOperation> *ptr) noexcept; 813 | 814 | ::mmscenegraph::WriteOperation *cxxbridge1$box$mmscenegraph$WriteOperation$alloc() noexcept; 815 | void cxxbridge1$box$mmscenegraph$WriteOperation$dealloc(::mmscenegraph::WriteOperation *) noexcept; 816 | void cxxbridge1$box$mmscenegraph$WriteOperation$drop(::rust::Box<::mmscenegraph::WriteOperation> *ptr) noexcept; 817 | } // extern "C" 818 | 819 | namespace rust { 820 | inline namespace cxxbridge1 { 821 | template <> 822 | MMSCENEGRAPH_SYMBOL_EXPORT ::mmscenegraph::ThingR *Box<::mmscenegraph::ThingR>::allocation::alloc() noexcept { 823 | return cxxbridge1$box$mmscenegraph$ThingR$alloc(); 824 | } 825 | template <> 826 | MMSCENEGRAPH_SYMBOL_EXPORT void Box<::mmscenegraph::ThingR>::allocation::dealloc(::mmscenegraph::ThingR *ptr) noexcept { 827 | cxxbridge1$box$mmscenegraph$ThingR$dealloc(ptr); 828 | } 829 | template <> 830 | MMSCENEGRAPH_SYMBOL_EXPORT void Box<::mmscenegraph::ThingR>::drop() noexcept { 831 | cxxbridge1$box$mmscenegraph$ThingR$drop(this); 832 | } 833 | template <> 834 | MMSCENEGRAPH_SYMBOL_EXPORT ::mmscenegraph::ReadOperation *Box<::mmscenegraph::ReadOperation>::allocation::alloc() noexcept { 835 | return cxxbridge1$box$mmscenegraph$ReadOperation$alloc(); 836 | } 837 | template <> 838 | MMSCENEGRAPH_SYMBOL_EXPORT void Box<::mmscenegraph::ReadOperation>::allocation::dealloc(::mmscenegraph::ReadOperation *ptr) noexcept { 839 | cxxbridge1$box$mmscenegraph$ReadOperation$dealloc(ptr); 840 | } 841 | template <> 842 | MMSCENEGRAPH_SYMBOL_EXPORT void Box<::mmscenegraph::ReadOperation>::drop() noexcept { 843 | cxxbridge1$box$mmscenegraph$ReadOperation$drop(this); 844 | } 845 | template <> 846 | MMSCENEGRAPH_SYMBOL_EXPORT ::mmscenegraph::WriteOperation *Box<::mmscenegraph::WriteOperation>::allocation::alloc() noexcept { 847 | return cxxbridge1$box$mmscenegraph$WriteOperation$alloc(); 848 | } 849 | template <> 850 | MMSCENEGRAPH_SYMBOL_EXPORT void Box<::mmscenegraph::WriteOperation>::allocation::dealloc(::mmscenegraph::WriteOperation *ptr) noexcept { 851 | cxxbridge1$box$mmscenegraph$WriteOperation$dealloc(ptr); 852 | } 853 | template <> 854 | MMSCENEGRAPH_SYMBOL_EXPORT void Box<::mmscenegraph::WriteOperation>::drop() noexcept { 855 | cxxbridge1$box$mmscenegraph$WriteOperation$drop(this); 856 | } 857 | } // namespace cxxbridge1 858 | } // namespace rust 859 | -------------------------------------------------------------------------------- /include/cxx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #if defined(_WIN32) 18 | #include 19 | #else 20 | #include 21 | #endif 22 | 23 | namespace rust { 24 | inline namespace cxxbridge1 { 25 | 26 | struct unsafe_bitcopy_t; 27 | 28 | namespace { 29 | template 30 | class impl; 31 | } 32 | 33 | #ifndef CXXBRIDGE1_RUST_STRING 34 | #define CXXBRIDGE1_RUST_STRING 35 | // https://cxx.rs/binding/string.html 36 | class String final { 37 | public: 38 | String() noexcept; 39 | String(const String &) noexcept; 40 | String(String &&) noexcept; 41 | ~String() noexcept; 42 | 43 | String(const std::string &); 44 | String(const char *); 45 | String(const char *, std::size_t); 46 | 47 | String &operator=(const String &) noexcept; 48 | String &operator=(String &&) noexcept; 49 | 50 | explicit operator std::string() const; 51 | 52 | // Note: no null terminator. 53 | const char *data() const noexcept; 54 | std::size_t size() const noexcept; 55 | std::size_t length() const noexcept; 56 | 57 | const char *c_str() noexcept; 58 | 59 | using iterator = char *; 60 | iterator begin() noexcept; 61 | iterator end() noexcept; 62 | 63 | using const_iterator = const char *; 64 | const_iterator begin() const noexcept; 65 | const_iterator end() const noexcept; 66 | const_iterator cbegin() const noexcept; 67 | const_iterator cend() const noexcept; 68 | 69 | bool operator==(const String &) const noexcept; 70 | bool operator!=(const String &) const noexcept; 71 | bool operator<(const String &) const noexcept; 72 | bool operator<=(const String &) const noexcept; 73 | bool operator>(const String &) const noexcept; 74 | bool operator>=(const String &) const noexcept; 75 | 76 | void swap(String &) noexcept; 77 | 78 | // Internal API only intended for the cxxbridge code generator. 79 | String(unsafe_bitcopy_t, const String &) noexcept; 80 | 81 | private: 82 | friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); } 83 | 84 | // Size and alignment statically verified by rust_string.rs. 85 | std::array repr; 86 | }; 87 | #endif // CXXBRIDGE1_RUST_STRING 88 | 89 | #ifndef CXXBRIDGE1_RUST_STR 90 | #define CXXBRIDGE1_RUST_STR 91 | // https://cxx.rs/binding/str.html 92 | class Str final { 93 | public: 94 | Str() noexcept; 95 | Str(const String &) noexcept; 96 | Str(const std::string &); 97 | Str(const char *); 98 | Str(const char *, std::size_t); 99 | 100 | Str &operator=(const Str &) noexcept = default; 101 | 102 | explicit operator std::string() const; 103 | 104 | // Note: no null terminator. 105 | const char *data() const noexcept; 106 | std::size_t size() const noexcept; 107 | std::size_t length() const noexcept; 108 | 109 | // Important in order for System V ABI to pass in registers. 110 | Str(const Str &) noexcept = default; 111 | ~Str() noexcept = default; 112 | 113 | using iterator = const char *; 114 | using const_iterator = const char *; 115 | const_iterator begin() const noexcept; 116 | const_iterator end() const noexcept; 117 | const_iterator cbegin() const noexcept; 118 | const_iterator cend() const noexcept; 119 | 120 | bool operator==(const Str &) const noexcept; 121 | bool operator!=(const Str &) const noexcept; 122 | bool operator<(const Str &) const noexcept; 123 | bool operator<=(const Str &) const noexcept; 124 | bool operator>(const Str &) const noexcept; 125 | bool operator>=(const Str &) const noexcept; 126 | 127 | void swap(Str &) noexcept; 128 | 129 | private: 130 | class uninit; 131 | Str(uninit) noexcept; 132 | friend impl; 133 | 134 | std::array repr; 135 | }; 136 | #endif // CXXBRIDGE1_RUST_STR 137 | 138 | #ifndef CXXBRIDGE1_RUST_SLICE 139 | namespace detail { 140 | template 141 | struct copy_assignable_if {}; 142 | 143 | template <> 144 | struct copy_assignable_if { 145 | copy_assignable_if() noexcept = default; 146 | copy_assignable_if(const copy_assignable_if &) noexcept = default; 147 | copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete; 148 | copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default; 149 | }; 150 | } // namespace detail 151 | 152 | // https://cxx.rs/binding/slice.html 153 | template 154 | class Slice final 155 | : private detail::copy_assignable_if::value> { 156 | public: 157 | using value_type = T; 158 | 159 | Slice() noexcept; 160 | Slice(T *, std::size_t count) noexcept; 161 | 162 | Slice &operator=(const Slice &) noexcept = default; 163 | Slice &operator=(Slice &&) noexcept = default; 164 | 165 | T *data() const noexcept; 166 | std::size_t size() const noexcept; 167 | std::size_t length() const noexcept; 168 | bool empty() const noexcept; 169 | 170 | T &operator[](std::size_t n) const noexcept; 171 | T &at(std::size_t n) const; 172 | T &front() const noexcept; 173 | T &back() const noexcept; 174 | 175 | // Important in order for System V ABI to pass in registers. 176 | Slice(const Slice &) noexcept = default; 177 | ~Slice() noexcept = default; 178 | 179 | class iterator; 180 | iterator begin() const noexcept; 181 | iterator end() const noexcept; 182 | 183 | void swap(Slice &) noexcept; 184 | 185 | private: 186 | class uninit; 187 | Slice(uninit) noexcept; 188 | friend impl; 189 | friend void sliceInit(void *, const void *, std::size_t) noexcept; 190 | friend void *slicePtr(const void *) noexcept; 191 | friend std::size_t sliceLen(const void *) noexcept; 192 | 193 | std::array repr; 194 | }; 195 | 196 | template 197 | class Slice::iterator final { 198 | public: 199 | using iterator_category = std::random_access_iterator_tag; 200 | using value_type = T; 201 | using difference_type = std::ptrdiff_t; 202 | using pointer = typename std::add_pointer::type; 203 | using reference = typename std::add_lvalue_reference::type; 204 | 205 | reference operator*() const noexcept; 206 | pointer operator->() const noexcept; 207 | reference operator[](difference_type) const noexcept; 208 | 209 | iterator &operator++() noexcept; 210 | iterator operator++(int) noexcept; 211 | iterator &operator--() noexcept; 212 | iterator operator--(int) noexcept; 213 | 214 | iterator &operator+=(difference_type) noexcept; 215 | iterator &operator-=(difference_type) noexcept; 216 | iterator operator+(difference_type) const noexcept; 217 | iterator operator-(difference_type) const noexcept; 218 | difference_type operator-(const iterator &) const noexcept; 219 | 220 | bool operator==(const iterator &) const noexcept; 221 | bool operator!=(const iterator &) const noexcept; 222 | bool operator<(const iterator &) const noexcept; 223 | bool operator<=(const iterator &) const noexcept; 224 | bool operator>(const iterator &) const noexcept; 225 | bool operator>=(const iterator &) const noexcept; 226 | 227 | private: 228 | friend class Slice; 229 | void *pos; 230 | std::size_t stride; 231 | }; 232 | #endif // CXXBRIDGE1_RUST_SLICE 233 | 234 | #ifndef CXXBRIDGE1_RUST_BOX 235 | // https://cxx.rs/binding/box.html 236 | template 237 | class Box final { 238 | public: 239 | using element_type = T; 240 | using const_pointer = 241 | typename std::add_pointer::type>::type; 242 | using pointer = typename std::add_pointer::type; 243 | 244 | Box() = delete; 245 | Box(Box &&) noexcept; 246 | ~Box() noexcept; 247 | 248 | explicit Box(const T &); 249 | explicit Box(T &&); 250 | 251 | Box &operator=(Box &&) noexcept; 252 | 253 | const T *operator->() const noexcept; 254 | const T &operator*() const noexcept; 255 | T *operator->() noexcept; 256 | T &operator*() noexcept; 257 | 258 | template 259 | static Box in_place(Fields &&...); 260 | 261 | void swap(Box &) noexcept; 262 | 263 | // Important: requires that `raw` came from an into_raw call. Do not pass a 264 | // pointer from `new` or any other source. 265 | static Box from_raw(T *) noexcept; 266 | 267 | T *into_raw() noexcept; 268 | 269 | /* Deprecated */ using value_type = element_type; 270 | 271 | private: 272 | class uninit; 273 | class allocation; 274 | Box(uninit) noexcept; 275 | void drop() noexcept; 276 | 277 | friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); } 278 | 279 | T *ptr; 280 | }; 281 | #endif // CXXBRIDGE1_RUST_BOX 282 | 283 | #ifndef CXXBRIDGE1_RUST_VEC 284 | // https://cxx.rs/binding/vec.html 285 | template 286 | class Vec final { 287 | public: 288 | using value_type = T; 289 | 290 | Vec() noexcept; 291 | Vec(std::initializer_list); 292 | Vec(const Vec &); 293 | Vec(Vec &&) noexcept; 294 | ~Vec() noexcept; 295 | 296 | Vec &operator=(Vec &&) noexcept; 297 | Vec &operator=(const Vec &); 298 | 299 | std::size_t size() const noexcept; 300 | bool empty() const noexcept; 301 | const T *data() const noexcept; 302 | T *data() noexcept; 303 | std::size_t capacity() const noexcept; 304 | 305 | const T &operator[](std::size_t n) const noexcept; 306 | const T &at(std::size_t n) const; 307 | const T &front() const noexcept; 308 | const T &back() const noexcept; 309 | 310 | T &operator[](std::size_t n) noexcept; 311 | T &at(std::size_t n); 312 | T &front() noexcept; 313 | T &back() noexcept; 314 | 315 | void reserve(std::size_t new_cap); 316 | void push_back(const T &value); 317 | void push_back(T &&value); 318 | template 319 | void emplace_back(Args &&... args); 320 | 321 | using iterator = typename Slice::iterator; 322 | iterator begin() noexcept; 323 | iterator end() noexcept; 324 | 325 | using const_iterator = typename Slice::iterator; 326 | const_iterator begin() const noexcept; 327 | const_iterator end() const noexcept; 328 | const_iterator cbegin() const noexcept; 329 | const_iterator cend() const noexcept; 330 | 331 | void swap(Vec &) noexcept; 332 | 333 | // Internal API only intended for the cxxbridge code generator. 334 | Vec(unsafe_bitcopy_t, const Vec &) noexcept; 335 | 336 | private: 337 | void reserve_total(std::size_t cap) noexcept; 338 | void set_len(std::size_t len) noexcept; 339 | void drop() noexcept; 340 | 341 | friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); } 342 | 343 | // Size and alignment statically verified by rust_vec.rs. 344 | std::array repr; 345 | }; 346 | #endif // CXXBRIDGE1_RUST_VEC 347 | 348 | #ifndef CXXBRIDGE1_RUST_FN 349 | // https://cxx.rs/binding/fn.html 350 | template 351 | class Fn; 352 | 353 | template 354 | class Fn final { 355 | public: 356 | Ret operator()(Args... args) const noexcept; 357 | Fn operator*() const noexcept; 358 | 359 | private: 360 | Ret (*trampoline)(Args..., void *fn) noexcept; 361 | void *fn; 362 | }; 363 | #endif // CXXBRIDGE1_RUST_FN 364 | 365 | #ifndef CXXBRIDGE1_RUST_ERROR 366 | #define CXXBRIDGE1_RUST_ERROR 367 | // https://cxx.rs/binding/result.html 368 | class Error final : public std::exception { 369 | public: 370 | Error(const Error &); 371 | Error(Error &&) noexcept; 372 | ~Error() noexcept override; 373 | 374 | Error &operator=(const Error &); 375 | Error &operator=(Error &&) noexcept; 376 | 377 | const char *what() const noexcept override; 378 | 379 | private: 380 | Error() noexcept = default; 381 | friend impl; 382 | const char *msg; 383 | std::size_t len; 384 | }; 385 | #endif // CXXBRIDGE1_RUST_ERROR 386 | 387 | #ifndef CXXBRIDGE1_RUST_ISIZE 388 | #define CXXBRIDGE1_RUST_ISIZE 389 | #if defined(_WIN32) 390 | using isize = SSIZE_T; 391 | #else 392 | using isize = ssize_t; 393 | #endif 394 | #endif // CXXBRIDGE1_RUST_ISIZE 395 | 396 | std::ostream &operator<<(std::ostream &, const String &); 397 | std::ostream &operator<<(std::ostream &, const Str &); 398 | 399 | #ifndef CXXBRIDGE1_RUST_OPAQUE 400 | #define CXXBRIDGE1_RUST_OPAQUE 401 | // Base class of generated opaque Rust types. 402 | class Opaque { 403 | public: 404 | Opaque() = delete; 405 | Opaque(const Opaque &) = delete; 406 | ~Opaque() = delete; 407 | }; 408 | #endif // CXXBRIDGE1_RUST_OPAQUE 409 | 410 | template 411 | std::size_t size_of(); 412 | template 413 | std::size_t align_of(); 414 | 415 | // IsRelocatable is used in assertions that a C++ type passed by value 416 | // between Rust and C++ is soundly relocatable by Rust. 417 | // 418 | // There may be legitimate reasons to opt out of the check for support of types 419 | // that the programmer knows are soundly Rust-movable despite not being 420 | // recognized as such by the C++ type system due to a move constructor or 421 | // destructor. To opt out of the relocatability check, do either of the 422 | // following things in any header used by `include!` in the bridge. 423 | // 424 | // --- if you define the type: 425 | // struct MyType { 426 | // ... 427 | // + using IsRelocatable = std::true_type; 428 | // }; 429 | // 430 | // --- otherwise: 431 | // + template <> 432 | // + struct rust::IsRelocatable : std::true_type {}; 433 | template 434 | struct IsRelocatable; 435 | 436 | using u8 = std::uint8_t; 437 | using u16 = std::uint16_t; 438 | using u32 = std::uint32_t; 439 | using u64 = std::uint64_t; 440 | using usize = std::size_t; // see static asserts in cxx.cc 441 | using i8 = std::int8_t; 442 | using i16 = std::int16_t; 443 | using i32 = std::int32_t; 444 | using i64 = std::int64_t; 445 | using f32 = float; 446 | using f64 = double; 447 | 448 | // Snake case aliases for use in code that uses this style for type names. 449 | using string = String; 450 | using str = Str; 451 | template 452 | using slice = Slice; 453 | template 454 | using box = Box; 455 | template 456 | using vec = Vec; 457 | using error = Error; 458 | template 459 | using fn = Fn; 460 | template 461 | using is_relocatable = IsRelocatable; 462 | 463 | 464 | 465 | //////////////////////////////////////////////////////////////////////////////// 466 | /// end public API, begin implementation details 467 | 468 | #ifndef CXXBRIDGE1_PANIC 469 | #define CXXBRIDGE1_PANIC 470 | template 471 | void panic [[noreturn]] (const char *msg); 472 | #endif // CXXBRIDGE1_PANIC 473 | 474 | #ifndef CXXBRIDGE1_RUST_FN 475 | #define CXXBRIDGE1_RUST_FN 476 | template 477 | Ret Fn::operator()(Args... args) const noexcept { 478 | return (*this->trampoline)(std::move(args)..., this->fn); 479 | } 480 | 481 | template 482 | Fn Fn::operator*() const noexcept { 483 | return *this; 484 | } 485 | #endif // CXXBRIDGE1_RUST_FN 486 | 487 | #ifndef CXXBRIDGE1_RUST_BITCOPY 488 | #define CXXBRIDGE1_RUST_BITCOPY 489 | struct unsafe_bitcopy_t final { 490 | explicit unsafe_bitcopy_t() = default; 491 | }; 492 | 493 | constexpr unsafe_bitcopy_t unsafe_bitcopy{}; 494 | #endif // CXXBRIDGE1_RUST_BITCOPY 495 | 496 | #ifndef CXXBRIDGE1_RUST_SLICE 497 | #define CXXBRIDGE1_RUST_SLICE 498 | template 499 | Slice::Slice() noexcept { 500 | sliceInit(this, reinterpret_cast(align_of()), 0); 501 | } 502 | 503 | template 504 | Slice::Slice(T *s, std::size_t count) noexcept { 505 | sliceInit(this, const_cast::type *>(s), count); 506 | } 507 | 508 | template 509 | T *Slice::data() const noexcept { 510 | return reinterpret_cast(slicePtr(this)); 511 | } 512 | 513 | template 514 | std::size_t Slice::size() const noexcept { 515 | return sliceLen(this); 516 | } 517 | 518 | template 519 | std::size_t Slice::length() const noexcept { 520 | return this->size(); 521 | } 522 | 523 | template 524 | bool Slice::empty() const noexcept { 525 | return this->size() == 0; 526 | } 527 | 528 | template 529 | T &Slice::operator[](std::size_t n) const noexcept { 530 | assert(n < this->size()); 531 | auto pos = static_cast(slicePtr(this)) + size_of() * n; 532 | return *reinterpret_cast(pos); 533 | } 534 | 535 | template 536 | T &Slice::at(std::size_t n) const { 537 | if (n >= this->size()) { 538 | panic("rust::Slice index out of range"); 539 | } 540 | return (*this)[n]; 541 | } 542 | 543 | template 544 | T &Slice::front() const noexcept { 545 | assert(!this->empty()); 546 | return (*this)[0]; 547 | } 548 | 549 | template 550 | T &Slice::back() const noexcept { 551 | assert(!this->empty()); 552 | return (*this)[this->size() - 1]; 553 | } 554 | 555 | template 556 | typename Slice::iterator::reference 557 | Slice::iterator::operator*() const noexcept { 558 | return *static_cast(this->pos); 559 | } 560 | 561 | template 562 | typename Slice::iterator::pointer 563 | Slice::iterator::operator->() const noexcept { 564 | return static_cast(this->pos); 565 | } 566 | 567 | template 568 | typename Slice::iterator::reference Slice::iterator::operator[]( 569 | typename Slice::iterator::difference_type n) const noexcept { 570 | auto pos = static_cast(this->pos) + this->stride * n; 571 | return *reinterpret_cast(pos); 572 | } 573 | 574 | template 575 | typename Slice::iterator &Slice::iterator::operator++() noexcept { 576 | this->pos = static_cast(this->pos) + this->stride; 577 | return *this; 578 | } 579 | 580 | template 581 | typename Slice::iterator Slice::iterator::operator++(int) noexcept { 582 | auto ret = iterator(*this); 583 | this->pos = static_cast(this->pos) + this->stride; 584 | return ret; 585 | } 586 | 587 | template 588 | typename Slice::iterator &Slice::iterator::operator--() noexcept { 589 | this->pos = static_cast(this->pos) - this->stride; 590 | return *this; 591 | } 592 | 593 | template 594 | typename Slice::iterator Slice::iterator::operator--(int) noexcept { 595 | auto ret = iterator(*this); 596 | this->pos = static_cast(this->pos) - this->stride; 597 | return ret; 598 | } 599 | 600 | template 601 | typename Slice::iterator &Slice::iterator::operator+=( 602 | typename Slice::iterator::difference_type n) noexcept { 603 | this->pos = static_cast(this->pos) + this->stride * n; 604 | return *this; 605 | } 606 | 607 | template 608 | typename Slice::iterator &Slice::iterator::operator-=( 609 | typename Slice::iterator::difference_type n) noexcept { 610 | this->pos = static_cast(this->pos) - this->stride * n; 611 | return *this; 612 | } 613 | 614 | template 615 | typename Slice::iterator Slice::iterator::operator+( 616 | typename Slice::iterator::difference_type n) const noexcept { 617 | auto ret = iterator(*this); 618 | ret.pos = static_cast(this->pos) + this->stride * n; 619 | return ret; 620 | } 621 | 622 | template 623 | typename Slice::iterator Slice::iterator::operator-( 624 | typename Slice::iterator::difference_type n) const noexcept { 625 | auto ret = iterator(*this); 626 | ret.pos = static_cast(this->pos) - this->stride * n; 627 | return ret; 628 | } 629 | 630 | template 631 | typename Slice::iterator::difference_type 632 | Slice::iterator::operator-(const iterator &other) const noexcept { 633 | auto diff = std::distance(static_cast(other.pos), 634 | static_cast(this->pos)); 635 | return diff / this->stride; 636 | } 637 | 638 | template 639 | bool Slice::iterator::operator==(const iterator &other) const noexcept { 640 | return this->pos == other.pos; 641 | } 642 | 643 | template 644 | bool Slice::iterator::operator!=(const iterator &other) const noexcept { 645 | return this->pos != other.pos; 646 | } 647 | 648 | template 649 | bool Slice::iterator::operator<(const iterator &other) const noexcept { 650 | return this->pos < other.pos; 651 | } 652 | 653 | template 654 | bool Slice::iterator::operator<=(const iterator &other) const noexcept { 655 | return this->pos <= other.pos; 656 | } 657 | 658 | template 659 | bool Slice::iterator::operator>(const iterator &other) const noexcept { 660 | return this->pos > other.pos; 661 | } 662 | 663 | template 664 | bool Slice::iterator::operator>=(const iterator &other) const noexcept { 665 | return this->pos >= other.pos; 666 | } 667 | 668 | template 669 | typename Slice::iterator Slice::begin() const noexcept { 670 | iterator it; 671 | it.pos = slicePtr(this); 672 | it.stride = size_of(); 673 | return it; 674 | } 675 | 676 | template 677 | typename Slice::iterator Slice::end() const noexcept { 678 | iterator it = this->begin(); 679 | it.pos = static_cast(it.pos) + it.stride * this->size(); 680 | return it; 681 | } 682 | 683 | template 684 | void Slice::swap(Slice &rhs) noexcept { 685 | std::swap(*this, rhs); 686 | } 687 | #endif // CXXBRIDGE1_RUST_SLICE 688 | 689 | #ifndef CXXBRIDGE1_RUST_BOX 690 | #define CXXBRIDGE1_RUST_BOX 691 | template 692 | class Box::uninit {}; 693 | 694 | template 695 | class Box::allocation { 696 | static T *alloc() noexcept; 697 | static void dealloc(T *) noexcept; 698 | 699 | public: 700 | allocation() noexcept : ptr(alloc()) {} 701 | ~allocation() noexcept { 702 | if (this->ptr) { 703 | dealloc(this->ptr); 704 | } 705 | } 706 | T *ptr; 707 | }; 708 | 709 | template 710 | Box::Box(Box &&other) noexcept : ptr(other.ptr) { 711 | other.ptr = nullptr; 712 | } 713 | 714 | template 715 | Box::Box(const T &val) { 716 | allocation alloc; 717 | ::new (alloc.ptr) T(val); 718 | this->ptr = alloc.ptr; 719 | alloc.ptr = nullptr; 720 | } 721 | 722 | template 723 | Box::Box(T &&val) { 724 | allocation alloc; 725 | ::new (alloc.ptr) T(std::move(val)); 726 | this->ptr = alloc.ptr; 727 | alloc.ptr = nullptr; 728 | } 729 | 730 | template 731 | Box::~Box() noexcept { 732 | if (this->ptr) { 733 | this->drop(); 734 | } 735 | } 736 | 737 | template 738 | Box &Box::operator=(Box &&other) noexcept { 739 | if (this->ptr) { 740 | this->drop(); 741 | } 742 | this->ptr = other.ptr; 743 | other.ptr = nullptr; 744 | return *this; 745 | } 746 | 747 | template 748 | const T *Box::operator->() const noexcept { 749 | return this->ptr; 750 | } 751 | 752 | template 753 | const T &Box::operator*() const noexcept { 754 | return *this->ptr; 755 | } 756 | 757 | template 758 | T *Box::operator->() noexcept { 759 | return this->ptr; 760 | } 761 | 762 | template 763 | T &Box::operator*() noexcept { 764 | return *this->ptr; 765 | } 766 | 767 | template 768 | template 769 | Box Box::in_place(Fields &&... fields) { 770 | allocation alloc; 771 | auto ptr = alloc.ptr; 772 | ::new (ptr) T{std::forward(fields)...}; 773 | alloc.ptr = nullptr; 774 | return from_raw(ptr); 775 | } 776 | 777 | template 778 | void Box::swap(Box &rhs) noexcept { 779 | using std::swap; 780 | swap(this->ptr, rhs.ptr); 781 | } 782 | 783 | template 784 | Box Box::from_raw(T *raw) noexcept { 785 | Box box = uninit{}; 786 | box.ptr = raw; 787 | return box; 788 | } 789 | 790 | template 791 | T *Box::into_raw() noexcept { 792 | T *raw = this->ptr; 793 | this->ptr = nullptr; 794 | return raw; 795 | } 796 | 797 | template 798 | Box::Box(uninit) noexcept {} 799 | #endif // CXXBRIDGE1_RUST_BOX 800 | 801 | #ifndef CXXBRIDGE1_RUST_VEC 802 | #define CXXBRIDGE1_RUST_VEC 803 | template 804 | Vec::Vec(std::initializer_list init) : Vec{} { 805 | this->reserve_total(init.size()); 806 | std::move(init.begin(), init.end(), std::back_inserter(*this)); 807 | } 808 | 809 | template 810 | Vec::Vec(const Vec &other) : Vec() { 811 | this->reserve_total(other.size()); 812 | std::copy(other.begin(), other.end(), std::back_inserter(*this)); 813 | } 814 | 815 | template 816 | Vec::Vec(Vec &&other) noexcept : repr(other.repr) { 817 | new (&other) Vec(); 818 | } 819 | 820 | template 821 | Vec::~Vec() noexcept { 822 | this->drop(); 823 | } 824 | 825 | template 826 | Vec &Vec::operator=(Vec &&other) noexcept { 827 | if (this != &other) { 828 | this->drop(); 829 | this->repr = other.repr; 830 | new (&other) Vec(); 831 | } 832 | return *this; 833 | } 834 | 835 | template 836 | Vec &Vec::operator=(const Vec &other) { 837 | if (this != &other) { 838 | this->drop(); 839 | new (this) Vec(other); 840 | } 841 | return *this; 842 | } 843 | 844 | template 845 | bool Vec::empty() const noexcept { 846 | return this->size() == 0; 847 | } 848 | 849 | template 850 | T *Vec::data() noexcept { 851 | return const_cast(const_cast *>(this)->data()); 852 | } 853 | 854 | template 855 | const T &Vec::operator[](std::size_t n) const noexcept { 856 | assert(n < this->size()); 857 | auto data = reinterpret_cast(this->data()); 858 | return *reinterpret_cast(data + n * size_of()); 859 | } 860 | 861 | template 862 | const T &Vec::at(std::size_t n) const { 863 | if (n >= this->size()) { 864 | panic("rust::Vec index out of range"); 865 | } 866 | return (*this)[n]; 867 | } 868 | 869 | template 870 | const T &Vec::front() const noexcept { 871 | assert(!this->empty()); 872 | return (*this)[0]; 873 | } 874 | 875 | template 876 | const T &Vec::back() const noexcept { 877 | assert(!this->empty()); 878 | return (*this)[this->size() - 1]; 879 | } 880 | 881 | template 882 | T &Vec::operator[](std::size_t n) noexcept { 883 | assert(n < this->size()); 884 | auto data = reinterpret_cast(this->data()); 885 | return *reinterpret_cast(data + n * size_of()); 886 | } 887 | 888 | template 889 | T &Vec::at(std::size_t n) { 890 | if (n >= this->size()) { 891 | panic("rust::Vec index out of range"); 892 | } 893 | return (*this)[n]; 894 | } 895 | 896 | template 897 | T &Vec::front() noexcept { 898 | assert(!this->empty()); 899 | return (*this)[0]; 900 | } 901 | 902 | template 903 | T &Vec::back() noexcept { 904 | assert(!this->empty()); 905 | return (*this)[this->size() - 1]; 906 | } 907 | 908 | template 909 | void Vec::reserve(std::size_t new_cap) { 910 | this->reserve_total(new_cap); 911 | } 912 | 913 | template 914 | void Vec::push_back(const T &value) { 915 | this->emplace_back(value); 916 | } 917 | 918 | template 919 | void Vec::push_back(T &&value) { 920 | this->emplace_back(std::move(value)); 921 | } 922 | 923 | template 924 | template 925 | void Vec::emplace_back(Args &&... args) { 926 | auto size = this->size(); 927 | this->reserve_total(size + 1); 928 | ::new (reinterpret_cast(reinterpret_cast(this->data()) + 929 | size * size_of())) 930 | T(std::forward(args)...); 931 | this->set_len(size + 1); 932 | } 933 | 934 | template 935 | typename Vec::iterator Vec::begin() noexcept { 936 | return Slice(this->data(), this->size()).begin(); 937 | } 938 | 939 | template 940 | typename Vec::iterator Vec::end() noexcept { 941 | return Slice(this->data(), this->size()).end(); 942 | } 943 | 944 | template 945 | typename Vec::const_iterator Vec::begin() const noexcept { 946 | return this->cbegin(); 947 | } 948 | 949 | template 950 | typename Vec::const_iterator Vec::end() const noexcept { 951 | return this->cend(); 952 | } 953 | 954 | template 955 | typename Vec::const_iterator Vec::cbegin() const noexcept { 956 | return Slice(this->data(), this->size()).begin(); 957 | } 958 | 959 | template 960 | typename Vec::const_iterator Vec::cend() const noexcept { 961 | return Slice(this->data(), this->size()).end(); 962 | } 963 | 964 | template 965 | void Vec::swap(Vec &rhs) noexcept { 966 | using std::swap; 967 | swap(this->repr, rhs.repr); 968 | } 969 | 970 | // Internal API only intended for the cxxbridge code generator. 971 | template 972 | Vec::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {} 973 | #endif // CXXBRIDGE1_RUST_VEC 974 | 975 | #ifndef CXXBRIDGE1_IS_COMPLETE 976 | #define CXXBRIDGE1_IS_COMPLETE 977 | namespace detail { 978 | namespace { 979 | template 980 | struct is_complete : std::false_type {}; 981 | template 982 | struct is_complete : std::true_type {}; 983 | } // namespace 984 | } // namespace detail 985 | #endif // CXXBRIDGE1_IS_COMPLETE 986 | 987 | #ifndef CXXBRIDGE1_LAYOUT 988 | #define CXXBRIDGE1_LAYOUT 989 | class layout { 990 | template 991 | friend std::size_t size_of(); 992 | template 993 | friend std::size_t align_of(); 994 | template 995 | static typename std::enable_if::value, 996 | std::size_t>::type 997 | do_size_of() { 998 | return T::layout::size(); 999 | } 1000 | template 1001 | static typename std::enable_if::value, 1002 | std::size_t>::type 1003 | do_size_of() { 1004 | return sizeof(T); 1005 | } 1006 | template 1007 | static 1008 | typename std::enable_if::value, std::size_t>::type 1009 | size_of() { 1010 | return do_size_of(); 1011 | } 1012 | template 1013 | static typename std::enable_if::value, 1014 | std::size_t>::type 1015 | do_align_of() { 1016 | return T::layout::align(); 1017 | } 1018 | template 1019 | static typename std::enable_if::value, 1020 | std::size_t>::type 1021 | do_align_of() { 1022 | return alignof(T); 1023 | } 1024 | template 1025 | static 1026 | typename std::enable_if::value, std::size_t>::type 1027 | align_of() { 1028 | return do_align_of(); 1029 | } 1030 | }; 1031 | 1032 | template 1033 | std::size_t size_of() { 1034 | return layout::size_of(); 1035 | } 1036 | 1037 | template 1038 | std::size_t align_of() { 1039 | return layout::align_of(); 1040 | } 1041 | #endif // CXXBRIDGE1_LAYOUT 1042 | 1043 | #ifndef CXXBRIDGE1_RELOCATABLE 1044 | #define CXXBRIDGE1_RELOCATABLE 1045 | namespace detail { 1046 | template 1047 | struct make_void { 1048 | using type = void; 1049 | }; 1050 | 1051 | template 1052 | using void_t = typename make_void::type; 1053 | 1054 | template class, typename...> 1055 | struct detect : std::false_type {}; 1056 | template