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
use std::ffi::CStr;
use std::fmt;
use foreign_types::{foreign_type, ForeignType};
use crate::{common::Error as HsError, error::AsResult, ffi};
pub trait AsCompileResult: Sized {
type Output;
type Err;
fn ok_or(self, err: *mut ffi::hs_compile_error_t) -> Result<Self::Output, Self::Err> {
self.ok_or_else(|| err)
}
fn ok_or_else<F>(self, err: F) -> Result<Self::Output, Self::Err>
where
F: FnOnce() -> *mut ffi::hs_compile_error_t;
}
impl AsCompileResult for ffi::hs_error_t {
type Output = ();
type Err = HsError;
fn ok_or_else<F>(self, err: F) -> Result<Self::Output, Self::Err>
where
F: FnOnce() -> *mut ffi::hs_compile_error_t,
{
if self == ffi::HS_SUCCESS as ffi::hs_error_t {
Ok(())
} else if self == ffi::HS_COMPILER_ERROR {
Err(HsError::CompileError(unsafe { Error::from_ptr(err()) }))
} else {
Err(HsError::from(self))
}
}
}
foreign_type! {
pub unsafe type Error: Send + Sync {
type CType = ffi::hs_compile_error_t;
fn drop = free_compile_error;
}
}
unsafe fn free_compile_error(err: *mut ffi::hs_compile_error_t) {
ffi::hs_free_compile_error(err).expect("free compile error");
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.message())
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Error")
.field("message", &self.message())
.field("expression", &self.expression())
.finish()
}
}
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
self.as_ptr() == other.as_ptr()
}
}
impl Eq for Error {}
impl Error {
unsafe fn as_ref(&self) -> &ffi::hs_compile_error_t {
self.as_ptr().as_ref().unwrap()
}
pub fn message(&self) -> &str {
unsafe { CStr::from_ptr(self.as_ref().message).to_str().unwrap() }
}
pub fn expression(&self) -> Option<usize> {
let n = unsafe { self.as_ref().expression };
if n < 0 {
None
} else {
Some(n as usize)
}
}
}