Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  link.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// SPDX-License-Identifier: Apache-2.0

//================================================
// Macros
//================================================

#[cfg(feature = "runtime")]
macro_rules! link {
    (
        @LOAD:
        $(#[doc=$doc:expr])*
        #[cfg($cfg:meta)]
        fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*
    ) => (
        $(#[doc=$doc])*
        #[cfg($cfg)]
        pub fn $name(library: &mut super::SharedLibrary) {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
            library.functions.$name = match symbol {
                Some(s) => *s,
                None => None,
            };
        }

        #[cfg(not($cfg))]
        pub fn $name(_: &mut super::SharedLibrary) {}
    );

    (
        @LOAD:
        fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*
    ) => (
        link!(@LOAD: #[cfg(feature = "runtime")] fn $name($($pname: $pty), *) $(-> $ret)*);
    );

    (
        $(
            $(#[doc=$doc:expr] #[cfg($cfg:meta)])*
            pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;
        )+
    ) => (
        use std::cell::{RefCell};
        use std::fmt;
        use std::sync::{Arc};
        use std::path::{Path, PathBuf};

        /// The (minimum) version of a `libclang` shared library.
        #[allow(missing_docs)]
        #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
        pub enum Version {
            V3_5 = 35,
            V3_6 = 36,
            V3_7 = 37,
            V3_8 = 38,
            V3_9 = 39,
            V4_0 = 40,
            V5_0 = 50,
            V6_0 = 60,
            V7_0 = 70,
            V8_0 = 80,
            V9_0 = 90,
            V11_0 = 110,
            V12_0 = 120,
            V16_0 = 160,
            V17_0 = 170,
        }

        impl fmt::Display for Version {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                use Version::*;
                match self {
                    V3_5 => write!(f, "3.5.x"),
                    V3_6 => write!(f, "3.6.x"),
                    V3_7 => write!(f, "3.7.x"),
                    V3_8 => write!(f, "3.8.x"),
                    V3_9 => write!(f, "3.9.x"),
                    V4_0 => write!(f, "4.0.x"),
                    V5_0 => write!(f, "5.0.x"),
                    V6_0 => write!(f, "6.0.x"),
                    V7_0 => write!(f, "7.0.x"),
                    V8_0 => write!(f, "8.0.x"),
                    V9_0 => write!(f, "9.0.x - 10.0.x"),
                    V11_0 => write!(f, "11.0.x"),
                    V12_0 => write!(f, "12.0.x - 15.0.x"),
                    V16_0 => write!(f, "16.0.x"),
                    V17_0 => write!(f, "17.0.x or later"),
                }
            }
        }

        /// The set of functions loaded dynamically.
        #[derive(Debug, Default)]
        pub struct Functions {
            $(
                $(#[doc=$doc] #[cfg($cfg)])*
                pub $name: Option<unsafe extern fn($($pname: $pty), *) $(-> $ret)*>,
            )+
        }

        /// A dynamically loaded instance of the `libclang` library.
        #[derive(Debug)]
        pub struct SharedLibrary {
            library: libloading::Library,
            path: PathBuf,
            pub functions: Functions,
        }

        impl SharedLibrary {
            fn new(library: libloading::Library, path: PathBuf) -> Self {
                Self { library, path, functions: Functions::default() }
            }

            /// Returns the path to this `libclang` shared library.
            pub fn path(&self) -> &Path {
                &self.path
            }

            /// Returns the (minimum) version of this `libclang` shared library.
            ///
            /// If this returns `None`, it indicates that the version is too old
            /// to be supported by this crate (i.e., `3.4` or earlier). If the
            /// version of this shared library is more recent than that fully
            /// supported by this crate, the most recent fully supported version
            /// will be returned.
            pub fn version(&self) -> Option<Version> {
                macro_rules! check {
                    ($fn:expr, $version:ident) => {
                        if self.library.get::<unsafe extern fn()>($fn).is_ok() {
                            return Some(Version::$version);
                        }
                    };
                }

                unsafe {
                    check!(b"clang_CXXMethod_isExplicit", V17_0);
                    check!(b"clang_CXXMethod_isCopyAssignmentOperator", V16_0);
                    check!(b"clang_Cursor_getVarDeclInitializer", V12_0);
                    check!(b"clang_Type_getValueType", V11_0);
                    check!(b"clang_Cursor_isAnonymousRecordDecl", V9_0);
                    check!(b"clang_Cursor_getObjCPropertyGetterName", V8_0);
                    check!(b"clang_File_tryGetRealPathName", V7_0);
                    check!(b"clang_CXIndex_setInvocationEmissionPathOption", V6_0);
                    check!(b"clang_Cursor_isExternalSymbol", V5_0);
                    check!(b"clang_EvalResult_getAsLongLong", V4_0);
                    check!(b"clang_CXXConstructor_isConvertingConstructor", V3_9);
                    check!(b"clang_CXXField_isMutable", V3_8);
                    check!(b"clang_Cursor_getOffsetOfField", V3_7);
                    check!(b"clang_Cursor_getStorageClass", V3_6);
                    check!(b"clang_Type_getNumTemplateArguments", V3_5);
                }

                None
            }
        }

        thread_local!(static LIBRARY: RefCell<Option<Arc<SharedLibrary>>> = RefCell::new(None));

        /// Returns whether a `libclang` shared library is loaded on this thread.
        pub fn is_loaded() -> bool {
            LIBRARY.with(|l| l.borrow().is_some())
        }

        fn with_library<T, F>(f: F) -> Option<T> where F: FnOnce(&SharedLibrary) -> T {
            LIBRARY.with(|l| {
                match l.borrow().as_ref() {
                    Some(library) => Some(f(&library)),
                    _ => None,
                }
            })
        }

        $(
            #[cfg_attr(feature="cargo-clippy", allow(clippy::missing_safety_doc))]
            #[cfg_attr(feature="cargo-clippy", allow(clippy::too_many_arguments))]
            $(#[doc=$doc] #[cfg($cfg)])*
            pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = with_library(|library| {
                    if let Some(function) = library.functions.$name {
                        function
                    } else {
                        panic!(
                            r#"
A `libclang` function was called that is not supported by the loaded `libclang` instance.

    called function = `{0}`
    loaded `libclang` instance = {1}

This crate only supports `libclang` 3.5 and later.
The minimum `libclang` requirement for this particular function can be found here:
https://docs.rs/clang-sys/latest/clang_sys/{0}/index.html

Instructions for installing `libclang` can be found here:
https://rust-lang.github.io/rust-bindgen/requirements.html
"#, 
                            stringify!($name),
                            library
                                .version()
                                .map(|v| format!("{}", v))
                                .unwrap_or_else(|| "unsupported version".into()),
                        );
                    }
                }).expect("a `libclang` shared library is not loaded on this thread");
                f($($pname), *)
            }

            $(#[doc=$doc] #[cfg($cfg)])*
            pub mod $name {
                pub fn is_loaded() -> bool {
                    super::with_library(|l| l.functions.$name.is_some()).unwrap_or(false)
                }
            }
        )+

        mod load {
            $(link!(@LOAD: $(#[cfg($cfg)])* fn $name($($pname: $pty), *) $(-> $ret)*);)+
        }

        /// Loads a `libclang` shared library and returns the library instance.
        ///
        /// This function does not attempt to load any functions from the shared library. The caller
        /// is responsible for loading the functions they require.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        pub fn load_manually() -> Result<SharedLibrary, String> {
            #[allow(dead_code)]
            mod build {
                include!(concat!(env!("OUT_DIR"), "/macros.rs"));
                pub mod common { include!(concat!(env!("OUT_DIR"), "/common.rs")); }
                pub mod dynamic { include!(concat!(env!("OUT_DIR"), "/dynamic.rs")); }
            }

            let (directory, filename) = build::dynamic::find(true)?;
            let path = directory.join(filename);

            unsafe {
                let library = libloading::Library::new(&path).map_err(|e| {
                    format!(
                        "the `libclang` shared library at {} could not be opened: {}",
                        path.display(),
                        e,
                    )
                });

                let mut library = SharedLibrary::new(library?, path);
                $(load::$name(&mut library);)+
                Ok(library)
            }
        }

        /// Loads a `libclang` shared library for use in the current thread.
        ///
        /// This functions attempts to load all the functions in the shared library. Whether a
        /// function has been loaded can be tested by calling the `is_loaded` function on the
        /// module with the same name as the function (e.g., `clang_createIndex::is_loaded()` for
        /// the `clang_createIndex` function).
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        #[allow(dead_code)]
        pub fn load() -> Result<(), String> {
            let library = Arc::new(load_manually()?);
            LIBRARY.with(|l| *l.borrow_mut() = Some(library));
            Ok(())
        }

        /// Unloads the `libclang` shared library in use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library is not in use in the current thread
        pub fn unload() -> Result<(), String> {
            let library = set_library(None);
            if library.is_some() {
                Ok(())
            } else {
                Err("a `libclang` shared library is not in use in the current thread".into())
            }
        }

        /// Returns the library instance stored in TLS.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn get_library() -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| l.borrow_mut().clone())
        }

        /// Sets the library instance stored in TLS and returns the previous library.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn set_library(library: Option<Arc<SharedLibrary>>) -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| mem::replace(&mut *l.borrow_mut(), library))
        }
    )
}

#[cfg(not(feature = "runtime"))]
macro_rules! link {
    (
        $(
            $(#[doc=$doc:expr] #[cfg($cfg:meta)])*
            pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;
        )+
    ) => (
        extern {
            $(
                $(#[doc=$doc] #[cfg($cfg)])*
                pub fn $name($($pname: $pty), *) $(-> $ret)*;
            )+
        }

        $(
            $(#[doc=$doc] #[cfg($cfg)])*
            pub mod $name {
                pub fn is_loaded() -> bool { true }
            }
        )+
    )
}

[ Dauer der Verarbeitung: 0.34 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge