Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement for Haiku #66

Merged
merged 16 commits into from Oct 8, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/rust.yml
Expand Up @@ -212,6 +212,34 @@ jobs:
- run: cargo check --all-targets
- run: cargo clippy --all-targets -- -D warnings

no-docker-image-check-only:
strategy:
fail-fast: false
matrix:
target:
# - i686-unknown-haiku # Does not (cross) compile for 32bit
- x86_64-unknown-haiku
versions:
- ""
- "-Zminimal-versions"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust
id: actions-rs
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: rust-src
- name: Update lockfile
run: cargo generate-lockfile ${{ matrix.versions }}
env:
RUSTC_BOOTSTRAP: 1
- run: cargo +nightly check --target ${{ matrix.target }} -Z build-std --examples

doc:
runs-on: ubuntu-latest
steps:
Expand Down
6 changes: 6 additions & 0 deletions Cargo.toml
Expand Up @@ -29,3 +29,9 @@ wasm-bindgen = "0.2.70"

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3"

[target.'cfg(target_os = "haiku")'.dependencies]
cxx = "1.0.34"

[target.'cfg(target_os = "haiku")'.build-dependencies]
cxx-build = "1.0.34"
14 changes: 14 additions & 0 deletions build.rs
@@ -0,0 +1,14 @@
fn main() {
#[cfg(target_os = "haiku")]
let _: () = {
cxx_build::bridge("src/tz_haiku.rs")
.file("src/impl_haiku.cc")
.flag_if_supported("-std=c++11")
.compile("tz_haiku");

println!("cargo:return-if-changed=include/impl_haiku.h");
println!("cargo:return-if-changed=src/impl_haiku.cc");
println!("cargo:return-if-changed=src/tz_haiku.rs");
println!("cargo:rustc-link-lib=be");
};
}
9 changes: 9 additions & 0 deletions include/impl_haiku.h
@@ -0,0 +1,9 @@
#pragma once

#include "rust/cxx.h"

#include <cstddef>

namespace tz_haiku {
size_t get_tz(uint8_t *buf, size_t buf_len);
lopopolo marked this conversation as resolved.
Show resolved Hide resolved
}
40 changes: 40 additions & 0 deletions src/impl_haiku.cc
@@ -0,0 +1,40 @@
#include "iana-time-zone/include/impl_haiku.h"
#include "iana-time-zone/src/tz_haiku.rs.h"

#include <cstring>
#include <Errors.h>
#include <LocaleRoster.h>
#include <String.h>
#include <TimeZone.h>

size_t ::tz_haiku::get_tz(uint8_t *buf, size_t buf_len) {
lopopolo marked this conversation as resolved.
Show resolved Hide resolved
static_assert(sizeof(char) == sizeof(uint8_t), "Illegal char size");
lopopolo marked this conversation as resolved.
Show resolved Hide resolved

if (!buf || !buf_len) {
return 0;
}

BLocaleRoster *locale_roster(BLocaleRoster::Default());
if (!locale_roster) {
return 0;
}

BTimeZone tz(NULL, NULL);
if (locale_roster->GetDefaultTimeZone(&tz) != B_OK) {
return 0;
}

BString bname(tz.ID());
int32_t length(bname.Length());
if (length <= 0 || size_t(length) > buf_len) {
return 0;
}

const char *sname(bname.String());
lopopolo marked this conversation as resolved.
Show resolved Hide resolved
if (!sname) {
return 0;
}

std::memcpy(buf, sname, length);
return length;
}
1 change: 1 addition & 0 deletions src/lib.rs
Expand Up @@ -38,6 +38,7 @@
path = "tz_illumos.rs"
)]
#[cfg_attr(target_os = "android", path = "tz_android.rs")]
#[cfg_attr(target_os = "haiku", path = "tz_haiku.rs")]
mod platform;

/// Error types
Expand Down
2 changes: 1 addition & 1 deletion src/platform.rs
Expand Up @@ -5,5 +5,5 @@ pub fn get_timezone_inner() -> std::result::Result<String, crate::GetTimezoneErr
#[cfg(not(feature = "fallback"))]
compile_error!(
"iana-time-zone is currently implemented for Linux, Window, MacOS, FreeBSD, NetBSD, \
OpenBSD, Dragonfly, WebAssembly (browser), iOS, Illumos, Android, and Solaris.",
OpenBSD, Dragonfly, WebAssembly (browser), iOS, Illumos, Android, Solaris and Haiku.",
);
23 changes: 23 additions & 0 deletions src/tz_haiku.rs
@@ -0,0 +1,23 @@
#[cxx::bridge(namespace = "tz_haiku")]
mod ffi {
unsafe extern "C++" {
include!("iana-time-zone/include/impl_haiku.h");

/// SAFETY: `buf` must be valid and be at least `buf_len` bytes long
unsafe fn get_tz(buf: *mut u8, buf_len: usize) -> usize;
lopopolo marked this conversation as resolved.
Show resolved Hide resolved
}
}

pub(crate) fn get_timezone_inner() -> Result<String, crate::GetTimezoneError> {
// The longest name in the IANA time zone database is 25 ASCII characters long.
let mut buf = [0u8; 32];
// SAFETY: the buffer is valid and called function ensures that sizeof(u8) == sizeof(c_char)
lopopolo marked this conversation as resolved.
Show resolved Hide resolved
let len = unsafe { ffi::get_tz(buf.as_mut_ptr(), buf.len()) };
// The name should not be empty, or excessively long.
if len > 0 && len < buf.len() {
let s = std::str::from_utf8(&buf[..len]).map_err(|_| crate::GetTimezoneError::OsError)?;
Ok(s.to_owned())
} else {
Err(crate::GetTimezoneError::OsError)
}
Kijewski marked this conversation as resolved.
Show resolved Hide resolved
}