// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use std::sync::LazyLock; #[doc(hidden)] pub extern crate serde as __serde; #[doc(hidden)] pub mod __serde_helper { /// Deserialize value to a `Vec`. /// /// If the value was `null` return an empty vector. pub fn vec_null<'de, D: serde::Deserializer<'de>, T: serde::Deserialize<'de>>( d: D, ) -> Result, D::Error> { let res: Option> = serde::Deserialize::deserialize(d)?; Ok(res.unwrap_or_default()) } } // Re-export types that are used by the glean_parser-generated code. #[doc(hidden)] pub mod __export { pub use once_cell::sync::Lazy; } const FFI_CONTRACT_VERSION: u32 = include!("contract_version.txt"); // Based on https://searchfox.org/firefox-main/rev/6193f8fd1172486e3ce941b8de251b9d1a4dfa0b/toolkit/crashreporter/client/app/src/net/libcurl.rs#84 macro_rules! library_binding { ( $localname:ident members[$($members:tt)*] load[$($load:tt)*] fn $name:ident $args:tt $( -> $ret:ty )? ; $($rest:tt)* ) => { library_binding! { $localname members[ $($members)* pub(crate) $name: libloading::Symbol<'static, unsafe extern "C" fn $args $(->$ret)?>, ] load[ $($load)* $name: unsafe { let symbol = $localname.get::$ret)?>(stringify!($name).as_bytes()) .map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, e))?; // All symbols refer to library, so `'static` lifetimes are safe (`library` // will outlive them). std::mem::transmute::<_, libloading::Symbol<'static, _>>(symbol) }, ] $($rest)* } }; ( $localname:ident members[$($members:tt)*] load[$($load:tt)*] ) => { pub struct GleanSym { $($members)* _library: libloading::Library, } impl GleanSym { #[cfg(all(unix, not(target_os = "ios")))] pub fn load() -> std::io::Result { let name = libloading::library_filename("xul"); let library = match unsafe { libloading::Library::new(name) } { Ok(lib) => Some(lib), Err(_e) => None, }; let $localname = library.ok_or_else(|| { std::io::Error::new(std::io::ErrorKind::NotFound, "failed to find glean library") })?; let handle = GleanSym { $($load)* _library: $localname }; handle.check()?; Ok(handle) } #[cfg(target_os = "ios")] pub fn load() -> std::io::Result { // On iOS we compile it all together and can look up symbols without loading a library let $localname: libloading::Library = libloading::os::unix::Library::this().into(); Ok(GleanSym { $($load)* _library: $localname }) } #[cfg(not(unix))] pub fn load() -> std::io::Result { compile_error!("This crate is not implemented for Windows"); } fn check(&self) -> std::io::Result<()> { let ffi_contract_version = unsafe { (self.ffi_glean_core_uniffi_contract_version)() }; if crate::FFI_CONTRACT_VERSION == ffi_contract_version { Ok(()) } else { Err(std::io::Error::other("contract version mismatch")) } } } }; ( $($rest:tt)* ) => { library_binding! { library members[] load[] $($rest)* } } } pub mod metrics; pub mod types; mod util; static GLEAN: LazyLock = LazyLock::new(|| metrics::GleanSym::load().unwrap()); // This boilerplate is usually generated by `uniffi::setup_scaffolding!()` // along with all the extra FFI functions, like wrappers around Rust buffer allocation, async handling, etc. // We don't want to export those, so we do only the minimal part to support what `glean-sym` calls when used in other // crates. /// The crate-specific tag to implement traits. #[doc(hidden)] pub struct UniFfiTag; /// The namespace glean-sym FFI items are placed in. /// Required by UniFFI to match up items. const UNIFFI_META_CONST_NAMESPACE_GLEAN_SYM: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::NAMESPACE) .concat_str("glean_sym") .concat_str("glean_sym"); #[doc(hidden)] #[unsafe(no_mangle)] pub static UNIFFI_META_NAMESPACE_GLEAN_SYM: [::std::primitive::u8; UNIFFI_META_CONST_NAMESPACE_GLEAN_SYM.size] = UNIFFI_META_CONST_NAMESPACE_GLEAN_SYM.into_array();