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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use ;
/// Type-erased user data.
///
/// Use this to wrap arbitrary data into a structure which may be passed via a [`c_void`] pointer to
/// an external library. Later, when this `extern` callback is run with that data, you may unwrap it
/// and can thus access the original data.
///
/// The implementation uses associated methods:
///
/// - [`Userdata::prepare()`] to wrap the user data and get a [`c_void`] pointer
/// - [`Userdata::peek_at()`] to unwrap the [`c_void`] pointer and get the user data
/// - [`Userdata::consume()`] to clean up the [`c_void`] pointer and get the user data
///
/// Each [`prepare()`] must be paired with exactly one [`consume()`] to release the data held by the
/// wrapper structure. [`peek_at()`] must only be called in-between and the lifetime of the returned
/// reference is not allowed to extend past the next call to either [`peek_at()`] or [`consume()`].
///
/// [`prepare()`]: Self::prepare
/// [`peek_at()`]: Self::peek_at
/// [`consume()`]: Self::consume
///
/// # Examples
///
/// ```
/// use open62541::Userdata;
/// # use std::ffi::c_void;
///
/// // Turn user data into type-erased void pointer for FFI.
/// let raw_data: *mut c_void = Userdata::<u32>::prepare(0);
///
/// // Use type-erased pointer to get/manipulate user data.
/// unsafe {
/// let userdata = Userdata::<u32>::peek_at(raw_data);
/// assert_eq!(*userdata, 0);
/// *userdata = 123;
/// }
///
/// // Unwrap data. Clean up resources held by pointer.
/// let userdata = unsafe {
/// Userdata::<u32>::consume(raw_data)
/// };
///
/// // Got user data. `raw_data` is no longer valid.
/// assert_eq!(userdata, 123);
/// ```
// We allow only types with static lifetime (i.e. without references that would not be valid for the
// rest of the program) to allow leaking their values safely onto the heap to reclaim them later.
;
/// Sentinel for type-erased user data.
///
/// This consumes the user data when dropped.
;
// SAFETY: When `T` can be sent to another thread, the sentinel can be as well. (Despite the pointer
// inside, the sentinel is not a Rust reference but rather the owner of the data itself. To drop it,
// we move it out of its `Box` when consuming the `Userdata`.)
unsafe