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) + } + } + } +}