1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
//! Functions and data structures related to [Architecture]s.
use crate::Num;
use scotch_sys as s;
use std::io;
use std::mem;
use std::os::unix;
use std::path;
/// Equivalent of `SCOTCH_Arch`.
pub struct Architecture {
pub(crate) inner: s::SCOTCH_Arch,
}
impl Architecture {
/// Equivalent of `SCOTCH_archInit`.
fn new() -> Architecture {
let mut inner = mem::MaybeUninit::uninit();
// SAFETY: inner should be initialized if SCOTCH_archInit returns zero.
let inner = unsafe {
if s::SCOTCH_archInit(inner.as_mut_ptr()) != 0 {
panic!("Scotch internal error during architecture initialization");
}
inner.assume_init()
};
Architecture { inner }
}
/// Load an [`Architecture`] from the given file descriptor.
///
/// This function closes the given file descriptor.
///
/// # Safety
///
/// The given file descriptor must be valid for reading and must not be a
/// shared memory object.
unsafe fn load(fd: unix::io::RawFd) -> io::Result<Architecture> {
// SAFETY: caller must make sure the file descriptor is valid for reading.
let file = unsafe { crate::fdopen(fd, "r\0")? };
let mut architecture = Architecture::new();
let inner = &mut architecture.inner as *mut s::SCOTCH_Arch;
// SAFETY: file descriptor is valid and inner has been initialized.
unsafe {
if s::SCOTCH_archLoad(inner, file) != 0 {
s::fclose(file);
return Err(io::ErrorKind::Other.into());
}
s::fclose(file);
}
Ok(architecture)
}
/// Build an [`Architecture`] from the data found in standard input.
///
/// This function closes standard input.
///
/// Convenience wrapper around `SCOTCH_archLoad`.
pub fn from_stdin() -> io::Result<Architecture> {
// SAFETY: Standard input is open for reading and is not a shared memory object.
unsafe { Architecture::load(0) }
}
/// Build an [`Architecture`] from the data found in the given file.
///
/// Convenience wrapper around `SCOTCH_archLoad`.
pub fn from_file(path: impl AsRef<path::Path>) -> io::Result<Architecture> {
use std::fs;
use unix::io::IntoRawFd as _;
let file = fs::File::open(path)?;
let fd = file.into_raw_fd();
// SAFETY: file is open for reading and is not a shared memory object.
unsafe { Architecture::load(fd) }
}
/// Equivalent of `SCOTCH_archCmplt`.
pub fn complete(partnbr: Num) -> Architecture {
let mut architecture = Architecture::new();
let inner = &mut architecture.inner as *mut s::SCOTCH_Arch;
// SAFETY: inner is initialized.
unsafe {
if s::SCOTCH_archCmplt(inner, partnbr) != 0 {
panic!("Scotch internal error during architecture initialization");
}
}
architecture
}
}
impl Drop for Architecture {
fn drop(&mut self) {
unsafe {
let inner = &mut self.inner as *mut s::SCOTCH_Arch;
s::SCOTCH_archExit(inner);
}
}
}