Rust — a systems programming language with compile-time memory safety guarantees. Developed by Mozilla Research in 2010 under the direction of Graydon Hoare. Rust prevents entire classes of vulnerabilities: null pointers, dangling references, and data races. In mobile development, Rust is used for native modules, cross-platform SDKs, and WebAssembly. According to Stack Overflow Survey (2025), Rust has been the most «loved language» for nine consecutive years.
Key Takeaways
Rust is a statically typed systems programming language with zero-cost abstractions. Rust guarantees memory safety without a garbage collector thanks to its ownership, borrowing, and lifetimes system. The Rust compiler is one of the strictest: it rejects code that would cause undefined behavior in C++.
Rust compiles via LLVM to native code for all architectures: ARM, x86, RISC-V, WebAssembly. The toolchain includes: rustup (installer), rustc (compiler), cargo (package manager and build tool). Cargo.toml — similar to package.json, contains dependencies from crates.io. The latest stable version is Rust 1.81 (2025).
Key application areas of Rust in mobile development: native libraries (Android NDK, iOS), cross-platform SDKs (Firefox, Dropbox), replacing C++ in performance-critical sections, WebAssembly for hybrid applications. Google uses Rust in AOSP (Android Open Source Project) for Bluetooth, Wi-Fi, and NFC components.
For cross-compilation to Android, you need target toolchains: rustup target add aarch64-linux-android armv7-linux-androideabi. For iOS — aarch64-apple-ios x86_64-apple-ios. cargo-ndk (for Android) and cargo-lipo (for iOS) simplify the build process.
# Installing Rust and target platforms for mobile development
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ rustup target add aarch64-linux-android
$ rustup target add armv7-linux-androideabi
$ rustup target add aarch64-apple-ios
$ rustup target add x86_64-apple-ios
# Installing cargo-ndk for Android builds
$ cargo install cargo-ndk
# Building for Android
$ cargo ndk -t arm64-v8a -o ./jniLibs build --releaseOwnership is the fundamental concept of Rust. Every value has exactly one owner. When assigned or passed to a function, ownership is moved. After a move, the previous owner cannot use the value. This eliminates double memory freeing and dangling pointers.
Borrowing allows temporary use of a reference to a value without transferring ownership. The &T reference (immutable) — any number of readers. The &mut T reference (mutable) — exactly one writer, no readers. The compiler checks these rules at compile time.
fn process_data(data: &mut Vec<i32>) {
for item in data.iter_mut() {
*item *= 2;
}
}
fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
process_data(&mut numbers);
println!("Processed: {:?}", numbers);
let first = &numbers[0]; // immutable borrowing
println!("First: {}", first);
}process_data takes a mutable reference to Vec and doubles each element. iter_mut() returns an iterator with mutable references. *item dereferences the reference for assignment. After process_data, numbers remains accessible — ownership was not moved, only borrowed.
Lifetimes ('a) — annotations that link the lifetimes of references. The compiler uses them to verify that a reference does not outlive the data it points to. In most cases, lifetimes are inferred automatically — you only need to specify them in function signatures with references.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
fn main() {
let string1 = String::from("rust");
let result;
{
let string2 = String::from("mobile");
result = longest(string1.as_str(), string2.as_str());
println!("Longest: {}", result);
} // string2 lives until this brace, result is valid inside
// println!("{}", result); // error: string2 is dead
}Rust compiles to native libraries for Android (.so via NDK) and iOS (.a static libraries). Google officially supports Rust in the Android Open Source Project (AOSP) — Rust is used for Bluetooth (ava), DNS-over-HTTP3, and CriticalNotification components. According to Google (2025), Rust in Android eliminated 70% of memory vulnerabilities in targeted components.
For Android, cargo-ndk is used, which wraps Cargo with the correct toolchain for the chosen ABI. Building for Android includes: aarch64-linux-android (64-bit ARM, modern devices), armv7-linux-androideabi (32-bit ARM), x86_64-linux-android (emulators).
// Cargo.toml — library configuration for Android/iOS
[package]
name = "mobile_crypto"
version = "0.1.0"
[lib]
crate-type = ["staticlib", "cdylib"]
[dependencies]
serde = { version = "1", features = ["derive"] }
libc = "0.2"crate-type: staticlib — for iOS (.a), cdylib — for Android (.so). serde — serialization for data exchange with Kotlin/Swift. libc — C-compatible types for FFI.
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
/// C-compatible function for image processing
#[no_mangle]
pub unsafe extern "C" fn process_image(
input: *const u8,
len: usize,
output: *mut u8,
out_len: *mut usize,
) {
let input_slice = std::slice::from_raw_parts(input, len);
let result: Vec<u8> = input_slice.iter()
.map(|b| b ^ 0xFF)
.collect();
let result_len = result.len();
std::ptr::copy_nonoverlapping(result.as_ptr(), output, result_len);
*out_len = result_len;
}#[no_mangle] disables name mangling for C-compatible ABI. extern "C" specifies the C calling convention. unsafe — a marker indicating that a call from outside Rust does not guarantee safety. std::ptr::copy_nonoverlapping copies result bytes to the output buffer.
Rust is the ideal candidate for cross-platform SDKs that work on Android and iOS from a single codebase. Companies like Mozilla (Firefox), Dropbox (file synchronization), and Meta (Libra blockchain) chose Rust for critical components of their mobile applications.
Advantages of Rust libraries over C++: the compiler guarantees the absence of memory leaks and data races in cross-platform code. Code written and tested in Rust once works identically on all platforms. Cargo manages dependencies natively, without CMake or vcpkg.
| Library/Crate | Purpose |
|---|---|
| tonic | gRPC client/server in Rust |
| reqwest | HTTP client with async/await |
| ring | Cryptography (AES, RSA, ECDSA) |
| sqlx | Async SQLite, PostgreSQL |
| wasm-bindgen | Rust-to-JavaScript/WASM integration |
| ndk-glue | Android NativeActivity in Rust |
| uniffi | FFI binding generation for Kotlin/Swift |
Rust compiles to WebAssembly (Wasm) — a binary format executable in the browser and on mobile devices. Wasm delivers near-native performance in web environments. In mobile development, Wasm is used in hybrid applications (WebView + Wasm) for complex computations: 3D rendering, image recognition, encryption.
wasm-pack compiles Rust to .wasm and generates a JS wrapper. wasm-bindgen connects Rust functions with JavaScript calls. On a mobile device, the Wasm runner can run in WebView or via the Wasmer/Wasmtime SDK.
use wasm_bindgen::prelude::*;
/// Computing Fibonacci numbers in Wasm (called from JS)
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
}
}#[wasm_bindgen] generates a JavaScript wrapper for the fibonacci function. In the browser, the call looks like wasm.fibonacci(10). Types u32/u64 are automatically converted to Number/BigInt. The Wasm module weighs only ~5 KB for such a function — minimal overhead.
FFI (Foreign Function Interface) — a mechanism for calling Rust code from other languages. Rust functions with extern "C" and #[no_mangle] are exported with a C-compatible ABI. From Kotlin, such functions are called via JNI, from Swift — via @_cdecl ("name") or CBridge.h.
UniFFI — a Mozilla tool for generating FFI bindings. You describe the API in a .udl file, and UniFFI generates Kotlin and Swift wrappers automatically. This is the standard approach for Rust components in Firefox Android and Firefox iOS.
// Rust library with UniFFI interface
uniffi::setup_scaffolding!();
#[derive(uniffi::Enum)]
pub enum EncryptionError {
InvalidKey,
EncryptionFailed,
}
#[derive(uniffi::Record)]
pub struct EncryptedData {
pub ciphertext: Vec<u8>,
pub nonce: Vec<u8>,
}
#[uniffi::export]
pub fn encrypt(key: &[u8], plaintext: &[u8]) -> Result<EncryptedData, EncryptionError> {
// AES-256-GCM implementation
todo!()
}UniFFI generates a Kotlin class with the encrypt method, which takes a ByteArray and returns EncryptedData. In Swift, an EncryptedData struct is created with fields ciphertext (Data) and nonce (Data). Errors are converted to Kotlin/Swift exceptions.
Rust and C++ are the two main languages for systems programming in mobile development. Both compile to native ARM code and support FFI via the C ABI. The key difference is the memory safety model: Rust checks it at compile time, C++ relies on developer discipline.
| Criterion | Rust | C++ |
|---|---|---|
| Memory safety | Guaranteed (ownership) | Developer responsibility |
| Garbage collector | No (RAII + ownership) | No (manual management) |
| Memory leaks | Prevented by compiler | Possible (new without delete) |
| Data races | Prevented (Send + Sync) | Possible |
| Android NDK | Via cargo-ndk | Via CMake / NDK Build |
| iOS support | cargo-lipo + .a | Xcode + .a |
| Build system | Cargo (built-in) | CMake / Ninja |
| Build time | 2–5 min (clean) | 5–15 min (clean) |
| Ecosystem | crates.io (200k+ crates) | vcpkg / Conan (100k+ libraries) |
Rust is safer than C++ and more productive — the compiler catches errors that would manifest at runtime in C++. C++ has a richer mobile library ecosystem. For new projects, Rust is preferable; existing C++ code is ported incrementally.
Frequently Asked Questions
The main difference is compile-time memory safety. Rust has no nullptr, dangling pointers, or data races thanks to its ownership system and borrow checker. C++ relies on developer discipline, Rust relies on compiler checks.
Yes, via Android NDK. Google officially supports Rust in AOSP (Android Open Source Project). Rust compiles to .so libraries via cargo-ndk. FFI (Foreign Function Interface) through JNI works the same way as for C++.
Cargo is Rust's package manager and build system. It downloads dependencies from crates.io, compiles the project, and runs tests. In mobile development, cargo-ndk extends Cargo for cross-compilation to Android ABIs.
Rust supports both platforms. For iOS, cargo-lipo is used to create universal binaries (arm64 + x86_64 simulator). Rust code compiles to a static .a library and links via Xcode.
Yes, Rust is becoming the standard for cross-platform SDKs and native modules. Google, Meta, and Mozilla are investing in Rust. For performance-critical components, Rust is safer and more productive than C++.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also