libcoap-rs 0.2.2

An idiomatic wrapper around the libcoap CoAP library for Rust.
Documentation
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
// SPDX-License-Identifier: BSD-2-Clause
/*
 * mem.rs - Memory handling helper structs and traits for the libcoap Rust Wrapper.
 * This file is part of the libcoap-rs crate, see the README and LICENSE files for
 * more information and terms of use.
 * Copyright © 2021-2023 The NAMIB Project Developers, all rights reserved.
 * See the README as well as the LICENSE file for more information.
 */

//! Code related to memory handling, especially for passing objects through FFI

use std::cell::{Ref, RefCell, RefMut};
use std::ffi::c_void;
use std::fmt::{Debug, Formatter};
use std::ops::{Deref, DerefMut};
use std::rc::{Rc, Weak};

/// Trait implemented by libcoap wrapper structs that contain an inner value that may be dropped
/// exclusively, i.e., that can be dropped with the additional check that there are no further
/// references to the inner value.
pub(crate) trait DropInnerExclusively {
    /// Consume this instance, ensuring that the inner (and potentially shared) part of the struct
    /// referenced by this instance is also dropped.
    ///
    /// # Panics
    /// Panics if the inner part of this struct cannot be exclusively dropped, i.e., it is still
    /// used by another instance.
    fn drop_exclusively(self);
}

/// A strong reference counted cell, created from an app data/user data pointer inside of a C
/// library struct.
///
/// This type is a wrapper around Rc<RefCell<D>> with some additional functions for creating from
/// or converting to raw pointers.
pub(crate) struct CoapFfiRcCell<D>(Rc<RefCell<D>>);

impl<D> CoapFfiRcCell<D> {
    /// Creates a new instance of CoapFfiRcCell, containing the provided value.
    pub fn new(value: D) -> CoapFfiRcCell<D> {
        CoapFfiRcCell(Rc::new(RefCell::new(value)))
    }

    /// Converts from a raw user data/application data pointer inside of a libcoap C library struct
    /// into the appropriate reference type.
    ///
    /// This is done by first restoring the `Rc<RefCell<D>>` using [Rc::from_raw()], then
    /// cloning and creating the [CoapFfiRcCell] from it (maintaining the original reference using
    /// [Rc::into_raw()]).
    ///
    /// Note that for the lifetime of this [CoapFfiRcCell], the reference counter of the
    /// underlying [Rc] is increased by one.
    ///
    /// # Safety
    /// For an explanation of the purpose of this struct and where it was originally intended to be
    /// used, see the struct-level documentation.
    ///
    /// To safely use this function, the following invariants must be kept:
    /// - ptr is a valid pointer to an Rc<RefCell<D>>
    pub unsafe fn clone_raw_rc(ptr: *mut c_void) -> CoapFfiRcCell<D> {
        let orig_ref = Rc::from_raw(ptr as *const RefCell<D>);
        let new_ref = Rc::clone(&orig_ref);
        Rc::into_raw(orig_ref);
        CoapFfiRcCell(new_ref)
    }

    /// Converts from a raw user data/application data pointer inside of a libcoap C library struct
    /// into the appropriate reference type.
    ///
    /// This is done by first restoring the `Weak<RefCell<D>>` using [Weak::from_raw()],
    /// upgrading it to a `Rc<RefCell<D>>` then cloning and creating the [CoapFfiRcCell] from the
    /// upgraded reference (restoring the raw pointer again afterwards using [Rc::downgrade()] and
    /// [Weak::into_raw()]).
    ///
    /// Note that for the lifetime of this [CoapFfiRcCell], the reference counter of the underlying
    /// [Rc] is increased by one.
    ///
    /// # Panics
    /// Panics if the provided Weak reference is orphaned.
    ///
    /// # Safety
    /// For an explanation of the purpose of this struct and where it was originally intended to be
    /// used, see the struct-level documentation.
    ///
    /// To safely use this function, the following invariants must be kept:
    /// - ptr is a valid pointer to a `Weak<RefCell<D>>`
    pub unsafe fn clone_raw_weak(ptr: *mut c_void) -> CoapFfiRcCell<D> {
        let orig_ref = Weak::from_raw(ptr as *const RefCell<D>);
        let new_ref = Weak::upgrade(&orig_ref).expect("attempted to upgrade a weak reference that was orphaned");
        let _weakref = Weak::into_raw(orig_ref);
        CoapFfiRcCell(new_ref)
    }

    /// Converts from a raw user data/application data pointer inside of a libcoap C library struct
    /// into the underlying `Weak<RefCell<D>>`.
    ///
    /// This is done by restoring the `Weak<RefCell<D>>` using [Weak::from_raw()],
    ///
    /// Note that unlike [CoapFfiRcCell::clone_raw_weak()], this does not clone the weak reference
    /// inside of the pointer and instead restores the `Weak` directly from the pointer.
    /// This means that dropping the `Weak` returned from this function invalidates the pointer
    /// provided to this function.
    ///
    /// # Panics
    /// Panics if the provided Weak reference is orphaned.
    ///
    /// # Safety
    /// For an explanation of the purpose of this struct and where it was originally intended to be
    /// used, see the struct-level documentation.
    ///
    /// To safely use this function, the following invariants must be kept:
    /// - ptr is a valid pointer to a `Weak<RefCell<D>>`
    /// - as soon as the returned `Weak<RefCell<D>>` is dropped, the provided pointer is treated as
    ///   invalid.
    pub unsafe fn raw_ptr_to_weak(ptr: *mut c_void) -> Weak<RefCell<D>> {
        Weak::from_raw(ptr as *const RefCell<D>)
    }

    /// Converts from a raw user data/application data pointer inside of a libcoap C library struct
    /// into the underlying `Rc<RefCell<D>>`.
    ///
    /// This is done by restoring the `Rc<RefCell<D>>` using [Rc::from_raw()],
    ///
    /// Note that unlike [CoapFfiRcCell::clone_raw_rc()], this does not clone the weak reference
    /// inside of the pointer and instead restores the `Rc` directly from the pointer.
    /// This means that dropping the `Rc` returned from this function invalidates the pointer
    /// provided to this function and that the provided pointer must point to a valid
    /// `Rc<RefCell<D>>`.
    ///
    /// # Panics
    /// Panics if the provided Weak reference is orphaned.
    ///
    /// # Safety
    /// For an explanation of the purpose of this struct and where it was originally intended to be
    /// used, see the struct-level documentation.
    ///
    /// To safely use this function, the following invariants must be kept:
    /// - ptr is a valid pointer to a `Rc<RefCell<D>>`
    /// - as soon as the returned `Rc<RefCell<D>>` is dropped, the provided pointer is treated as
    ///   invalid.
    // Kept for consistency
    #[allow(unused)]
    pub unsafe fn raw_ptr_to_rc(ptr: *mut c_void) -> Rc<RefCell<D>> {
        Rc::from_raw(ptr as *const RefCell<D>)
    }

    /// Creates a raw reference, suitable for storage inside of a libcoap C library user/application
    /// data pointer.
    ///
    /// This function internally calls [Rc::clone()] and then [Rc::into_raw()] to create a pointer
    /// referring to a clone of the `Rc<RefCell<D>>` contained in this type.
    ///
    /// Note that this increases the reference count of the Rc by one.
    // Kept for consistency
    #[allow(unused)]
    pub fn create_raw_rc(&self) -> *mut c_void {
        Rc::into_raw(Rc::clone(&self.0)) as *mut c_void
    }

    /// Creates a raw reference, suitable for storage inside of a libcoap C library user/application
    /// data pointer.
    ///
    /// This function internally calls [Rc::downgrade()] and then [Weak::into_raw()] to create a
    /// pointer referring to a weak reference of the `Rc<RefCell<D>>` contained in this type.
    ///
    /// Note that this does not increase the reference count of the [Rc] by one. If you want to
    /// ensure that the underlying D is never cleaned up for as long as this pointer exists, you
    /// need to maintain this object for as least as long as the reference.
    pub fn create_raw_weak(&self) -> *mut c_void {
        Weak::into_raw(Rc::downgrade(&self.0)) as *mut c_void
    }

    /// Creates an immutable reference to the contained data type.
    ///
    /// # Panics
    /// Panics if borrowing here would violate Rusts aliasing rules.
    pub fn borrow(&self) -> Ref<D> {
        RefCell::borrow(&self.0)
    }

    /// Creates a mutable reference to the contained data type.
    ///
    /// # Panics
    /// Panics if borrowing mutably here would violate Rusts aliasing rules.
    pub fn borrow_mut(&self) -> RefMut<D> {
        RefCell::borrow_mut(&self.0)
    }
}

impl<D: PartialEq> PartialEq for CoapFfiRcCell<D> {
    fn eq(&self, other: &Self) -> bool {
        Rc::eq(&self.0, &other.0)
    }
}

impl<D: Eq + PartialEq> Eq for CoapFfiRcCell<D> {}

impl<D> Clone for CoapFfiRcCell<D> {
    fn clone(&self) -> Self {
        CoapFfiRcCell(self.0.clone())
    }
}

impl<D: Debug> Debug for CoapFfiRcCell<D> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("CoapFfiRcCell").field("0", &self.0).finish()
    }
}

impl<T: Debug> DropInnerExclusively for CoapFfiRcCell<T> {
    fn drop_exclusively(self) {
        std::mem::drop(
            Rc::try_unwrap(self.0).expect("unable to unwrap instance of CoapFfiRcCell as it is still in use"),
        )
    }
}

/// A reference counted cell suitable for passing through the FFI barrier, with the additional
/// possibility of passing an existing reference through this barrier.
///
/// This struct is similar to [CoapFfiRcCell], but provides additional functionality for
/// maintaining a reference through the FFI barrier using the [lend()] function.
#[derive(Debug)]
pub(crate) struct CoapLendableFfiRcCell<T: Debug>(Rc<RefCell<T>>, Rc<RefCell<Option<*mut T>>>);

impl<T: Debug> CoapLendableFfiRcCell<T> {
    /// Creates a new [`CoapLendableFfiRcCell`] from the given value.
    pub fn new(value: T) -> CoapLendableFfiRcCell<T> {
        CoapLendableFfiRcCell(Rc::new(RefCell::new(value)), Rc::new(RefCell::new(None)))
    }

    /// Mutably borrows from the value in this cell.
    ///
    /// This function will first check if a reference was lent through the FFI barrier using a call
    /// to [lend()].
    /// If so, it will take that reference (and return it to the cell when the returned
    /// [CoapLendableFfiRef] goes out of scope).
    /// If not, it will borrow the value normally by calling [Rc::borrow()] on the contained value.
    ///
    /// # Panics
    /// Panics if the value was already mutably borrowed.
    pub fn borrow_mut(&self) -> CoapLendableFfiRefMut<'_, T> {
        if let Some(borrowed) = RefCell::borrow_mut(&self.1).take() {
            // SAFETY: The aliasing rules are ensured here by making sure that only one person may
            // retrieve the pointer value stored in the container at any time (as the value in the
            // Option is always retrieved using _take()_.
            // The validity of the pointer is ensured because the only way a value can be stored
            // here is by calling CoapLendableFfiRcCell::lend_ref_mut(), which converts a
            // reference into an always valid pointer.
            CoapLendableFfiRefMut::Borrowed(unsafe { borrowed.as_mut() }.unwrap(), Rc::clone(&self.1))
        } else {
            CoapLendableFfiRefMut::Owned(RefCell::borrow_mut(&self.0))
        }
    }

    /// Immutably borrows from the value in this cell.
    ///
    /// This function will first check if a reference was lent through the FFI barrier using a call
    /// to [lend()].
    /// If so, it will take that reference (and return it to the cell when the returned
    /// [CoapLendableFfiRef] goes out of scope).
    /// If not, it will borrow the value normally by calling [Rc::borrow()] on the contained value.
    ///
    /// # Panics
    /// Panics if the value was already mutably borrowed.
    pub fn borrow(&self) -> CoapLendableFfiRef<'_, T> {
        if let Some(borrowed) = RefCell::borrow_mut(&self.1).take() {
            // SAFETY: The aliasing rules are ensured here by making sure that only one person may
            // retrieve the pointer value stored in the container at any time (as the value in the
            // Option is always retrieved using _take()_.
            // The validity of the pointer is ensured because the only way a value can be stored
            // here is by calling CoapLendableFfiRcCell::lend_ref_mut(), which converts a
            // reference into an always valid pointer.
            // TODO we may want to allow multiple immutable borrows at some point(?)
            CoapLendableFfiRef::Borrowed(unsafe { borrowed.as_mut() }.unwrap(), Rc::clone(&self.1))
        } else {
            CoapLendableFfiRef::Owned(RefCell::borrow(&self.0))
        }
    }

    /// Create a raw pointer to this cell, suitable for storage in a libcoap application data
    /// pointer.
    ///
    /// Internally, this function creates a clone of this cell, wraps this cell in a `Box` and then
    /// converts this value into a pointer using [Box::into_raw].
    ///
    /// It is in the callers responsibility to free the memory associated with this `Box`, e.g., by
    /// calling [from_raw_box()] and then dropping the value.
    // Kept for consistency
    #[allow(unused)]
    pub fn create_raw_rc_box(&self) -> *mut CoapLendableFfiRcCell<T> {
        Box::into_raw(Box::new(CoapLendableFfiRcCell::<T>::clone(self)))
    }

    /// Create a raw pointer to this cell, suitable for storage in a libcoap application data
    /// pointer.
    ///
    /// Internally, this function creates a weak clone of this cell, wraps this cell in a `Box` and
    /// then converts this value into a pointer using [Box::into_raw].
    ///
    /// It is in the callers responsibility to free the memory associated with this `Box`, e.g., by
    /// calling [CoapLendableFfiWeakCell::from_raw_box()] and then dropping the value.
    pub fn create_raw_weak_box(&self) -> *mut CoapLendableFfiWeakCell<T> {
        Box::into_raw(Box::new(self.downgrade()))
    }

    /// Creates a new instance of this struct by cloning from a raw pointer pointing to a
    /// `Box<CoapLendableFfiRcCell<T>`.
    ///
    /// # Safety
    /// The provided pointer must point to a valid instance of `Box<CoapLendableFfiRcCell<T>`.
    // Kept for consistency
    #[allow(unused)]
    pub unsafe fn clone_raw_rc_box(ptr: *mut CoapLendableFfiRcCell<T>) -> CoapLendableFfiRcCell<T> {
        let ref_box: Box<CoapLendableFfiRcCell<T>> = Box::from_raw(ptr);
        let ret_val = CoapLendableFfiRcCell::<T>::clone(ref_box.as_ref());
        Box::into_raw(ref_box);
        ret_val
    }

    /// Creates a new instance of this struct by cloning from a raw pointer pointing to a
    /// `Box<CoapLendableFfiWeakCell<T>`.
    ///
    /// # Panics
    /// Panics if the provided weak cell is orphaned.
    ///
    /// # Safety
    /// The provided pointer must point to a valid instance of `Box<CoapLendableFfiWeakCell<T>`.
    pub unsafe fn clone_raw_weak_box(ptr: *mut CoapLendableFfiWeakCell<T>) -> CoapLendableFfiRcCell<T> {
        let ref_box: Box<CoapLendableFfiWeakCell<T>> = Box::from_raw(ptr);
        let ret_val = ref_box
            .upgrade()
            .expect("unable to restore CoapLendableFfiRcCell as the underlying value was already dropped");
        Box::into_raw(ref_box);
        ret_val
    }

    /// Restores a `Box<CoapLendableFfiRcCell<T>>` from a raw pointer.
    ///
    /// Note that unlike [clone_raw_rc_box()], this function does not create a clone but directly
    /// restores the underlying provided box.
    /// As soon as the returned value is dropped, the provided pointer is therefore invalid.
    ///
    /// # Safety
    /// The provided pointer must point to a valid instance of `Box<CoapLendableFfiRcCell<T>`.
    // Kept for consistency
    #[allow(unused)]
    pub unsafe fn from_raw_rc_box(ptr: *mut CoapLendableFfiRcCell<T>) -> Box<CoapLendableFfiRcCell<T>> {
        Box::from_raw(ptr)
    }

    /// Stores a mutable reference to an instance of T for later retrieval by code running on the
    /// other side of the FFI barrier.
    ///
    /// This function can be used to pass a previously borrowed value to other users of this cell
    /// through the FFI barrier _without_ intermittently releasing the borrow.
    ///
    /// The reference will be lent for as long as the returned [CoapLendableFfiRefLender<'a, T>] is
    /// not dropped.
    pub fn lend_ref_mut<'a>(&self, refer: &'a mut T) -> CoapLendableFfiRefLender<'a, T> {
        assert_eq!(
            RefCell::as_ptr(&self.0),
            refer as *mut T,
            "attempted to lend different object over CoapLendableFfiRcCell"
        );
        CoapLendableFfiRefLender::new(refer, &self.1)
    }

    /// Creates a weak version of this reference counted cell by downgrading its components.
    pub fn downgrade(&self) -> CoapLendableFfiWeakCell<T> {
        CoapLendableFfiWeakCell(Rc::downgrade(&self.0), Rc::downgrade(&self.1))
    }
}

impl<T: Debug> Clone for CoapLendableFfiRcCell<T> {
    fn clone(&self) -> Self {
        CoapLendableFfiRcCell(Rc::clone(&self.0), Rc::clone(&self.1))
    }
}

/// The weak variant of a [CoapLendableFfiRcCell].
#[derive(Debug)]
pub(crate) struct CoapLendableFfiWeakCell<T: Debug>(Weak<RefCell<T>>, Weak<RefCell<Option<*mut T>>>);

impl<T: Debug> Clone for CoapLendableFfiWeakCell<T> {
    fn clone(&self) -> Self {
        CoapLendableFfiWeakCell(Weak::clone(&self.0), Weak::clone(&self.1))
    }
}

impl<T: Debug> CoapLendableFfiWeakCell<T> {
    /// Attempts to upgrade this weak cell into a full [CoapLendableFfiRcCell<T>], returning None
    /// if the underlying value was already dropped.
    pub fn upgrade(&self) -> Option<CoapLendableFfiRcCell<T>> {
        self.0
            .upgrade()
            .zip(self.1.upgrade())
            .map(|(v0, v1)| CoapLendableFfiRcCell(v0, v1))
    }

    /// Restores a `Box<CoapLendableFfiWeakCell<T>>` from a raw pointer.
    ///
    /// Note that unlike [CoapLendableFfiRcCell<T>::clone_raw_weak_box()], this function does not
    /// create a clone but directly restores the underlying provided box.
    /// As soon as the returned value is dropped, the provided pointer is therefore invalid.
    ///
    /// # Safety
    /// The provided pointer must point to a valid instance of `Box<CoapLendableFfiWeakCell<T>`.
    pub unsafe fn from_raw_box(ptr: *mut CoapLendableFfiWeakCell<T>) -> Box<CoapLendableFfiWeakCell<T>> {
        Box::from_raw(ptr)
    }
}

/// A token that is held by the lender of a mutable reference.
///
/// As long as this token is held, the mutable reference provided to [CoapLendableFfiRcCell] can be
/// borrowed by other functions owning clones of the same [CoapLendableFfiRcCell].
///
/// When this value is dropped, it will check whether the lent reference is currently used
/// elsewhere and panic/abort if this is the case, as this would violate the Rust aliasing rules.
pub(crate) struct CoapLendableFfiRefLender<'a, T> {
    lent_ref: &'a mut T,
    lent_ptr_ctr: Weak<RefCell<Option<*mut T>>>,
}

impl<'a, T> CoapLendableFfiRefLender<'a, T> {
    /// Create a new lender token from the given reference.
    fn new(refer: &'a mut T, container: &Rc<RefCell<Option<*mut T>>>) -> CoapLendableFfiRefLender<'a, T> {
        RefCell::borrow_mut(container).replace(refer as *mut T);
        CoapLendableFfiRefLender {
            lent_ref: refer,
            lent_ptr_ctr: Rc::downgrade(container),
        }
    }

    pub(crate) fn unlend(self) {
        std::mem::drop(self);
    }
}

impl<T> Drop for CoapLendableFfiRefLender<'_, T> {
    fn drop(&mut self) {
        if let Some(lent_ptr_ctr) = self.lent_ptr_ctr.upgrade() {
            assert_eq!(
                self.lent_ref as *mut T,
                lent_ptr_ctr
                    .take()
                    .expect("unable to retrieve lent reference, implying that it may be in use somewhere"),
                "somehow, multiple references are stored in the same CoapLendableFfiRcCell"
            )
        }
    }
}

/// A non-mutable reference created by borrowing mutably from a [CoapFfiRcCell] using
/// [CoapFfiRcCell::borrow_mut()].
pub(crate) enum CoapLendableFfiRef<'a, T> {
    Owned(Ref<'a, T>),
    Borrowed(&'a mut T, Rc<RefCell<Option<*mut T>>>),
}

impl<T> Deref for CoapLendableFfiRef<'_, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        match self {
            CoapLendableFfiRef::Owned(v) => v.deref(),
            CoapLendableFfiRef::Borrowed(v, _lend_container) => v,
        }
    }
}

impl<T> Drop for CoapLendableFfiRef<'_, T> {
    fn drop(&mut self) {
        if let CoapLendableFfiRef::Borrowed(refer, lend_container) = self {
            let mut lend_container = RefCell::borrow_mut(lend_container);
            assert!(
                lend_container.is_none(),
                "somehow, multiple references are stored in the same CoapLendableFfiRcCell"
            );
            assert!(
                lend_container.replace(*refer).is_none(),
                "somehow, multiple references are stored in the same CoapLendableFfiRcCell"
            );
        }
    }
}

/// A mutable reference created by borrowing mutably from a [CoapFfiRcCell] using
/// [CoapFfiRcCell::borrow_mut()].
pub(crate) enum CoapLendableFfiRefMut<'a, T> {
    Owned(RefMut<'a, T>),
    Borrowed(&'a mut T, Rc<RefCell<Option<*mut T>>>),
}

impl<T> Deref for CoapLendableFfiRefMut<'_, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        match self {
            CoapLendableFfiRefMut::Owned(v) => v.deref(),
            CoapLendableFfiRefMut::Borrowed(v, _lend_container) => v,
        }
    }
}

impl<T> DerefMut for CoapLendableFfiRefMut<'_, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            CoapLendableFfiRefMut::Owned(v) => v.deref_mut(),
            CoapLendableFfiRefMut::Borrowed(v, _lend_container) => v,
        }
    }
}

impl<T> Drop for CoapLendableFfiRefMut<'_, T> {
    fn drop(&mut self) {
        if let CoapLendableFfiRefMut::Borrowed(refer, lend_container) = self {
            let mut lend_container = RefCell::borrow_mut(lend_container);
            assert!(
                lend_container.is_none(),
                "somehow, multiple references are stored in the same CoapLendableFfiRcCell"
            );
            assert!(
                lend_container.replace(*refer).is_none(),
                "somehow, multiple references are stored in the same CoapLendableFfiRcCell"
            );
        }
    }
}