From 3b042e8a6b3edfe981075c78ad0f997c02b5bcb7 Mon Sep 17 00:00:00 2001 From: Sebastian Holmin Date: Wed, 17 Jan 2024 11:30:49 +0100 Subject: [PATCH] Manual `IntoJava` impl to skip `locked_down` field Here we manually implement the `IntoJava` trait of jnix to skip the `locked_down` field of `TunnelState::Disconnected` as the derive macro currently does not support skipping fields of struct variants in and enum. It was decided that this solution is the preferred to updating the macro since the jnix crate will be dropped once android implements gRPC. --- mullvad-types/src/states.rs | 117 ++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/mullvad-types/src/states.rs b/mullvad-types/src/states.rs index 67f95b23e114..ac121e1bc812 100644 --- a/mullvad-types/src/states.rs +++ b/mullvad-types/src/states.rs @@ -1,6 +1,4 @@ use crate::location::GeoIpLocation; -#[cfg(target_os = "android")] -use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::fmt; use talpid_types::{ @@ -31,8 +29,6 @@ impl fmt::Display for TargetState { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] #[serde(tag = "state", content = "details")] -#[cfg_attr(target_os = "android", derive(IntoJava))] -#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub enum TunnelState { Disconnected { location: Option, @@ -67,3 +63,116 @@ impl TunnelState { matches!(self, TunnelState::Disconnected { .. }) } } + +#[cfg(target_os = "android")] +// Here we manually implement the `IntoJava` trait of jnix to skip the `locked_down` field of +// `TunnelState::Disconnected`. The derive macro currently does not support skipping fields in +// struct variants of enums. It was decided that this solution is the preferred to updating the +// macro since the jnix crate will be dropped once android implements gRPC. +impl<'borrow, 'env> jnix::IntoJava<'borrow, 'env> for TunnelState +where + 'env: 'borrow, +{ + const JNI_SIGNATURE: &'static str = "Lnet/mullvad/mullvadvpn/model/TunnelState;"; + type JavaType = jnix::jni::objects::AutoLocal<'env, 'borrow>; + #[allow(non_snake_case)] + fn into_java(self, env: &'borrow jnix::JnixEnv<'env>) -> Self::JavaType { + match self { + Self::Disconnected { + location, + locked_down: _, + } => { + let constructor_signature = format!("({})V", location.jni_signature()); + + let location_java = location.into_java(env); + let parameters = [jnix::AsJValue::as_jvalue(&location_java)]; + + let class = env.get_class("net/mullvad/mullvadvpn/model/TunnelState$Disconnected"); + + let object = env + .new_object(&class, constructor_signature, ¶meters) + .expect( + "Failed to convert TunnelState::Disconnected Rust type into net.mullvad.mullvadvpn.model.TunnelState.Disconnected Java object", + ); + env.auto_local(object) + } + Self::Connecting { endpoint, location } => { + let constructor_signature = format!( + "({}{})V", + endpoint.jni_signature(), + location.jni_signature() + ); + + let endpoint_java = endpoint.into_java(env); + let location_java = location.into_java(env); + let parameters = [ + jnix::AsJValue::as_jvalue(&endpoint_java), + jnix::AsJValue::as_jvalue(&location_java), + ]; + + let class = env.get_class("net/mullvad/mullvadvpn/model/TunnelState$Connecting"); + + let object = env + .new_object(&class, constructor_signature, ¶meters) + .expect( + "Failed to convert TunnelState::Connecting Rust type into net.mullvad.mullvadvpn.model.TunnelState.Connecting Java object", + ); + env.auto_local(object) + } + Self::Connected { endpoint, location } => { + let constructor_signature = format!( + "({}{})V", + endpoint.jni_signature(), + location.jni_signature() + ); + + let endpoint_java = endpoint.into_java(env); + let location_java = location.into_java(env); + let parameters = [ + jnix::AsJValue::as_jvalue(&endpoint_java), + jnix::AsJValue::as_jvalue(&location_java), + ]; + + let class = env.get_class("net/mullvad/mullvadvpn/model/TunnelState$Connected"); + + let object = env + .new_object(&class, constructor_signature, ¶meters) + .expect( + "Failed to convert TunnelState::Connected Rust type into net.mullvad.mullvadvpn.model.TunnelState.Connected Java object", + ); + env.auto_local(object) + } + Self::Disconnecting(action_after_disconnect) => { + let constructor_signature = + format!("({})V", action_after_disconnect.jni_signature()); + + let action_after_disconnect_java = action_after_disconnect.into_java(env); + let parameters = [jnix::AsJValue::as_jvalue(&action_after_disconnect_java)]; + + let class = env.get_class("net/mullvad/mullvadvpn/model/TunnelState$Disconnecting"); + + let object = env + .new_object(&class, constructor_signature, ¶meters) + .expect( + "Failed to convert TunnelState::Disconnecting Rust type into net.mullvad.mullvadvpn.model.TunnelState.Disconnecting Java object", + ); + env.auto_local(object) + } + Self::Error(error_state) => { + let constructor_signature = format!("({})V", error_state.jni_signature()); + + let error_state_java = error_state.into_java(env); + let parameters = [jnix::AsJValue::as_jvalue(&error_state_java)]; + + let class = env.get_class("net/mullvad/mullvadvpn/model/TunnelState$Error"); + + let object = env + .new_object(&class, constructor_signature, ¶meters) + .expect( + "Failed to convert TunnelState::Error Rust type into net.mullvad.mullvadvpn.model.TunnelState.Error Java object", + ); + env.auto_local(object) + } + } + } +}