From cc56928e9874b2894e7aabdf8b09efcf47820efa Mon Sep 17 00:00:00 2001 From: Darius Maitia Date: Thu, 12 Sep 2024 13:22:39 -0300 Subject: [PATCH] issue(key expr): adding concat function --- zenoh-jni/src/key_expr.rs | 43 ++++++++++++++++++- .../kotlin/io/zenoh/jni/JNIKeyExpr.kt | 7 +++ .../kotlin/io/zenoh/keyexpr/KeyExpr.kt | 6 +-- .../commonTest/kotlin/io/zenoh/KeyExprTest.kt | 9 ++++ 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/zenoh-jni/src/key_expr.rs b/zenoh-jni/src/key_expr.rs index b6d831c89..a329e618b 100644 --- a/zenoh-jni/src/key_expr.rs +++ b/zenoh-jni/src/key_expr.rs @@ -206,9 +206,48 @@ pub unsafe extern "C" fn Java_io_zenoh_jni_JNIKeyExpr_00024Companion_joinViaJNI( ) -> jstring { || -> Result { let key_expr_1 = process_kotlin_key_expr(&mut env, &key_expr_str_1, key_expr_ptr_1)?; - let key_expr_str = decode_string(&mut env, &key_expr_2)?; + let key_expr_2_str = decode_string(&mut env, &key_expr_2)?; let result = key_expr_1 - .join(key_expr_str.as_str()) + .join(key_expr_2_str.as_str()) + .map_err(|err| session_error!(err))?; + env.new_string(result.to_string()) + .map(|kexp| kexp.as_raw()) + .map_err(|err| jni_error!(err)) + }() + .unwrap_or_else(|err| { + throw_exception!(env, err); + JString::default().as_raw() + }) +} + +/// Concats key_expr_1 with key_expr_2, where key_expr_2 is a string. Returns the string representation +/// of the result, or throws an exception in case of failure. +/// +/// # Params: +/// - `key_expr_ptr_1`: Pointer to the key expression 1, differs from null only if it's a declared key expr. +/// - `key_expr_ptr_1`: String representation of the key expression 1. +/// - `key_expr_2`: String representation of the key expression 2. +/// +/// # Safety +/// - This function is marked as unsafe due to raw pointer manipulation, which happens only when providing +/// key expressions that were declared from a session (in that case the key expression has a pointer associated). +/// In that case, this function assumes the pointers are valid pointers to key expressions and those pointers +/// remain valid after the call to this function. +/// +#[no_mangle] +#[allow(non_snake_case)] +pub unsafe extern "C" fn Java_io_zenoh_jni_JNIKeyExpr_00024Companion_concatViaJNI( + mut env: JNIEnv, + _class: JClass, + key_expr_ptr_1: /*nullable*/ *const KeyExpr<'static>, + key_expr_str_1: JString, + key_expr_2: JString, +) -> jstring { + || -> Result { + let key_expr_1 = process_kotlin_key_expr(&mut env, &key_expr_str_1, key_expr_ptr_1)?; + let key_expr_2_str = decode_string(&mut env, &key_expr_2)?; + let result = key_expr_1 + .concat(key_expr_2_str.as_str()) .map_err(|err| session_error!(err))?; env.new_string(result.to_string()) .map(|kexp| kexp.as_raw()) diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIKeyExpr.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIKeyExpr.kt index 917465607..ea0f54760 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIKeyExpr.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIKeyExpr.kt @@ -61,6 +61,10 @@ internal class JNIKeyExpr(internal val ptr: Long) { KeyExpr(joinViaJNI(keyExpr.jniKeyExpr?.ptr ?: 0, keyExpr.keyExpr, other)) } + fun concatViaJNI(keyExpr: KeyExpr, other: String): Result = runCatching { + KeyExpr(concatViaJNI(keyExpr.jniKeyExpr?.ptr ?: 0, keyExpr.keyExpr, other)) + } + @Throws(Exception::class) private external fun tryFromViaJNI(keyExpr: String): String @@ -78,6 +82,9 @@ internal class JNIKeyExpr(internal val ptr: Long) { @Throws(Exception::class) private external fun joinViaJNI(ptrA: Long, keyExprA: String, other: String): String + + @Throws(Exception::class) + private external fun concatViaJNI(ptrA: Long, keyExprA: String, other: String): String } fun close() { diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/KeyExpr.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/KeyExpr.kt index 606722dd4..97ac77880 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/KeyExpr.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/keyexpr/KeyExpr.kt @@ -129,10 +129,10 @@ class KeyExpr internal constructor(internal val keyExpr: String, internal var jn /** * Performs string concatenation and returns the result as a KeyExpr if possible. - * You should probably prefer [join] as Zenoh may then take advantage of the hierachical separation it inserts. + * You should probably prefer [join] as Zenoh may then take advantage of the hierarchical separation it inserts. */ - fun concat(other: String): KeyExpr { - TODO() + fun concat(other: String): Result { + return JNIKeyExpr.concatViaJNI(this, other) } override fun toString(): String { diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/KeyExprTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/KeyExprTest.kt index 2d4523e98..6753adc76 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/KeyExprTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/KeyExprTest.kt @@ -169,4 +169,13 @@ class KeyExprTest { val keyExprJoined = keyExprA.join("C/D").getOrThrow() assertEquals(keyExprExpected, keyExprJoined) } + + @Test + fun `concat test`() { + val keyExprA = KeyExpr.tryFrom("A/B").getOrThrow() + val keyExprExpected = KeyExpr.tryFrom("A/B/C/D").getOrThrow() + + val keyExprConcat = keyExprA.concat("/C/D").getOrThrow() + assertEquals(keyExprExpected, keyExprConcat) + } }