Skip to content

Commit f2c56ae

Browse files
committed
feat: introduce KotlinInstant type for Kotlin bindings
1 parent bb85350 commit f2c56ae

File tree

8 files changed

+80
-5
lines changed

8 files changed

+80
-5
lines changed

crypto-ffi/bindings/android/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies {
2020
implementation(kotlin("stdlib-jdk7"))
2121
implementation("${libs.jna.get()}@aar")
2222
implementation(libs.coroutines.core)
23+
implementation(libs.kotlinx.datetime)
2324
implementation("androidx.annotation:annotation:1.9.1")
2425

2526
androidTestImplementation(kotlin("test"))

crypto-ffi/bindings/gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[versions]
22
kotlin = "1.9.25"
33
coroutines = "1.7.3"
4+
kotlinx-datetime = "0.6.1"
45
jna = "5.17.0"
56
assertj = "3.24.2"
67
espresso = "3.6.1"
@@ -29,3 +30,4 @@ espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "esp
2930
android-junit = { module = "androidx.test.ext:junit", version.ref = "android-junit" }
3031
android-tools = { module = "com.android.tools.build:gradle", version.ref = "android-tools" }
3132
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin-gradle" }
33+
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }

crypto-ffi/bindings/jvm/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies {
2020
implementation(kotlin("stdlib-jdk7"))
2121
implementation(libs.jna)
2222
implementation(libs.coroutines.core)
23+
implementation(libs.kotlinx.datetime)
2324
testImplementation(kotlin("test"))
2425
testImplementation(libs.coroutines.test)
2526
testImplementation(libs.assertj.core)

crypto-ffi/src/identity/x509.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use wasm_bindgen::prelude::*;
33

44
#[cfg(not(target_family = "wasm"))]
5-
use std::time::{Duration, SystemTime};
5+
use crate::Timestamp;
66

77
/// Represents the parts of [WireIdentity][crate::WireIdentity] that are specific to a X509 certificate (and not a Basic one).
88
///
@@ -39,7 +39,7 @@ pub struct X509Identity {
3939

4040
/// X509 certificate not before
4141
#[cfg(not(target_family = "wasm"))]
42-
pub not_before: SystemTime,
42+
pub not_before: Timestamp,
4343

4444
/// X509 certificate not after as Unix timestamp
4545
#[cfg(target_family = "wasm")]
@@ -48,7 +48,7 @@ pub struct X509Identity {
4848

4949
/// X509 certificate not after
5050
#[cfg(not(target_family = "wasm"))]
51-
pub not_after: SystemTime,
51+
pub not_after: Timestamp,
5252
}
5353

5454
impl From<core_crypto::prelude::X509Identity> for X509Identity {
@@ -60,10 +60,10 @@ impl From<core_crypto::prelude::X509Identity> for X509Identity {
6060
let not_after = i.not_after;
6161

6262
#[cfg(not(target_family = "wasm"))]
63-
let not_before = SystemTime::UNIX_EPOCH + Duration::from_secs(i.not_before);
63+
let not_before = Timestamp::from_epoch_secs(i.not_before);
6464

6565
#[cfg(not(target_family = "wasm"))]
66-
let not_after = SystemTime::UNIX_EPOCH + Duration::from_secs(i.not_after);
66+
let not_after = Timestamp::from_epoch_secs(i.not_after);
6767

6868
Self {
6969
handle: i.handle,

crypto-ffi/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ mod error;
2626
mod identity;
2727
mod metadata;
2828
mod proteus;
29+
#[cfg(not(target_family = "wasm"))]
30+
mod timestamp;
2931

3032
pub use bundles::{
3133
commit::CommitBundle, group_info::GroupInfoBundle, proteus_auto_prekey::ProteusAutoPrekeyBundle,
@@ -70,3 +72,5 @@ pub use identity::{
7072
x509::X509Identity,
7173
};
7274
pub use metadata::{BuildMetadata, build_metadata, version};
75+
#[cfg(not(target_family = "wasm"))]
76+
pub use timestamp::Timestamp;

crypto-ffi/src/timestamp.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//! Custom timestamp type for UniFFI bindings.
2+
//!
3+
//! This wrapper allows custom type mapping per target language:
4+
//! - Kotlin: maps to `kotlinx.datetime.Instant`
5+
//! - Swift: maps to `Date`
6+
//! - WASM: not changed
7+
//!
8+
//! This unifies timestamp handling across JVM/Android and KMP bindings.
9+
//! This can be removed once we fully migrate to Kotlin Multiplatform and
10+
//! stop generating JVM/Android bindings.
11+
12+
use std::time::{Duration, SystemTime};
13+
14+
/// A wrapper around `SystemTime` for FFI bindings with custom type mapping per language.
15+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
16+
pub struct Timestamp(pub SystemTime);
17+
18+
impl Timestamp {
19+
/// Creates a new `Timestamp` from a `SystemTime`.
20+
pub fn new(time: SystemTime) -> Self {
21+
Self(time)
22+
}
23+
24+
/// Creates a new `Timestamp` from seconds since the Unix epoch.
25+
pub fn from_epoch_secs(secs: u64) -> Self {
26+
Self(SystemTime::UNIX_EPOCH + Duration::from_secs(secs))
27+
}
28+
29+
/// Returns the inner `SystemTime`.
30+
pub fn into_inner(self) -> SystemTime {
31+
self.0
32+
}
33+
}
34+
35+
impl From<SystemTime> for Timestamp {
36+
fn from(time: SystemTime) -> Self {
37+
Self(time)
38+
}
39+
}
40+
41+
impl From<Timestamp> for SystemTime {
42+
fn from(timestamp: Timestamp) -> Self {
43+
timestamp.0
44+
}
45+
}
46+
47+
uniffi::custom_type!(Timestamp, SystemTime);

crypto-ffi/uniffi-android.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
[bindings.kotlin]
22
android = true
33
android_cleaner = true
4+
5+
[bindings.kotlin.custom_types.KotlinInstant]
6+
imports = [
7+
"kotlinx.datetime.Instant",
8+
"kotlinx.datetime.toKotlinInstant",
9+
"kotlinx.datetime.toJavaInstant",
10+
]
11+
type_name = "Instant"
12+
lift = "{}.toKotlinInstant()"
13+
lower = "{}.toJavaInstant()"

crypto-ffi/uniffi.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
package_name = "com.wire.crypto"
33
cdylib_name = "core_crypto_ffi"
44

5+
[bindings.kotlin.custom_types.Timestamp]
6+
imports = [
7+
"kotlinx.datetime.Instant",
8+
"kotlinx.datetime.toKotlinInstant",
9+
"kotlinx.datetime.toJavaInstant",
10+
]
11+
type_name = "Instant"
12+
lift = "{}.toKotlinInstant()"
13+
lower = "{}.toJavaInstant()"
14+
515
[bindings.swift]
616
cdylib_name = "core_crypto_ffi"
717
ffi_module_name = "LibCoreCrypto"

0 commit comments

Comments
 (0)