OXYGENHUB
◆ v0.9.0 oxygen / vendor / iana-time-zone / src / tz_ohos.rs
1.8 KiB · Rust · last changed Strata: the cloud stores send through ureq, so every release target links 1 month ago source blame history raw
1
//! OpenHarmony doesn't have `/etc/localtime`, we have to use it's "Time Service" to get the timezone information:
2
//!
3
//! - [API Reference](https://gitee.com/openharmony/docs/blob/43726785b4033887cd1a838aaaca5e255897a71e/en/application-dev/reference/apis-basic-services-kit/_time_service.md#oh_timeservice_gettimezone)
4
5
use crate::ffi_utils::buffer::{tzname_buf, MAX_LEN};
6
use crate::GetTimezoneError;
7
use std::ffi::{c_char, CStr};
8
9
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
10
#[repr(C)]
11
#[allow(non_camel_case_types)]
12
#[allow(dead_code)]
13
enum TimeService_ErrCode {
14
    TIMESERVICE_ERR_OK = 0,
15
    TIMESERVICE_ERR_INTERNAL_ERROR = 13000001,
16
    TIMESERVICE_ERR_INVALID_PARAMETER = 13000002,
17
}
18
19
#[link(name = "time_service_ndk", kind = "dylib")]
20
extern "C" {
21
    fn OH_TimeService_GetTimeZone(timeZone: *mut c_char, len: u32) -> TimeService_ErrCode;
22
}
23
24
/// TODO: Change this `CStr::from_bytes_until_nul` once MSRV was bumped above 1.69.0
25
fn from_bytes_until_nul(bytes: &[u8]) -> Option<&CStr> {
26
    let nul_pos = bytes.iter().position(|&b| b == 0)?;
27
    // SAFETY:
28
    // 1. nul_pos + 1 <= bytes.len()
29
    // 2. We know there is a nul byte at nul_pos, so this slice (ending at the nul byte) is a well-formed C string.
30
    Some(unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[..=nul_pos]) })
31
}
32
33
pub(crate) fn get_timezone_inner() -> Result<String, GetTimezoneError> {
34
    let mut time_zone = tzname_buf();
35
    // SAFETY:
36
    // `time_zone` is a valid buffer with a length of 40 bytes.
37
    let ret = unsafe {
38
        OH_TimeService_GetTimeZone(time_zone.as_mut_ptr().cast::<c_char>(), MAX_LEN as u32 - 1)
39
    };
40
    if ret != TimeService_ErrCode::TIMESERVICE_ERR_OK {
41
        return Err(GetTimezoneError::OsError);
42
    }
43
    from_bytes_until_nul(&time_zone)
44
        .and_then(|x| x.to_str().ok())
45
        .map(|x| x.to_owned())
46
        .ok_or(GetTimezoneError::OsError)
47
}