Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  util.rs

  Sprache: Rust
 

/* 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 http://mozilla.org/MPL/2.0/. */


use crate::ffiops;
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, ToTokens};
use std::path::{Path as StdPath, PathBuf};
use syn::{
    ext::IdentExt,
    parse::{Parse, ParseStream},
    Attribute, Expr, Lit, Token,
};

pub fn manifest_path() -> Result<PathBuf, String> {
    let manifest_dir =
        std::env::var_os("CARGO_MANIFEST_DIR").ok_or("`CARGO_MANIFEST_DIR` is not set")?;

    Ok(StdPath::new(&manifest_dir).join("Cargo.toml"))
}

#[cfg(not(feature = "nightly"))]
pub fn mod_path() -> syn::Result<String> {
    // Without the nightly feature and TokenStream::expand_expr, just return the crate name

    use fs_err as fs;
    use once_cell::sync::Lazy;
    use serde::Deserialize;

    #[derive(Deserialize)]
    struct CargoToml {
        package: Package,
        #[serde(default)]
        lib: Lib,
    }

    #[derive(Deserialize)]
    struct Package {
        name: String,
    }

    #[derive(Default, Deserialize)]
    struct Lib {
        name: Option<String>,
    }

    static LIB_CRATE_MOD_PATH: Lazy<Result<String, String>> = Lazy::new(|| {
        let file = manifest_path()?;
        let cargo_toml_bytes = fs::read(file).map_err(|e| e.to_string())?;

        let cargo_toml = toml::from_slice::<CargoToml>(&cargo_toml_bytes)
            .map_err(|e| format!("Failed to parse `Cargo.toml`: {e}"))?;

        let lib_crate_name = cargo_toml
            .lib
            .name
            .unwrap_or_else(|| cargo_toml.package.name.replace('-'"_"));

        Ok(lib_crate_name)
    });

    LIB_CRATE_MOD_PATH
        .clone()
        .map_err(|e| syn::Error::new(Span::call_site(), e))
}

#[cfg(feature = "nightly")]
pub fn mod_path() -> syn::Result<String> {
    use proc_macro::TokenStream;

    let module_path_invoc = TokenStream::from(quote! { ::core::module_path!() });
    // We ask the compiler what `module_path!()` expands to here.
    // This is a nightly feature, tracked at https://github.com/rust-lang/rust/issues/90765
    let expanded_module_path = TokenStream::expand_expr(&module_path_invoc)
        .map_err(|e| syn::Error::new(Span::call_site(), e))?;
    Ok(syn::parse::<syn::LitStr>(expanded_module_path)?.value())
}

pub fn try_read_field(f: &syn::Field) -> TokenStream {
    let ident = &f.ident;
    let try_read = ffiops::try_read(&f.ty);

    match ident {
        Some(ident) => quote! {
            #ident#try_read(buf)?,
        },
        None => quote! {
            #try_read(buf)?,
        },
    }
}

pub fn ident_to_string(ident: &Ident) -> String {
    ident.unraw().to_string()
}

pub fn crate_name() -> String {
    std::env::var("CARGO_CRATE_NAME").unwrap().replace('-'"_")
}

pub fn create_metadata_items(
    kind: &str,
    name: &str,
    metadata_expr: TokenStream,
    checksum_fn_name: Option<String>,
) -> TokenStream {
    let crate_name = crate_name();
    let crate_name_upper = crate_name.to_uppercase();
    let kind_upper = kind.to_uppercase();
    let name_upper = name.to_uppercase();
    let const_ident =
        format_ident!("UNIFFI_META_CONST_{crate_name_upper}_{kind_upper}_{name_upper}");
    let static_ident = format_ident!("UNIFFI_META_{crate_name_upper}_{kind_upper}_{name_upper}");
    let checksum_fn = checksum_fn_name.map(|name| {
        let ident = Ident::new(&name, Span::call_site());
        quote! {
            #[doc(hidden)]
            #[no_mangle]
            pub extern "C" fn #ident() -> u16 {
                // Force constant evaluation to ensure:
                // 1. The checksum is computed at compile time; and
                // 2. The metadata buffer is not embedded into the binary.
                const CHECKSUM: u16 = #const_ident.checksum();
                CHECKSUM
            }
        }
    });

    quote! {
        const #const_ident: ::uniffi::MetadataBuffer = #metadata_expr;
        #[no_mangle]
        #[doc(hidden)]
        pub static #static_ident: [u8; #const_ident.size] = #const_ident.into_array();

        #checksum_fn
    }
}

pub fn try_metadata_value_from_usize(value: usize, error_message: &str) -> syn::Result<u8> {
    value
        .try_into()
        .map_err(|_| syn::Error::new(Span::call_site(), error_message))
}

pub fn chain<T>(
    a: impl IntoIterator<Item = T>,
    b: impl IntoIterator<Item = T>,
) -> impl Iterator<Item = T> {
    a.into_iter().chain(b)
}

pub trait UniffiAttributeArgs: Default {
    fn parse_one(input: ParseStream<'_>) -> syn::Result<Self>;
    fn merge(self, other: Self) -> syn::Result<Self>;
}

pub fn parse_comma_separated<T: UniffiAttributeArgs>(input: ParseStream<'_>) -> syn::Result<T> {
    let punctuated = input.parse_terminated(T::parse_one, Token![,])?;
    punctuated.into_iter().try_fold(T::default(), T::merge)
}

#[derive(Default)]
struct ArgumentNotAllowedHere;

impl UniffiAttributeArgs for ArgumentNotAllowedHere {
    fn parse_one(input: ParseStream<'_>) -> syn::Result<Self> {
        Err(syn::Error::new(
            input.span(),
            "attribute arguments are not currently recognized in this position",
        ))
    }

    fn merge(self, _other: Self) -> syn::Result<Self> {
        Ok(Self)
    }
}

pub trait AttributeSliceExt {
    fn parse_uniffi_attr_args<T: UniffiAttributeArgs>(&self) -> syn::Result<T>;
    fn uniffi_attr_args_not_allowed_here(&self) -> Option<syn::Error> {
        self.parse_uniffi_attr_args::<ArgumentNotAllowedHere>()
            .err()
    }
}

impl AttributeSliceExt for [Attribute] {
    fn parse_uniffi_attr_args<T: UniffiAttributeArgs>(&self) -> syn::Result<T> {
        self.iter()
            .filter(|attr| attr.path().is_ident("uniffi"))
            .try_fold(T::default(), |res, attr| {
                let parsed = attr.parse_args_with(parse_comma_separated)?;
                res.merge(parsed)
            })
    }
}

pub fn either_attribute_arg<T: ToTokens>(a: Option<T>, b: Option<T>) -> syn::Result<Option<T>> {
    match (a, b) {
        (None, None) => Ok(None),
        (Some(val), None) | (None, Some(val)) => Ok(Some(val)),
        (Some(a), Some(b)) => {
            let mut error = syn::Error::new_spanned(a, "redundant attribute argument");
            error.combine(syn::Error::new_spanned(b, "note: first one here"));
            Err(error)
        }
    }
}

pub(cratefn tagged_impl_header(
    trait_name: &str,
    ident: &impl ToTokens,
    udl_mode: bool,
) -> TokenStream {
    let trait_name = Ident::new(trait_name, Span::call_site());
    if udl_mode {
        quote! { impl ::uniffi::#trait_name<crate::UniFfiTag> for #ident }
    } else {
        quote! { impl<T> ::uniffi::#trait_name<T> for #ident }
    }
}

pub(cratefn derive_all_ffi_traits(ty: &Ident, udl_mode: bool) -> TokenStream {
    if udl_mode {
        quote! { ::uniffi::derive_ffi_traits!(local #ty); }
    } else {
        quote! { ::uniffi::derive_ffi_traits!(blanket #ty); }
    }
}

pub(cratefn derive_ffi_traits(
    ty: impl ToTokens,
    udl_mode: bool,
    trait_names: &[&str],
) -> TokenStream {
    let trait_idents = trait_names
        .iter()
        .map(|name| Ident::new(name, Span::call_site()));
    if udl_mode {
        quote! {
            #(
                ::uniffi::derive_ffi_traits!(impl #trait_idents<crate::UniFfiTag> for #ty);
            )*
        }
    } else {
        quote! {
            #(
                ::uniffi::derive_ffi_traits!(impl<UT> #trait_idents<UT> for #ty);
            )*
        }
    }
}

/// Custom keywords
pub mod kw {
    syn::custom_keyword!(async_runtime);
    syn::custom_keyword!(callback_interface);
    syn::custom_keyword!(with_foreign);
    syn::custom_keyword!(default);
    syn::custom_keyword!(flat_error);
    syn::custom_keyword!(None);
    syn::custom_keyword!(Some);
    syn::custom_keyword!(with_try_read);
    syn::custom_keyword!(name);
    syn::custom_keyword!(non_exhaustive);
    syn::custom_keyword!(Record);
    syn::custom_keyword!(Enum);
    syn::custom_keyword!(Error);
    syn::custom_keyword!(Object);
    syn::custom_keyword!(Debug);
    syn::custom_keyword!(Display);
    syn::custom_keyword!(Eq);
    syn::custom_keyword!(Hash);
    // Not used anymore
    syn::custom_keyword!(handle_unknown_callback_error);
}

/// Specifies a type from a dependent crate
pub struct ExternalTypeItem {
    pub crate_ident: Ident,
    pub sep: Token![,],
    pub type_ident: Ident,
}

impl Parse for ExternalTypeItem {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        Ok(Self {
            crate_ident: input.parse()?,
            sep: input.parse()?,
            type_ident: input.parse()?,
        })
    }
}

pub(cratefn extract_docstring(attrs: &[Attribute]) -> syn::Result<String> {
    return attrs
        .iter()
        .filter(|attr| attr.path().is_ident("doc"))
        .map(|attr| {
            let name_value = attr.meta.require_name_value()?;
            if let Expr::Lit(expr) = &name_value.value {
                if let Lit::Str(lit_str) = &expr.lit {
                    return Ok(lit_str.value().trim().to_owned());
                }
            }
            Err(syn::Error::new_spanned(attr, "Cannot parse doc attribute"))
        })
        .collect::<syn::Result<Vec<_>>>()
        .map(|lines| lines.join("\n"));
}

Messung V0.5 in Prozent
C=86 H=95 G=90

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet am  2026-06-18) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik