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
use crate::mlvalues::{is_block, string_val, tag_val, RawOCaml};
use crate::mlvalues::{tag, MAX_FIXNUM, MIN_FIXNUM};
use ocaml_sys::caml_string_length;
use core::{fmt, slice};
#[derive(Debug)]
pub struct OCamlException {
raw: RawOCaml,
}
#[derive(Debug)]
pub enum OCamlError {
Exception(OCamlException),
}
#[derive(Debug)]
pub enum OCamlFixnumConversionError {
InputTooBig(i64),
InputTooSmall(i64),
}
impl fmt::Display for OCamlFixnumConversionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
OCamlFixnumConversionError::InputTooBig(n) => write!(
f,
"Input value doesn't fit in OCaml fixnum n={} > MAX_FIXNUM={}",
n, MAX_FIXNUM
),
OCamlFixnumConversionError::InputTooSmall(n) => write!(
f,
"Input value doesn't fit in OCaml fixnum n={} < MIN_FIXNUM={}",
n, MIN_FIXNUM
),
}
}
}
impl OCamlException {
pub fn of(raw: RawOCaml) -> Self {
OCamlException { raw }
}
pub fn message(&self) -> Option<String> {
if is_block(self.raw) {
unsafe {
let message = *(self.raw as *const RawOCaml).add(1);
if tag_val(message) == tag::STRING {
let error_message =
slice::from_raw_parts(string_val(message), caml_string_length(message))
.to_owned();
let error_message = String::from_utf8_unchecked(error_message);
Some(error_message)
} else {
None
}
}
} else {
None
}
}
}