dtolnay / cxx

Safe interop between Rust and C++
https://cxx.rs
Apache License 2.0
5.68k stars 322 forks source link

error: template argument 1 is invalid #1276

Closed taqtiqa-mark closed 8 months ago

taqtiqa-mark commented 9 months ago

Thanks for all the work on cxx. This is my first FFI build/project - apologies if I've done something silly... appreciate any hints or tips.

I observe this error:

cargo:warning=/home/user/src/zno-fhe-src/target/x86_64-unknown-linux-gnu/debug/build/zno-helib-sys-9e1c57f56ad6e2da/out/cxxbridge/sources/zno-helib-sys/src/cxx-bridges/context.rs.cc:827:67: error: template argument 1 is invalid

  cargo:warning=  827 |   ::rust::deleter_if<::rust::detail::is_complete<::Context>::value>{}(ptr);

  cargo:warning=      |                                                                   ^

  exit status: 1

  --- stderr

  CXX include path:
    /home/user/src/zno-fhe-src/target/x86_64-unknown-linux-gnu/debug/build/zno-helib-sys-9e1c57f56ad6e2da/out/cxxbridge/include
    /home/user/src/zno-fhe-src/target/x86_64-unknown-linux-gnu/debug/build/zno-helib-sys-9e1c57f56ad6e2da/out/cxxbridge/crate

  error occurred: Command "c++" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-gdwarf-4" "-fno-omit-frame-pointer" "-m64" "-I" "/home/user/src/zno-fhe-src/target/x86_64-unknown-linux-gnu/debug/build/zno-helib-sys-9e1c57f56ad6e2da/out/cxxbridge/include" "-I" "/home/user/src/zno-fhe-src/target/x86_64-unknown-linux-gnu/debug/build/zno-helib-sys-9e1c57f56ad6e2da/out/cxxbridge/crate" "-I" "/home/user/src/zno-fhe-src/zno-helib-sys/ffi" "-Wall" "-Wextra" "-std=c++17" "-o" "/home/user/src/zno-fhe-src/target/x86_64-unknown-linux-gnu/debug/build/zno-helib-sys-9e1c57f56ad6e2da/out/04463708872899c9-context.rs.o" "-c" "/home/user/src/zno-fhe-src/target/x86_64-unknown-linux-gnu/debug/build/zno-helib-sys-9e1c57f56ad6e2da/out/cxxbridge/sources/zno-helib-sys/src/cxx-bridges/context.rs.cc" with args "c++" did not execute successfully (status code exit status: 1).

When I build or test this cxx-bridge:

context.rs ```rust use cxx::UniquePtr; use std::os::raw::c_long; use cxx::rust::String; use std::convert::TryInto; // Import the BGV struct and its fields use super::bgv::*; #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("zno-helib-sys/ffi/ffi_wrapper.h"); type Context; type ContextBuilderWrapper; fn create_context_builder() -> UniquePtr; fn build(builder: &mut UniquePtr) -> UniquePtr; fn set_m(builder: &mut UniquePtr, m: i64); fn set_p(builder: &mut UniquePtr, p: i64); fn set_r(builder: &mut UniquePtr, r: i64); // ... other methods // For vectors, you might need to handle conversions yourself // or write additional helper functions in C++ fn set_gens(builder: &mut UniquePtr, gens: &CxxVector); fn set_ords(builder: &mut UniquePtr, ords: &CxxVector); // ... other methods fn create_bgv_context( m: u64, p: u64, r: u64, gens: Vec, ords: Vec, ) -> UniquePtr; // fn create_generic_context( // m: i64, // p: i64, // r: i64, // gens: Vec, // ords: Vec, // mparams: Option, // bparams: Option, // ) -> UniquePtr; // Declare the new functions you've exposed in C++ fn get_m(context: &Context) -> u64; fn is_bootstrappable(context: &Context) -> bool; } // External Rust functions, used to convert Rust types into types that can be used in C++: extern "Rust" { fn convert_to_vec(s: &str) -> Vec; } } // Define the Rust struct to represent the C++ Context class struct Context { // Fields matching the C++ constructor arguments m: c_long, p: c_long, r: c_long, gens: Vec, ords: Vec, } // Define methods for the Rust Context struct impl Context { pub fn convert_to_vec(s: &str) -> Vec { s.split(',') .filter_map(|s| s.parse::().ok()) .collect() } // Create Rust functions to create BGV contexts using FFI pub fn create_bgv_context_default() -> UniquePtr { ffi::create_context_default() } // Define a method to create a Context instance using one constructor pub fn create_bgv_context_params(bgvs: BGV) -> UniquePtr { let gens_vec: Vec = bgvs.gens.iter().cloned().collect(); let ords_vec: Vec = bgvs.ords.iter().cloned().collect(); ffi::create_context_params(bgvs.m, bgvs.p, bgvs.r, gens_vec, ords_vec) } pub fn create_bgv_context_params_extended(bgvs: BGV, mparams: Option, bparams: Option) -> UniquePtr { let gens_vec: Vec = bgvs.gens.iter().cloned().collect(); let ords_vec: Vec = bgvs.ords.iter().cloned().collect(); ffi::create_context_params_extended(bgvs.m, bgvs.p, bgvs.r, gens_vec, ords_vec, mparams, bparams) } pub fn create_bgv_context_serializable(content: SerializableContent) -> UniquePtr { ffi::create_context_serializable(content) } } ```

and this is the build script:

buil.rs ```rust use std::collections::HashSet; use std::env; use std::ffi::OsString; use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; fn main() -> miette::Result<()> { // cxx_build::CFG.exported_header_prefixes = vec!["helib"]; // Determine the project directory let project_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let ffi_dir = Path::new(&project_dir).join("ffi"); let helib_dir = Path::new(&project_dir).join("src").join("helib_pack"); // let helib_dir = Path::new(&ffi_dir); let helib_lib_dir = helib_dir.join("lib"); let helib_include_dir = helib_dir.join("include"); // Compile ffi_wrapper.cpp separately let cpp_source = ffi_dir.join("ffi_wrapper.cpp"); let cpp_output = ffi_dir.join("ffi_wrapper"); // Output binary name // Copy ffi_wrapper.h and ffi_wrapper.cpp alongside helib.h let _ = fs::copy(ffi_dir.join("ffi_wrapper.h"), helib_include_dir.join("ffi_wrapper.h")); let _ = fs::copy(ffi_dir.join("ffi_wrapper.cpp"), cpp_source.clone()); // Retrieve the CARGO_MANIFEST_DIR and OUT_DIR environment variables let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap(); let source_dir = Path::new(&manifest_dir).join("src/helib_pack/include"); let target_dir = Path::new(&manifest_dir).join("ffi"); // Recursively copy files from source to target directory if let Err(e) = copy_dir_to(&source_dir, &target_dir) { panic!("Failed to copy header files: {}", e); } // Allows Rust to call C++ functions defined in "ffi_wrapper.cpp" and use // any C++ functionality encapsulated in "ffi_wrapper.cpp" separately from the original C++ code. // let _ = Command::new("g++") // .args(&["-std=c++17", "-shared", "-fPIC", "-o", &cpp_output.to_string_lossy(), &cpp_source.to_string_lossy()]) // .status() // .expect("Failed to compile ffi_wrapper.cpp"); // // Generate Rust bindings using cxx_build // cxx_build::bridge("src/cxx-bridges/context.rs") // .file(cpp_source.to_string_lossy()) // Include the necessary C++ source files // .flag_if_supported("-std=c++17") // .compile("ffi_wrapper"); // Output the linker flags for the compiled wrapper C++ source println!("cargo:rustc-link-search=native={}", ffi_dir.display()); println!("cargo:rustc-link-lib=dylib=ffi_wrapper"); println!("cargo:rerun-if-changed={}",ffi_dir.join("ffi_wrapper.h").display()); println!("cargo:rerun-if-changed={}",ffi_dir.join("ffi_wrapper.cpp").display()); // println!("cargo:rustc-cfg=exported_header_prefixes=\"helib\""); // let helib_include_dir = std::path::PathBuf::from("src/helib_pack/include"); // include path // let mut b = autocxx_build::Builder::new("src/lib.rs", &[&helib_include_dir]) // .extra_clang_args(&["-std=c++17"]) // .build()?; // // This assumes all your C++ bindings are in main.rs // b.flag_if_supported("-std=c++17") // .compile("helib-autocxx"); // arbitrary library name, pick anything // Compile cxx generated bindings. This is the name of the Rust FFI library // that includes the generated Rust bindings for your C++ code. // It is used to link the Rust code with the upstream C++ code. let path: PathBuf = cpp_source.to_string_lossy().into_owned().into(); println!("cargo:warning=This is a test 1"); let mut cc_build = cxx_build::bridge("src/cxx-bridges/context.rs"); println!("cargo:warning=This is a test 2"); println!("cargo:include=/home/hedge/src/zno-fhe-src/zno-helib-sys/ffi"); // println!("cargo:include=/home/hedge/src/zno-fhe-src/zno-helib-sys/src/helib_pack/include"); // println!("cargo:include=/home/hedge/src/zno-fhe-src/zno-helib-sys/src/helib_pack/include/helib"); // println!("cargo:include=/home/hedge/src/zno-fhe-src/zno-helib-sys/src/helib_pack/include/helib/../"); cc_build.file(path) .include("/home/hedge/src/zno-fhe-src/zno-helib-sys/ffi") // .include("/home/hedge/src/zno-fhe-src/zno-helib-sys/src/helib_pack/include") // .include("/home/hedge/src/zno-fhe-src/zno-helib-sys/src/helib_pack/include/helib") .flag_if_supported("-std=c++17") .compile("cxx-bridge-context"); // compile cxx generated bindings println!("cargo:rerun-if-changed=src/lib.rs"); println!("cargo:rerun-if-changed=ffi/helib/helib.h"); // Add instructions to link to any C++ libraries you need. let rtfcts = Build::new().artifacts(); rtfcts.print_cargo_metadata(); Ok(()) } pub fn source_dir() -> PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")).join("helib") } pub fn version() -> &'static str { env!("CARGO_PKG_VERSION") } /// Function to recursively copy directories fn copy_dir_to(src: &Path, dst: &Path) -> std::io::Result<()> { if !dst.is_dir() { fs::create_dir_all(dst)?; } for entry_result in src.read_dir()? { let entry = entry_result?; let file_type = entry.file_type()?; let src_path = src.join(entry.file_name()); let dst_path = dst.join(entry.file_name()); if file_type.is_dir() { copy_dir_to(&src_path, &dst_path)?; } else { fs::copy(&src_path, &dst_path)?; } } Ok(()) } pub struct Build { out_dir: Option, target: Option, host: Option, } pub struct Artifacts { package_dir: PathBuf, include_dir: PathBuf, lib_dir: PathBuf, bin_dir: PathBuf, share_dir: PathBuf, libs: Vec, target: String, } impl Build { pub fn new() -> Build { Build { out_dir: env::var_os("OUT_DIR").map(|s| PathBuf::from(s)), target: env::var("TARGET").ok(), host: env::var("HOST").ok(), } } pub fn out_dir>(&mut self, path: P) -> &mut Build { self.out_dir = Some(path.as_ref().to_path_buf()); self } pub fn target(&mut self, target: &str) -> &mut Build { self.target = Some(target.to_string()); self } pub fn host(&mut self, host: &str) -> &mut Build { self.host = Some(host.to_string()); self } fn cmd_make(&self) -> Command { let host = &self.host.as_ref().expect("HOST dir not set")[..]; if host.contains("dragonfly") || host.contains("freebsd") || host.contains("openbsd") || host.contains("solaris") || host.contains("illumos") { Command::new("gmake") } else { Command::new("make") } } #[cfg(windows)] fn check_env_var(&self, var_name: &str) -> Option { env::var_os(var_name).map(|s| { if s == "1" { // a message to stdout, let user know asm is force enabled println!( "{}: nasm.exe is force enabled by the \ 'ZNO_RUST_USE_NASM' env var.", env!("CARGO_PKG_NAME") ); true } else if s == "0" { // a message to stdout, let user know asm is force disabled println!( "{}: nasm.exe is force disabled by the \ 'ZNO_RUST_USE_NASM' env var.", env!("CARGO_PKG_NAME") ); false } else { panic!( "The environment variable {} is set to an unacceptable value: {:?}", var_name, s ); } }) } // #[cfg(windows)] // fn is_nasm_ready(&self) -> bool { // self.check_env_var("ZNO_RUST_USE_NASM") // .unwrap_or_else(|| { // // On Windows, use cmd `where` command to check if nasm is installed // let wherenasm = Command::new("cmd") // .args(&["/C", "where nasm"]) // .output() // .expect("Failed to execute `cmd`."); // wherenasm.status.success() // }) // } // #[cfg(not(windows))] // fn is_nasm_ready(&self) -> bool { // // We assume that nobody would run nasm.exe on a non-windows system. // false // } pub fn artifacts(&mut self) -> Artifacts { let target = &self.target.as_ref().expect("TARGET dir not set")[..]; let out_dir = self.out_dir.as_ref().expect("OUT_DIR not set"); // Generate files under the -sys crate src folder let install_dir = env::var_os("CARGO_MANIFEST_DIR") .map(|s| PathBuf::from(s)) .unwrap() .join("src"); let libs = if target.contains("msvc") { vec!["helibw".to_string(), "gmp".to_string(), "ntl".to_string()] } else { vec!["helib".to_string(), "gmp".to_string(), "ntl".to_string()] }; let pd = install_dir.join("helib_pack"); Artifacts { package_dir: pd.clone(), lib_dir: pd.clone().join("lib"), bin_dir: pd.clone().join("bin"), share_dir: pd.clone().join("share"), include_dir:pd.clone().join("include"), libs, target: target.to_string(), } } } impl Artifacts { pub fn include_dir(&self) -> &Path { &self.include_dir } pub fn lib_dir(&self) -> &Path { &self.lib_dir } pub fn bin_dir(&self) -> &Path { &self.bin_dir } pub fn package_dir(&self) -> &Path { &self.package_dir } pub fn share_dir(&self) -> &Path { &self.share_dir } pub fn libs(&self) -> &[String] { &self.libs } pub fn target(&self) -> String { self.target.clone() } pub fn print_cargo_metadata(&self) { println!("cargo:rustc-link-search=native={}", self.lib_dir.display()); let libdirs = vec![self.lib_dir().to_path_buf()]; let kind = Self::determine_mode(&libdirs, &self.libs); for lib in self.libs.clone().into_iter() { println!("cargo:rustc-link-lib={}={}", kind, lib); } println!("cargo:include={}", self.include_dir.display()); println!("cargo:lib={}", self.lib_dir.display()); if self.target.contains("msvc") { println!("cargo:rustc-link-lib=user32"); } else if self.target == "wasm32-wasi" { println!("cargo:rustc-link-lib=wasi-emulated-signal"); println!("cargo:rustc-link-lib=wasi-emulated-process-clocks"); println!("cargo:rustc-link-lib=wasi-emulated-mman"); println!("cargo:rustc-link-lib=wasi-emulated-getpid"); } } pub fn env_inner(name: &str) -> Option { let var = env::var_os(name); println!("cargo:rerun-if-env-changed={}", name); match var { Some(ref v) => println!("{} = {}", name, v.to_string_lossy()), None => println!("{} unset", name), } var } pub fn get_env(name: &str) -> Option { let prefix = env::var("TARGET").unwrap().to_uppercase().replace('-', "_"); let prefixed = format!("{}_{}", prefix, name); Self::env_inner(&prefixed).or_else(|| Self::env_inner(name)) } /// Given a libdir (where artifacts are located) as well as the name /// of the libraries we're linking to, figure out whether we should link them /// statically or dynamically. fn determine_mode(libdirs: &Vec, libs: &[String]) -> &'static str { // First see if a mode was explicitly requested let kind = Self::get_env("HELIB_STATIC"); match kind.as_ref().and_then(|s| s.to_str()) { Some("0") => return "dylib", Some(_) => return "static", None => {} } // Next, see what files we actually have to link against, and see what our // possibilities even are. let mut files = HashSet::new(); for dir in libdirs { for path in dir .read_dir() .unwrap() .map(|e| e.unwrap()) .map(|e| e.file_name()) .filter_map(|e| e.into_string().ok()) { files.insert(path); } } let can_static = libs .iter() .all(|l| files.contains(&format!("lib{}.a", l)) || files.contains(&format!("{}.lib", l))); let can_dylib = libs.iter().all(|l| { files.contains(&format!("lib{}.so", l)) || files.contains(&format!("{}.dll", l)) || files.contains(&format!("lib{}.dylib", l)) }); match (can_static, can_dylib) { (true, false) => return "static", (false, true) => return "dylib", (false, false) => { panic!( "libdir does not contain the required files \ to either statically or dynamically link HElib" ); } (true, true) => {} } // Ok, we've got not explicit preference and can *either* link statically or // link dynamically. In the interest of "security upgrades" and/or "best // practices with security libs", let's link dynamically. "dylib" } } ```

which generates this code:

context.rs.cc ```cpp #include "zno-helib-sys/ffi/ffi_wrapper.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace rust { inline namespace cxxbridge1 { // #include "rust/cxx.h" #ifndef CXXBRIDGE1_PANIC #define CXXBRIDGE1_PANIC template void panic [[noreturn]] (const char *msg); #endif // CXXBRIDGE1_PANIC namespace { template class impl; } // namespace class String; class Opaque; template ::std::size_t size_of(); template ::std::size_t align_of(); #ifndef CXXBRIDGE1_RUST_STR #define CXXBRIDGE1_RUST_STR class Str final { public: Str() noexcept; Str(const String &) noexcept; Str(const std::string &); Str(const char *); Str(const char *, std::size_t); Str &operator=(const Str &) &noexcept = default; explicit operator std::string() const; const char *data() const noexcept; std::size_t size() const noexcept; std::size_t length() const noexcept; bool empty() const noexcept; Str(const Str &) noexcept = default; ~Str() noexcept = default; using iterator = const char *; using const_iterator = const char *; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; bool operator==(const Str &) const noexcept; bool operator!=(const Str &) const noexcept; bool operator<(const Str &) const noexcept; bool operator<=(const Str &) const noexcept; bool operator>(const Str &) const noexcept; bool operator>=(const Str &) const noexcept; void swap(Str &) noexcept; private: class uninit; Str(uninit) noexcept; friend impl; std::array repr; }; #endif // CXXBRIDGE1_RUST_STR #ifndef CXXBRIDGE1_RUST_SLICE #define CXXBRIDGE1_RUST_SLICE namespace detail { template struct copy_assignable_if {}; template <> struct copy_assignable_if { copy_assignable_if() noexcept = default; copy_assignable_if(const copy_assignable_if &) noexcept = default; copy_assignable_if &operator=(const copy_assignable_if &) &noexcept = delete; copy_assignable_if &operator=(copy_assignable_if &&) &noexcept = default; }; } // namespace detail template class Slice final : private detail::copy_assignable_if::value> { public: using value_type = T; Slice() noexcept; Slice(T *, std::size_t count) noexcept; Slice &operator=(const Slice &) &noexcept = default; Slice &operator=(Slice &&) &noexcept = default; T *data() const noexcept; std::size_t size() const noexcept; std::size_t length() const noexcept; bool empty() const noexcept; T &operator[](std::size_t n) const noexcept; T &at(std::size_t n) const; T &front() const noexcept; T &back() const noexcept; Slice(const Slice &) noexcept = default; ~Slice() noexcept = default; class iterator; iterator begin() const noexcept; iterator end() const noexcept; void swap(Slice &) noexcept; private: class uninit; Slice(uninit) noexcept; friend impl; friend void sliceInit(void *, const void *, std::size_t) noexcept; friend void *slicePtr(const void *) noexcept; friend std::size_t sliceLen(const void *) noexcept; std::array repr; }; template class Slice::iterator final { public: using iterator_category = std::random_access_iterator_tag; using value_type = T; using difference_type = std::ptrdiff_t; using pointer = typename std::add_pointer::type; using reference = typename std::add_lvalue_reference::type; reference operator*() const noexcept; pointer operator->() const noexcept; reference operator[](difference_type) const noexcept; iterator &operator++() noexcept; iterator operator++(int) noexcept; iterator &operator--() noexcept; iterator operator--(int) noexcept; iterator &operator+=(difference_type) noexcept; iterator &operator-=(difference_type) noexcept; iterator operator+(difference_type) const noexcept; iterator operator-(difference_type) const noexcept; difference_type operator-(const iterator &) const noexcept; bool operator==(const iterator &) const noexcept; bool operator!=(const iterator &) const noexcept; bool operator<(const iterator &) const noexcept; bool operator<=(const iterator &) const noexcept; bool operator>(const iterator &) const noexcept; bool operator>=(const iterator &) const noexcept; private: friend class Slice; void *pos; std::size_t stride; }; template Slice::Slice() noexcept { sliceInit(this, reinterpret_cast(align_of()), 0); } template Slice::Slice(T *s, std::size_t count) noexcept { assert(s != nullptr || count == 0); sliceInit(this, s == nullptr && count == 0 ? reinterpret_cast(align_of()) : const_cast::type *>(s), count); } template T *Slice::data() const noexcept { return reinterpret_cast(slicePtr(this)); } template std::size_t Slice::size() const noexcept { return sliceLen(this); } template std::size_t Slice::length() const noexcept { return this->size(); } template bool Slice::empty() const noexcept { return this->size() == 0; } template T &Slice::operator[](std::size_t n) const noexcept { assert(n < this->size()); auto ptr = static_cast(slicePtr(this)) + size_of() * n; return *reinterpret_cast(ptr); } template T &Slice::at(std::size_t n) const { if (n >= this->size()) { panic("rust::Slice index out of range"); } return (*this)[n]; } template T &Slice::front() const noexcept { assert(!this->empty()); return (*this)[0]; } template T &Slice::back() const noexcept { assert(!this->empty()); return (*this)[this->size() - 1]; } template typename Slice::iterator::reference Slice::iterator::operator*() const noexcept { return *static_cast(this->pos); } template typename Slice::iterator::pointer Slice::iterator::operator->() const noexcept { return static_cast(this->pos); } template typename Slice::iterator::reference Slice::iterator::operator[]( typename Slice::iterator::difference_type n) const noexcept { auto ptr = static_cast(this->pos) + this->stride * n; return *reinterpret_cast(ptr); } template typename Slice::iterator &Slice::iterator::operator++() noexcept { this->pos = static_cast(this->pos) + this->stride; return *this; } template typename Slice::iterator Slice::iterator::operator++(int) noexcept { auto ret = iterator(*this); this->pos = static_cast(this->pos) + this->stride; return ret; } template typename Slice::iterator &Slice::iterator::operator--() noexcept { this->pos = static_cast(this->pos) - this->stride; return *this; } template typename Slice::iterator Slice::iterator::operator--(int) noexcept { auto ret = iterator(*this); this->pos = static_cast(this->pos) - this->stride; return ret; } template typename Slice::iterator &Slice::iterator::operator+=( typename Slice::iterator::difference_type n) noexcept { this->pos = static_cast(this->pos) + this->stride * n; return *this; } template typename Slice::iterator &Slice::iterator::operator-=( typename Slice::iterator::difference_type n) noexcept { this->pos = static_cast(this->pos) - this->stride * n; return *this; } template typename Slice::iterator Slice::iterator::operator+( typename Slice::iterator::difference_type n) const noexcept { auto ret = iterator(*this); ret.pos = static_cast(this->pos) + this->stride * n; return ret; } template typename Slice::iterator Slice::iterator::operator-( typename Slice::iterator::difference_type n) const noexcept { auto ret = iterator(*this); ret.pos = static_cast(this->pos) - this->stride * n; return ret; } template typename Slice::iterator::difference_type Slice::iterator::operator-(const iterator &other) const noexcept { auto diff = std::distance(static_cast(other.pos), static_cast(this->pos)); return diff / static_cast::iterator::difference_type>( this->stride); } template bool Slice::iterator::operator==(const iterator &other) const noexcept { return this->pos == other.pos; } template bool Slice::iterator::operator!=(const iterator &other) const noexcept { return this->pos != other.pos; } template bool Slice::iterator::operator<(const iterator &other) const noexcept { return this->pos < other.pos; } template bool Slice::iterator::operator<=(const iterator &other) const noexcept { return this->pos <= other.pos; } template bool Slice::iterator::operator>(const iterator &other) const noexcept { return this->pos > other.pos; } template bool Slice::iterator::operator>=(const iterator &other) const noexcept { return this->pos >= other.pos; } template typename Slice::iterator Slice::begin() const noexcept { iterator it; it.pos = slicePtr(this); it.stride = size_of(); return it; } template typename Slice::iterator Slice::end() const noexcept { iterator it = this->begin(); it.pos = static_cast(it.pos) + it.stride * this->size(); return it; } template void Slice::swap(Slice &rhs) noexcept { std::swap(*this, rhs); } #endif // CXXBRIDGE1_RUST_SLICE #ifndef CXXBRIDGE1_RUST_BITCOPY_T #define CXXBRIDGE1_RUST_BITCOPY_T struct unsafe_bitcopy_t final { explicit unsafe_bitcopy_t() = default; }; #endif // CXXBRIDGE1_RUST_BITCOPY_T #ifndef CXXBRIDGE1_RUST_BITCOPY #define CXXBRIDGE1_RUST_BITCOPY constexpr unsafe_bitcopy_t unsafe_bitcopy{}; #endif // CXXBRIDGE1_RUST_BITCOPY #ifndef CXXBRIDGE1_RUST_VEC #define CXXBRIDGE1_RUST_VEC template class Vec final { public: using value_type = T; Vec() noexcept; Vec(std::initializer_list); Vec(const Vec &); Vec(Vec &&) noexcept; ~Vec() noexcept; Vec &operator=(Vec &&) &noexcept; Vec &operator=(const Vec &) &; std::size_t size() const noexcept; bool empty() const noexcept; const T *data() const noexcept; T *data() noexcept; std::size_t capacity() const noexcept; const T &operator[](std::size_t n) const noexcept; const T &at(std::size_t n) const; const T &front() const noexcept; const T &back() const noexcept; T &operator[](std::size_t n) noexcept; T &at(std::size_t n); T &front() noexcept; T &back() noexcept; void reserve(std::size_t new_cap); void push_back(const T &value); void push_back(T &&value); template void emplace_back(Args &&...args); void truncate(std::size_t len); void clear(); using iterator = typename Slice::iterator; iterator begin() noexcept; iterator end() noexcept; using const_iterator = typename Slice::iterator; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; void swap(Vec &) noexcept; Vec(unsafe_bitcopy_t, const Vec &) noexcept; private: void reserve_total(std::size_t new_cap) noexcept; void set_len(std::size_t len) noexcept; void drop() noexcept; friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); } std::array repr; }; template Vec::Vec(std::initializer_list init) : Vec{} { this->reserve_total(init.size()); std::move(init.begin(), init.end(), std::back_inserter(*this)); } template Vec::Vec(const Vec &other) : Vec() { this->reserve_total(other.size()); std::copy(other.begin(), other.end(), std::back_inserter(*this)); } template Vec::Vec(Vec &&other) noexcept : repr(other.repr) { new (&other) Vec(); } template Vec::~Vec() noexcept { this->drop(); } template Vec &Vec::operator=(Vec &&other) &noexcept { this->drop(); this->repr = other.repr; new (&other) Vec(); return *this; } template Vec &Vec::operator=(const Vec &other) & { if (this != &other) { this->drop(); new (this) Vec(other); } return *this; } template bool Vec::empty() const noexcept { return this->size() == 0; } template T *Vec::data() noexcept { return const_cast(const_cast *>(this)->data()); } template const T &Vec::operator[](std::size_t n) const noexcept { assert(n < this->size()); auto data = reinterpret_cast(this->data()); return *reinterpret_cast(data + n * size_of()); } template const T &Vec::at(std::size_t n) const { if (n >= this->size()) { panic("rust::Vec index out of range"); } return (*this)[n]; } template const T &Vec::front() const noexcept { assert(!this->empty()); return (*this)[0]; } template const T &Vec::back() const noexcept { assert(!this->empty()); return (*this)[this->size() - 1]; } template T &Vec::operator[](std::size_t n) noexcept { assert(n < this->size()); auto data = reinterpret_cast(this->data()); return *reinterpret_cast(data + n * size_of()); } template T &Vec::at(std::size_t n) { if (n >= this->size()) { panic("rust::Vec index out of range"); } return (*this)[n]; } template T &Vec::front() noexcept { assert(!this->empty()); return (*this)[0]; } template T &Vec::back() noexcept { assert(!this->empty()); return (*this)[this->size() - 1]; } template void Vec::reserve(std::size_t new_cap) { this->reserve_total(new_cap); } template void Vec::push_back(const T &value) { this->emplace_back(value); } template void Vec::push_back(T &&value) { this->emplace_back(std::move(value)); } template template void Vec::emplace_back(Args &&...args) { auto size = this->size(); this->reserve_total(size + 1); ::new (reinterpret_cast(reinterpret_cast(this->data()) + size * size_of())) T(std::forward(args)...); this->set_len(size + 1); } template void Vec::clear() { this->truncate(0); } template typename Vec::iterator Vec::begin() noexcept { return Slice(this->data(), this->size()).begin(); } template typename Vec::iterator Vec::end() noexcept { return Slice(this->data(), this->size()).end(); } template typename Vec::const_iterator Vec::begin() const noexcept { return this->cbegin(); } template typename Vec::const_iterator Vec::end() const noexcept { return this->cend(); } template typename Vec::const_iterator Vec::cbegin() const noexcept { return Slice(this->data(), this->size()).begin(); } template typename Vec::const_iterator Vec::cend() const noexcept { return Slice(this->data(), this->size()).end(); } template void Vec::swap(Vec &rhs) noexcept { using std::swap; swap(this->repr, rhs.repr); } template Vec::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {} #endif // CXXBRIDGE1_RUST_VEC #ifndef CXXBRIDGE1_IS_COMPLETE #define CXXBRIDGE1_IS_COMPLETE namespace detail { namespace { template struct is_complete : std::false_type {}; template struct is_complete : std::true_type {}; } // namespace } // namespace detail #endif // CXXBRIDGE1_IS_COMPLETE #ifndef CXXBRIDGE1_LAYOUT #define CXXBRIDGE1_LAYOUT class layout { template friend std::size_t size_of(); template friend std::size_t align_of(); template static typename std::enable_if::value, std::size_t>::type do_size_of() { return T::layout::size(); } template static typename std::enable_if::value, std::size_t>::type do_size_of() { return sizeof(T); } template static typename std::enable_if::value, std::size_t>::type size_of() { return do_size_of(); } template static typename std::enable_if::value, std::size_t>::type do_align_of() { return T::layout::align(); } template static typename std::enable_if::value, std::size_t>::type do_align_of() { return alignof(T); } template static typename std::enable_if::value, std::size_t>::type align_of() { return do_align_of(); } }; template std::size_t size_of() { return layout::size_of(); } template std::size_t align_of() { return layout::align_of(); } #endif // CXXBRIDGE1_LAYOUT namespace detail { template struct operator_new { void *operator()(::std::size_t sz) { return ::operator new(sz); } }; template struct operator_new { void *operator()(::std::size_t sz) { return T::operator new(sz); } }; } // namespace detail template union MaybeUninit { T value; void *operator new(::std::size_t sz) { return detail::operator_new{}(sz); } MaybeUninit() {} ~MaybeUninit() {} }; namespace { template struct deleter_if { template void operator()(T *) {} }; template <> struct deleter_if { template void operator()(T *ptr) { ptr->~T(); } }; } // namespace } // namespace cxxbridge1 } // namespace rust using Context = ::Context; using ContextBuilderWrapper = ::ContextBuilderWrapper; extern "C" { ::ContextBuilderWrapper *cxxbridge1$create_context_builder() noexcept { ::std::unique_ptr<::ContextBuilderWrapper> (*create_context_builder$)() = ::create_context_builder; return create_context_builder$().release(); } ::Context *cxxbridge1$build(::std::unique_ptr<::ContextBuilderWrapper> &builder) noexcept { ::std::unique_ptr<::Context> (*build$)(::std::unique_ptr<::ContextBuilderWrapper> &) = ::build; return build$(builder).release(); } void cxxbridge1$set_m(::std::unique_ptr<::ContextBuilderWrapper> &builder, ::std::int64_t m) noexcept { void (*set_m$)(::std::unique_ptr<::ContextBuilderWrapper> &, ::std::int64_t) = ::set_m; set_m$(builder, m); } void cxxbridge1$set_p(::std::unique_ptr<::ContextBuilderWrapper> &builder, ::std::int64_t p) noexcept { void (*set_p$)(::std::unique_ptr<::ContextBuilderWrapper> &, ::std::int64_t) = ::set_p; set_p$(builder, p); } void cxxbridge1$set_r(::std::unique_ptr<::ContextBuilderWrapper> &builder, ::std::int64_t r) noexcept { void (*set_r$)(::std::unique_ptr<::ContextBuilderWrapper> &, ::std::int64_t) = ::set_r; set_r$(builder, r); } void cxxbridge1$set_gens(::std::unique_ptr<::ContextBuilderWrapper> &builder, ::std::vector<::std::int64_t> const &gens) noexcept { void (*set_gens$)(::std::unique_ptr<::ContextBuilderWrapper> &, ::std::vector<::std::int64_t> const &) = ::set_gens; set_gens$(builder, gens); } void cxxbridge1$set_ords(::std::unique_ptr<::ContextBuilderWrapper> &builder, ::std::vector<::std::int64_t> const &ords) noexcept { void (*set_ords$)(::std::unique_ptr<::ContextBuilderWrapper> &, ::std::vector<::std::int64_t> const &) = ::set_ords; set_ords$(builder, ords); } ::Context *cxxbridge1$create_bgv_context(::std::uint64_t m, ::std::uint64_t p, ::std::uint64_t r, ::rust::Vec<::std::int64_t> const *gens, ::rust::Vec<::std::int64_t> const *ords) noexcept { ::std::unique_ptr<::Context> (*create_bgv_context$)(::std::uint64_t, ::std::uint64_t, ::std::uint64_t, ::rust::Vec<::std::int64_t>, ::rust::Vec<::std::int64_t>) = ::create_bgv_context; return create_bgv_context$(m, p, r, ::rust::Vec<::std::int64_t>(::rust::unsafe_bitcopy, *gens), ::rust::Vec<::std::int64_t>(::rust::unsafe_bitcopy, *ords)).release(); } ::std::uint64_t cxxbridge1$get_m(::Context const &context) noexcept { ::std::uint64_t (*get_m$)(::Context const &) = ::get_m; return get_m$(context); } bool cxxbridge1$is_bootstrappable(::Context const &context) noexcept { bool (*is_bootstrappable$)(::Context const &) = ::is_bootstrappable; return is_bootstrappable$(context); } void cxxbridge1$convert_to_vec(::rust::Str s, ::rust::Vec<::std::int64_t> *return$) noexcept; } // extern "C" ::rust::Vec<::std::int64_t> convert_to_vec(::rust::Str s) noexcept { ::rust::MaybeUninit<::rust::Vec<::std::int64_t>> return$; cxxbridge1$convert_to_vec(s, &return$.value); return ::std::move(return$.value); } extern "C" { static_assert(::rust::detail::is_complete<::ContextBuilderWrapper>::value, "definition of ContextBuilderWrapper is required"); static_assert(sizeof(::std::unique_ptr<::ContextBuilderWrapper>) == sizeof(void *), ""); static_assert(alignof(::std::unique_ptr<::ContextBuilderWrapper>) == alignof(void *), ""); void cxxbridge1$unique_ptr$ContextBuilderWrapper$null(::std::unique_ptr<::ContextBuilderWrapper> *ptr) noexcept { ::new (ptr) ::std::unique_ptr<::ContextBuilderWrapper>(); } void cxxbridge1$unique_ptr$ContextBuilderWrapper$raw(::std::unique_ptr<::ContextBuilderWrapper> *ptr, ::ContextBuilderWrapper *raw) noexcept { ::new (ptr) ::std::unique_ptr<::ContextBuilderWrapper>(raw); } ::ContextBuilderWrapper const *cxxbridge1$unique_ptr$ContextBuilderWrapper$get(::std::unique_ptr<::ContextBuilderWrapper> const &ptr) noexcept { return ptr.get(); } ::ContextBuilderWrapper *cxxbridge1$unique_ptr$ContextBuilderWrapper$release(::std::unique_ptr<::ContextBuilderWrapper> &ptr) noexcept { return ptr.release(); } void cxxbridge1$unique_ptr$ContextBuilderWrapper$drop(::std::unique_ptr<::ContextBuilderWrapper> *ptr) noexcept { ::rust::deleter_if<::rust::detail::is_complete<::ContextBuilderWrapper>::value>{}(ptr); } static_assert(::rust::detail::is_complete<::Context>::value, "definition of Context is required"); static_assert(sizeof(::std::unique_ptr<::Context>) == sizeof(void *), ""); static_assert(alignof(::std::unique_ptr<::Context>) == alignof(void *), ""); void cxxbridge1$unique_ptr$Context$null(::std::unique_ptr<::Context> *ptr) noexcept { ::new (ptr) ::std::unique_ptr<::Context>(); } void cxxbridge1$unique_ptr$Context$raw(::std::unique_ptr<::Context> *ptr, ::Context *raw) noexcept { ::new (ptr) ::std::unique_ptr<::Context>(raw); } ::Context const *cxxbridge1$unique_ptr$Context$get(::std::unique_ptr<::Context> const &ptr) noexcept { return ptr.get(); } ::Context *cxxbridge1$unique_ptr$Context$release(::std::unique_ptr<::Context> &ptr) noexcept { return ptr.release(); } void cxxbridge1$unique_ptr$Context$drop(::std::unique_ptr<::Context> *ptr) noexcept { ::rust::deleter_if<::rust::detail::is_complete<::Context>::value>{}(ptr); } } // extern "C" ```
taqtiqa-mark commented 8 months ago

I think I've resolved this - keyboard operator error.