blob: 4b8489c94732cd3cd9569a686653a07511a8c5e0 (
plain)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
use libc::EINVAL;
use crate::enums::rustls_tls_version;
use crate::error::{rustls_io_result, rustls_result};
use crate::rslice::{rustls_slice_bytes, rustls_str};
use std::ptr::{null, null_mut};
// We wrap all function calls in an ffi_panic_boundary! macro, which catches
// panics and early-returns from the function. For functions that return
// rustls_result, we return a dedicated error code: `Panic`. For functions
// that don't return rustls_result, we return a default value: false, 0, or
// null. This trait provides that logic.
pub(crate) trait PanicOrDefault {
fn value() -> Self;
}
// This trait is like PanicOrDefault, but returns rustls_result::NullParameter
// rather than `Panic`.
pub(crate) trait NullParameterOrDefault {
fn value() -> Self;
}
// Defaultable is a subset of Default that can be returned by rustls-ffi.
// We use this rather than Default directly so that we can do a blanket
// impl for `T: Defaultable`. The compiler disallows a blanket impl for
// `T: Default` because `std::default` could later implement `Default`
// for `*mut T` and `*const T`.
pub(crate) trait Defaultable: Default {}
impl Defaultable for u16 {}
impl Defaultable for usize {}
impl Defaultable for bool {}
impl Defaultable for () {}
impl Defaultable for rustls_tls_version {}
impl<T> Defaultable for Option<T> {}
impl<'a> Defaultable for rustls_slice_bytes<'a> {}
impl<T: Defaultable> PanicOrDefault for T {
fn value() -> Self {
Default::default()
}
}
impl<T> PanicOrDefault for *mut T {
fn value() -> Self {
null_mut()
}
}
impl<T> PanicOrDefault for *const T {
fn value() -> Self {
null()
}
}
impl PanicOrDefault for rustls_result {
fn value() -> Self {
rustls_result::Panic
}
}
impl<'a> PanicOrDefault for rustls_str<'a> {
fn value() -> Self {
rustls_str::from_str_unchecked("")
}
}
impl PanicOrDefault for rustls_io_result {
fn value() -> Self {
rustls_io_result(EINVAL)
}
}
impl<T: Defaultable> NullParameterOrDefault for T {
fn value() -> Self {
Default::default()
}
}
impl<T> NullParameterOrDefault for *mut T {
fn value() -> Self {
null_mut()
}
}
impl<T> NullParameterOrDefault for *const T {
fn value() -> Self {
null()
}
}
impl NullParameterOrDefault for rustls_result {
fn value() -> Self {
rustls_result::NullParameter
}
}
impl NullParameterOrDefault for rustls_io_result {
fn value() -> Self {
rustls_io_result(EINVAL)
}
}
impl<'a> NullParameterOrDefault for rustls_str<'a> {
fn value() -> Self {
rustls_str::from_str_unchecked("")
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! ffi_panic_boundary {
( $($tt:tt)* ) => {
match ::std::panic::catch_unwind(|| {
$($tt)*
}) {
Ok(ret) => ret,
Err(_) => return $crate::PanicOrDefault::value(),
}
}
}
|