Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crypto-ffi/bindings/android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
implementation(kotlin("stdlib-jdk7"))
implementation("${libs.jna.get()}@aar")
implementation(libs.coroutines.core)
implementation(libs.kotlinx.datetime)
implementation("androidx.annotation:annotation:1.9.1")

androidTestImplementation(kotlin("test"))
Expand Down
2 changes: 2 additions & 0 deletions crypto-ffi/bindings/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[versions]
kotlin = "1.9.25"
coroutines = "1.7.3"
kotlinx-datetime = "0.6.1"
jna = "5.17.0"
assertj = "3.24.2"
espresso = "3.6.1"
Expand Down Expand Up @@ -29,3 +30,4 @@ espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "esp
android-junit = { module = "androidx.test.ext:junit", version.ref = "android-junit" }
android-tools = { module = "com.android.tools.build:gradle", version.ref = "android-tools" }
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin-gradle" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
1 change: 1 addition & 0 deletions crypto-ffi/bindings/jvm/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
implementation(kotlin("stdlib-jdk7"))
implementation(libs.jna)
implementation(libs.coroutines.core)
implementation(libs.kotlinx.datetime)
testImplementation(kotlin("test"))
testImplementation(libs.coroutines.test)
testImplementation(libs.assertj.core)
Expand Down
10 changes: 5 additions & 5 deletions crypto-ffi/src/identity/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use wasm_bindgen::prelude::*;

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

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

/// X509 certificate not before
#[cfg(not(target_family = "wasm"))]
pub not_before: SystemTime,
pub not_before: Timestamp,

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

/// X509 certificate not after
#[cfg(not(target_family = "wasm"))]
pub not_after: SystemTime,
pub not_after: Timestamp,
}

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

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

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

Self {
handle: i.handle,
Expand Down
4 changes: 4 additions & 0 deletions crypto-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ mod error;
mod identity;
mod metadata;
mod proteus;
#[cfg(not(target_family = "wasm"))]
mod timestamp;

pub use bundles::{
commit::CommitBundle, group_info::GroupInfoBundle, proteus_auto_prekey::ProteusAutoPrekeyBundle,
Expand Down Expand Up @@ -70,3 +72,5 @@ pub use identity::{
x509::X509Identity,
};
pub use metadata::{BuildMetadata, build_metadata, version};
#[cfg(not(target_family = "wasm"))]
pub use timestamp::Timestamp;
47 changes: 47 additions & 0 deletions crypto-ffi/src/timestamp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//! Custom timestamp type for UniFFI bindings.
//!
//! This wrapper allows custom type mapping per target language:
//! - Kotlin: maps to `kotlinx.datetime.Instant`
//! - Swift: maps to `Date`
//! - WASM: not changed
//!
//! This unifies timestamp handling across JVM/Android and KMP bindings.
//! This can be removed once we fully migrate to Kotlin Multiplatform and
//! stop generating JVM/Android bindings.

use std::time::{Duration, SystemTime};

/// A wrapper around `SystemTime` for FFI bindings with custom type mapping per language.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Timestamp(pub SystemTime);

impl Timestamp {
/// Creates a new `Timestamp` from a `SystemTime`.
pub fn new(time: SystemTime) -> Self {
Self(time)
}

/// Creates a new `Timestamp` from seconds since the Unix epoch.
pub fn from_epoch_secs(secs: u64) -> Self {
Self(SystemTime::UNIX_EPOCH + Duration::from_secs(secs))
}

/// Returns the inner `SystemTime`.
pub fn into_inner(self) -> SystemTime {
self.0
}
}

impl From<SystemTime> for Timestamp {
fn from(time: SystemTime) -> Self {
Self(time)
}
}

impl From<Timestamp> for SystemTime {
fn from(timestamp: Timestamp) -> Self {
timestamp.0
}
}

uniffi::custom_type!(Timestamp, SystemTime);
10 changes: 10 additions & 0 deletions crypto-ffi/uniffi-android.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
[bindings.kotlin]
android = true
android_cleaner = true

[bindings.kotlin.custom_types.KotlinInstant]
imports = [
"kotlinx.datetime.Instant",
"kotlinx.datetime.toKotlinInstant",
"kotlinx.datetime.toJavaInstant",
]
type_name = "Instant"
lift = "{}.toKotlinInstant()"
lower = "{}.toJavaInstant()"
10 changes: 10 additions & 0 deletions crypto-ffi/uniffi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
package_name = "com.wire.crypto"
cdylib_name = "core_crypto_ffi"

[bindings.kotlin.custom_types.Timestamp]
imports = [
"kotlinx.datetime.Instant",
"kotlinx.datetime.toKotlinInstant",
"kotlinx.datetime.toJavaInstant",
]
type_name = "Instant"
lift = "{}.toKotlinInstant()"
lower = "{}.toJavaInstant()"

[bindings.swift]
cdylib_name = "core_crypto_ffi"
ffi_module_name = "LibCoreCrypto"
Expand Down
Loading