open62541/ua/
server.rs

1use std::ptr::NonNull;
2
3use open62541_sys::{UA_Server, UA_Server_delete, UA_Server_newWithConfig};
4
5use crate::{Error, ua};
6
7/// Wrapper for [`UA_Server`] from [`open62541_sys`].
8///
9/// This owns the wrapped data type. When the wrapper is dropped, its inner value is cleaned up with
10/// [`UA_Server_delete()`].
11#[derive(Debug)]
12pub struct Server(NonNull<UA_Server>);
13
14// SAFETY: We know that the underlying `UA_Server` allows access from different threads, i.e. it may
15// be dropped in a different thread from where it was created.
16unsafe impl Send for Server {}
17
18// SAFETY: The underlying `UA_Server` can be used from different threads concurrently, at least with
19// _most_ methods (those marked `UA_THREADSAFE` and/or with explicit mutex locks inside).
20unsafe impl Sync for Server {}
21
22impl Server {
23    /// Creates server from server config.
24    ///
25    /// This consumes the config object and makes the server the owner of all contained data therein
26    /// (e.g. logging configuration and logger instance).
27    pub(crate) fn new_with_config(config: ua::ServerConfig) -> Self {
28        let mut config = config.into_raw();
29        let inner = unsafe { UA_Server_newWithConfig(&raw mut config) };
30        // PANIC: The only possible errors here are out-of-memory.
31        let inner = NonNull::new(inner).expect("create UA_Server");
32        Self(inner)
33    }
34
35    /// Returns const pointer to value.
36    ///
37    /// # Safety
38    ///
39    /// The value is owned by `Self`. Ownership must not be given away, in whole or in parts. This
40    /// may happen when `open62541` functions are called that take ownership of values by pointer.
41    #[must_use]
42    pub(crate) const unsafe fn as_ptr(&self) -> *const UA_Server {
43        self.0.as_ptr()
44    }
45
46    /// Returns mutable pointer to value.
47    ///
48    /// # Safety
49    ///
50    /// The value is owned by `Self`. Ownership must not be given away, in whole or in parts. This
51    /// may happen when `open62541` functions are called that take ownership of values by pointer.
52    #[must_use]
53    #[expect(clippy::allow_attributes, reason = "non-static condition")]
54    #[allow(clippy::missing_const_for_fn, reason = "unsupported before Rust 1.87")]
55    pub(crate) unsafe fn as_mut_ptr(&mut self) -> *mut UA_Server {
56        self.0.as_ptr()
57    }
58}
59
60impl Drop for Server {
61    fn drop(&mut self) {
62        log::debug!("Deleting server");
63
64        let status_code = ua::StatusCode::new(unsafe {
65            // SAFETY: We retain ownership of `self`.
66            UA_Server_delete(self.as_mut_ptr())
67        });
68        if let Err(error) = Error::verify_good(&status_code) {
69            log::warn!("Error while dropping server: {error}");
70        }
71    }
72}