Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  tz_darwin.rs

  Sprache: Rust
 

use crate::ffi_utils::buffer::{tzname_buf, MAX_LEN};

pub(cratefn get_timezone_inner() -> Result<String, crate::GetTimezoneError> {
    get_timezone().ok_or(crate::GetTimezoneError::OsError)
}

#[inline]
fn get_timezone() -> Option<String> {
    let mut buf = tzname_buf();
    // Get system time zone, and borrow its name.
    let tz = system_time_zone::SystemTimeZone::new()?;
    let name = tz.name()?;

    // If the name is encoded in UTF-8, copy it directly.
    let name = if let Some(name) = name.as_utf8() {
        name
    } else {
        // Otherwise convert the name to UTF-8.
        name.to_utf8(&mut buf)?
    };

    if name.is_empty() || name.len() > MAX_LEN {
        // The name should not be empty, or excessively long.
        None
    } else {
        Some(name.to_owned())
    }
}

mod system_time_zone {
    //! create a safe wrapper around `CFTimeZoneRef`

    use core_foundation_sys::base::{CFRelease, CFTypeRef};
    use core_foundation_sys::timezone::{
        CFTimeZoneCopySystem, CFTimeZoneGetName, CFTimeZoneRef, CFTimeZoneResetSystem,
    };

    pub(cratestruct SystemTimeZone(CFTimeZoneRef);

    impl Drop for SystemTimeZone {
        fn drop(&mut self) {
            // SAFETY: `SystemTimeZone` is only ever created with a valid `CFTimeZoneRef`.
            unsafe { CFRelease(self.0 as CFTypeRef) };
        }
    }

    impl SystemTimeZone {
        /// Creates a new `SystemTimeZone` by querying the current Darwin system
        /// timezone.
        ///
        /// This function implicitly calls `CFTimeZoneResetSystem` to invalidate
        /// the cached timezone and ensure we always retrieve the current system
        /// timezone.
        ///
        /// Due to CoreFoundation's internal caching mechanism, subsequent calls
        /// to `CFTimeZoneCopySystem` do not reflect system timezone changes
        /// made while the process is running. Thus, we explicitly call
        /// `CFTimeZoneResetSystem` first to invalidate the cached value and
        /// ensure we always retrieve the current system timezone.
        pub(cratefn new() -> Option<Self> {
            // SAFETY:
            // - Both `CFTimeZoneResetSystem` and `CFTimeZoneCopySystem` are FFI
            //   calls to macOS CoreFoundation.
            // - `CFTimeZoneResetSystem` safely invalidates the cached timezone
            //   without any external invariants.
            // - The pointer returned by `CFTimeZoneCopySystem` is managed and
            //   released properly within `Drop`.
            let v: CFTimeZoneRef = unsafe {
                // First, clear the potentially cached timezone. This call will
                // take the global lock on the timezone data.
                //
                // See <https://github.com/strawlab/iana-time-zone/issues/145#issuecomment-2745934606>
                // for context on why we reset the timezone here.
                CFTimeZoneResetSystem();

                // Fetch the current value. This will likely allocate. This call
                // will again take the global lock on the timezone data.
                CFTimeZoneCopySystem()
            };
            if v.is_null() {
                None
            } else {
                Some(SystemTimeZone(v))
            }
        }

        /// Get the time zone name as a [`StringRef`].
        ///
        /// The lifetime of the `StringRef` is bound to our lifetime. Mutable
        /// access is also prevented by taking a reference to `self`.
        ///
        /// [`StringRef`]: super::string_ref::StringRef
        pub(cratefn name(&self) -> Option<super::string_ref::StringRef<'_, Self>> {
            // SAFETY: `SystemTimeZone` is only ever created with a valid `CFTimeZoneRef`.
            let string = unsafe { CFTimeZoneGetName(self.0) };
            if string.is_null() {
                None
            } else {
                // SAFETY: here we ensure that `string` is a valid pointer.
                Some(unsafe { super::string_ref::StringRef::new(string, self) })
            }
        }
    }
}

mod string_ref {
    //! create safe wrapper around `CFStringRef`

    use core::convert::TryInto;

    use core_foundation_sys::base::{Boolean, CFRange};
    use core_foundation_sys::string::{
        kCFStringEncodingUTF8, CFStringGetBytes, CFStringGetCStringPtr, CFStringGetLength,
        CFStringRef,
    };

    pub(cratestruct StringRef<'a, T> {
        string: CFStringRef,
        // We exclude mutable access to the parent by taking a reference to the
        // parent (rather than, for example, just using a marker to enforce the
        // parent's lifetime).
        _parent: &'a T,
    }

    impl<'a, T> StringRef<'a, T> {
        // SAFETY: `string` must be valid pointer
        pub(crateunsafe fn new(string: CFStringRef, _parent: &'a T) -> Self {
            Self { string, _parent }
        }

        pub(cratefn as_utf8(&self) -> Option<&'a str> {
            // SAFETY: `StringRef` is only ever created with a valid `CFStringRef`.
            let v = unsafe { CFStringGetCStringPtr(self.string, kCFStringEncodingUTF8) };
            if !v.is_null() {
                // SAFETY: `CFStringGetCStringPtr()` returns NUL-terminated
                // strings and will return NULL if the internal representation
                // of the `CFString`` is not compatible with the requested
                // encoding.
                let v = unsafe { std::ffi::CStr::from_ptr(v) };
                if let Ok(v) = v.to_str() {
                    return Some(v);
                }
            }
            None
        }

        pub(cratefn to_utf8<'b>(&self, buf: &'mut [u8]) -> Option<&'b str> {
            // SAFETY: `StringRef` is only ever created with a valid `CFStringRef`.
            let length = unsafe { CFStringGetLength(self.string) };

            let mut buf_bytes = 0;
            let range = CFRange {
                location: 0,
                length,
            };

            // SAFETY: `StringRef` is only ever created with a valid `CFStringRef`.
            let converted_bytes = unsafe {
                CFStringGetBytes(
                    self.string,
                    range,
                    kCFStringEncodingUTF8,
                    b'\0',
                    false as Boolean,
                    buf.as_mut_ptr(),
                    buf.len() as isize,
                    &mut buf_bytes,
                )
            };
            if converted_bytes != length {
                return None;
            }

            let len = buf_bytes.try_into().ok()?;
            let s = buf.get(..len)?;
            std::str::from_utf8(s).ok()
        }
    }
}

Messung V0.5 in Prozent
C=82 H=94 G=88

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© 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

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002