Skip to content

Commit

Permalink
fix: remove to_str from conversion functions, change mapping of err…
Browse files Browse the repository at this point in the history
…orcodes and free error message immediately after copying it
  • Loading branch information
algebraic-dev committed Jan 24, 2024
1 parent 31026dd commit c12b1c1
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 92 deletions.
7 changes: 0 additions & 7 deletions machine-bindings/cartesi-machine-sys/Cargo.lock

This file was deleted.

21 changes: 0 additions & 21 deletions machine-bindings/cartesi-machine/Cargo.lock

This file was deleted.

109 changes: 45 additions & 64 deletions machine-bindings/cartesi-machine/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,62 @@
use std::{ffi::c_char, fmt::Display};

fn c_char_to_string(c_char: *const c_char) -> &'static str {
if c_char.is_null() {
""
} else {
unsafe { std::ffi::CStr::from_ptr(c_char).to_str().unwrap() }
}
}
use cartesi_machine_sys::*;

use crate::ffi::from_cstr;

/// Error codes returned from machine emulator C API
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorCode {
// Logic errors
InvalidArgument = 1,
DomainError,
LengthError,
OutOfRange,
LogicError,

// Bad optional access error
BadOptionalAccess,

// Runtime errors
RuntimeError,
RangeError,
OverflowError,
UnderflowError,
RegexError,
SystemIosBaseFailure,
FilesystemError,
AtomicTxError,
NonexistingLocalTime,
AmbigousLocalTime,
FormatError,

// Other errors
BadTypeid,
BadCast,
BadAnyCast,
BadWeakPtr,
BadFunctionCall,
BadAlloc,
BadArrayNewLength,
BadException,
BadVariantAccess,
Exception,

// C API Errors
Unknown,
InvalidArgument = CM_ERROR_CM_ERROR_INVALID_ARGUMENT as isize,
DomainError = CM_ERROR_CM_ERROR_DOMAIN_ERROR as isize,
LengthError = CM_ERROR_CM_ERROR_LENGTH_ERROR as isize,
OutOfRange = CM_ERROR_CM_ERROR_OUT_OF_RANGE as isize,
LogicError = CM_ERROR_CM_ERROR_LOGIC_ERROR as isize,
LogicErrorEnd = CM_ERROR_CM_LOGIC_ERROR_END as isize,
BadOptionalAccess = CM_ERROR_CM_ERROR_BAD_OPTIONAL_ACCESS as isize,
RuntimeError = CM_ERROR_CM_ERROR_RUNTIME_ERROR as isize,
RangeError = CM_ERROR_CM_ERROR_RANGE_ERROR as isize,
OverflowError = CM_ERROR_CM_ERROR_OVERFLOW_ERROR as isize,
UnderflowError = CM_ERROR_CM_ERROR_UNDERFLOW_ERROR as isize,
RegexError = CM_ERROR_CM_ERROR_REGEX_ERROR as isize,
SystemIosBaseFailure = CM_ERROR_CM_ERROR_SYSTEM_IOS_BASE_FAILURE as isize,
FilesystemError = CM_ERROR_CM_ERROR_FILESYSTEM_ERROR as isize,
AtomicTxError = CM_ERROR_CM_ERROR_ATOMIC_TX_ERROR as isize,
NonexistingLocalTime = CM_ERROR_CM_ERROR_NONEXISTING_LOCAL_TIME as isize,
AmbigousLocalTime = CM_ERROR_CM_ERROR_AMBIGOUS_LOCAL_TIME as isize,
FormatError = CM_ERROR_CM_ERROR_FORMAT_ERROR as isize,
RuntimeErrorEnd = CM_ERROR_CM_RUNTIME_ERROR_END as isize,
BadTypeid = CM_ERROR_CM_ERROR_BAD_TYPEID as isize,
BadCast = CM_ERROR_CM_ERROR_BAD_CAST as isize,
BadAnyCast = CM_ERROR_CM_ERROR_BAD_ANY_CAST as isize,
BadWeakPtr = CM_ERROR_CM_ERROR_BAD_WEAK_PTR as isize,
BadFunctionCall = CM_ERROR_CM_ERROR_BAD_FUNCTION_CALL as isize,
BadAlloc = CM_ERROR_CM_ERROR_BAD_ALLOC as isize,
BadArrayNewLength = CM_ERROR_CM_ERROR_BAD_ARRAY_NEW_LENGTH as isize,
BadException = CM_ERROR_CM_ERROR_BAD_EXCEPTION as isize,
BadVariantAccess = CM_ERROR_CM_ERROR_BAD_VARIANT_ACCESS as isize,
Exception = CM_ERROR_CM_ERROR_EXCEPTION as isize,
OtherErrorEnd = CM_ERROR_CM_OTHER_ERROR_END as isize,
Unknown = CM_ERROR_CM_ERROR_UNKNOWN as isize
}

/// Error returned from machine emulator C API
#[derive(Debug, Clone)]
pub struct MachineError {
code: ErrorCode,
message: *const c_char
}

impl Drop for MachineError {
fn drop(&mut self) {
unsafe { cartesi_machine_sys::cm_delete_cstring(self.message) };
}
message: Option<String>
}

impl Display for MachineError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let message = c_char_to_string(self.message);
write!(f, "Error {:?}: {}", self.code as u8, message)
}
}

impl std::fmt::Debug for MachineError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let message = c_char_to_string(self.message);
f.debug_struct("MachineError")
.field("code", &self.code)
.field("message", &message)
.finish()
write!(f, "Error {:?}: {}", self.code as u8, self.message.clone().unwrap_or_default())
}
}

/// Collects an error and cleans the memory. It's used to avoid accidental memory leaks when
/// handling errors using the ownership of [ErrorCollector], the inability to clone it and the
/// [cm_delete_cstring] function.
pub struct ErrorCollector {
ptr: *mut c_char
}
Expand All @@ -103,9 +80,13 @@ impl ErrorCollector {
if code == 0 {
Ok(())
} else {
let message = from_cstr(self.ptr);

unsafe { cartesi_machine_sys::cm_delete_cstring(self.ptr) };

Err(MachineError {
code: unsafe { std::mem::transmute(code as u8) },
message: self.ptr
message
})
}
}
Expand Down

0 comments on commit c12b1c1

Please sign in to comment.