libloading/
as_symbol_name.rs

1use crate::Error;
2use alloc::ffi::CString;
3use alloc::string::String;
4use core::ffi::CStr;
5
6pub(crate) trait Sealed {
7    fn symbol_name<R>(
8        self,
9        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, crate::Error>,
10    ) -> Result<R, crate::Error>;
11}
12
13/// This trait is implemented for types [`Library`](crate::Library) implementations can use to look
14/// up symbols.
15///
16/// It is currently sealed and cannot be implemented or its methods called by users of this crate.
17#[expect(private_bounds)]
18pub trait AsSymbolName: Sealed {}
19
20impl AsSymbolName for &str {}
21impl Sealed for &str {
22    fn symbol_name<R>(
23        self,
24        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
25    ) -> Result<R, Error> {
26        self.as_bytes().symbol_name(function)
27    }
28}
29
30impl AsSymbolName for &String {}
31impl Sealed for &String {
32    fn symbol_name<R>(
33        self,
34        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
35    ) -> Result<R, Error> {
36        self.as_str().symbol_name(function)
37    }
38}
39
40impl AsSymbolName for String {}
41impl Sealed for String {
42    fn symbol_name<R>(
43        mut self,
44        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
45    ) -> Result<R, Error> {
46        if crate::util::check_null_bytes(self.as_bytes())? {
47            function(self.as_ptr().cast())
48        } else {
49            self.push('\0');
50            function(self.as_ptr().cast())
51        }
52    }
53}
54
55impl AsSymbolName for &CStr {}
56impl Sealed for &CStr {
57    fn symbol_name<R>(
58        self,
59        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
60    ) -> Result<R, Error> {
61        function(self.as_ptr())
62    }
63}
64
65impl AsSymbolName for &CString {}
66impl Sealed for &CString {
67    fn symbol_name<R>(
68        self,
69        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
70    ) -> Result<R, Error> {
71        function(self.as_ptr())
72    }
73}
74
75impl AsSymbolName for CString {}
76impl Sealed for CString {
77    fn symbol_name<R>(
78        self,
79        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
80    ) -> Result<R, Error> {
81        function(self.as_ptr())
82    }
83}
84
85impl AsSymbolName for &[u8] {}
86impl Sealed for &[u8] {
87    fn symbol_name<R>(
88        self,
89        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
90    ) -> Result<R, Error> {
91        if crate::util::check_null_bytes(self)? {
92            function(self.as_ptr().cast())
93        } else {
94            let copy = crate::util::copy_and_push(self, 0);
95            function(copy.as_ptr().cast())
96        }
97    }
98}
99
100impl<const N: usize> AsSymbolName for [u8; N] {}
101impl<const N: usize> Sealed for [u8; N] {
102    fn symbol_name<R>(
103        self,
104        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
105    ) -> Result<R, Error> {
106        self.as_slice().symbol_name(function)
107    }
108}
109
110impl<const N: usize> AsSymbolName for &[u8; N] {}
111impl<const N: usize> Sealed for &[u8; N] {
112    fn symbol_name<R>(
113        self,
114        function: impl FnOnce(*const core::ffi::c_char) -> Result<R, Error>,
115    ) -> Result<R, Error> {
116        self.as_slice().symbol_name(function)
117    }
118}