Skip to content

Commit d8a177e

Browse files
MirageLyudjc
authored andcommitted
Support ohos tzdata since oh35
1 parent 05a6ce6 commit d8a177e

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/offset/local/tz_info/parser.rs

+15
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,21 @@ impl<'a> Cursor<'a> {
247247
Ok(u32::from_be_bytes(buf))
248248
}
249249

250+
#[cfg(target_env = "ohos")]
251+
pub(crate) fn seek_after(&mut self, offset: usize) -> Result<usize, io::Error> {
252+
if offset < self.read_count {
253+
return Err(io::Error::from(ErrorKind::UnexpectedEof));
254+
}
255+
match self.remaining.get((offset - self.read_count)..) {
256+
Some(remaining) => {
257+
self.remaining = remaining;
258+
self.read_count = offset;
259+
Ok(offset)
260+
}
261+
_ => Err(io::Error::from(ErrorKind::UnexpectedEof)),
262+
}
263+
}
264+
250265
/// Read exactly `count` bytes, reducing remaining data and incrementing read count
251266
pub(crate) fn read_exact(&mut self, count: usize) -> Result<&'a [u8], io::Error> {
252267
match (self.remaining.get(..count), self.remaining.get(count..)) {

src/offset/local/tz_info/timezone.rs

+61
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use std::{cmp::Ordering, fmt, str};
88
use super::rule::{AlternateTime, TransitionRule};
99
use super::{parser, Error, DAYS_PER_WEEK, SECONDS_PER_DAY};
1010

11+
#[cfg(target_env = "ohos")]
12+
use crate::offset::local::tz_info::parser::Cursor;
13+
1114
/// Time zone
1215
#[derive(Debug, Clone, Eq, PartialEq)]
1316
pub(crate) struct TimeZone {
@@ -50,6 +53,12 @@ impl TimeZone {
5053
}
5154
}
5255

56+
// ohos merge all file into tzdata since ver35
57+
#[cfg(target_env = "ohos")]
58+
{
59+
return Self::from_tz_data(&find_ohos_tz_data(tz_string)?);
60+
}
61+
5362
let mut chars = tz_string.chars();
5463
if chars.next() == Some(':') {
5564
return Self::from_file(&mut find_tz_file(chars.as_str())?);
@@ -629,6 +638,58 @@ fn find_tz_file(path: impl AsRef<Path>) -> Result<File, Error> {
629638
}
630639
}
631640

641+
#[cfg(target_env = "ohos")]
642+
fn from_tzdata_bytes(bytes: &mut Vec<u8>, tz_string: &str) -> Result<Vec<u8>, Error> {
643+
const VERSION_SIZE: usize = 12;
644+
const OFFSET_SIZE: usize = 4;
645+
const INDEX_CHUNK_SIZE: usize = 48;
646+
const ZONENAME_SIZE: usize = 40;
647+
648+
let mut cursor = Cursor::new(&bytes);
649+
// version head
650+
let _ = cursor.read_exact(VERSION_SIZE)?;
651+
let index_offset_offset = cursor.read_be_u32()?;
652+
let data_offset_offset = cursor.read_be_u32()?;
653+
// final offset
654+
let _ = cursor.read_be_u32()?;
655+
656+
cursor.seek_after(index_offset_offset as usize)?;
657+
let mut idx = index_offset_offset;
658+
while idx < data_offset_offset {
659+
let index_buf = cursor.read_exact(ZONENAME_SIZE)?;
660+
let offset = cursor.read_be_u32()?;
661+
let length = cursor.read_be_u32()?;
662+
let zone_name = str::from_utf8(index_buf)?.trim_end_matches('\0');
663+
if zone_name != tz_string {
664+
idx += INDEX_CHUNK_SIZE as u32;
665+
continue;
666+
}
667+
cursor.seek_after((data_offset_offset + offset) as usize)?;
668+
return match cursor.read_exact(length as usize) {
669+
Ok(result) => Ok(result.to_vec()),
670+
Err(_err) => Err(Error::InvalidTzFile("invalid ohos tzdata chunk")),
671+
};
672+
}
673+
674+
Err(Error::InvalidTzString("cannot find tz string within tzdata"))
675+
}
676+
677+
#[cfg(target_env = "ohos")]
678+
fn from_tzdata_file(file: &mut File, tz_string: &str) -> Result<Vec<u8>, Error> {
679+
let mut bytes = Vec::new();
680+
file.read_to_end(&mut bytes)?;
681+
from_tzdata_bytes(&mut bytes, tz_string)
682+
}
683+
684+
#[cfg(target_env = "ohos")]
685+
fn find_ohos_tz_data(tz_string: &str) -> Result<Vec<u8>, Error> {
686+
const TZDATA_PATH: &str = "/system/etc/zoneinfo/tzdata";
687+
match File::open(TZDATA_PATH) {
688+
Ok(mut file) => from_tzdata_file(&mut file, tz_string),
689+
Err(err) => Err(err.into()),
690+
}
691+
}
692+
632693
// Possible system timezone directories
633694
#[cfg(unix)]
634695
const ZONE_INFO_DIRECTORIES: [&str; 4] =

0 commit comments

Comments
 (0)