<img src="../../slides/kotlinconf/opening.png", width="850px" height="600px"> --- <!-- Why you, the reader should trust what I have to say--> <h1>Who am I?</h1> <div class="parent"> <div> <h2>Tarik Eshaq</h2> <h2>Engineer at Mozilla</h2> <h2>Writing Rust with Kotlin for 3 years</h2> <h2>Work on Firefox Sync</h2> </div> </div> `tarikeshaq` on Twitter, GitHub, etc <style> .parent { display: flex } </style> --- # Overview <ol> <li class="agenda-item">Why would you ever use Kotlin with Rust?</li> </ol> <style> .agenda-item { font-size: 40px; } </style> --- # Overview <ol> <li class="agenda-item">Why would you ever use Kotlin with Rust?</li> <li class="agenda-item">What it means to cross the barrier between Kotlin and Rust</li> </ol> --- # Overview <ol> <li class="agenda-item">Why would you ever use Kotlin with Rust?</li> <li class="agenda-item">What it means to cross the barrier between Kotlin and Rust</li> <li class="agenda-item">How you would cross that barrier</li> </ol> --- # Overview <ol> <li class="agenda-item"><span><b>Why</b></span> would you ever use Kotlin with Rust?</li> <li class="agenda-item"><span><b>What</b></span> it means to cross the barrier between Kotlin and Rust</li> <li class="agenda-item"><span><b>How</b></span> you would cross that barrier</li> </ol> --- class: center, middle # Why would you ever use Kotlin with Rust? --- class: center, middle # Why would you ever use Kotlin with Rust? <h2>Simple Answer: <span class="red">You Probably Shouldn't</span></h2> <style> .red { color: red; } </style> --- # Why ## You'd like to use an existing Rust Library --- # Why ## You'd like to use an existing Rust Library ## You'd like granular memory management --- # Why ## You'd like to use an existing Rust Library ## You'd like granular memory management ## The overhead of a runtime or GC is too expensive --- # Why ## You'd like to use an existing Rust Library ## You'd like granular memory management ## The overhead of a runtime or GC is too expensive ## You'd like to take advantage of Rust's first class cross-platform support --- class: center, middle # What it means to cross the barrier between Kotlin and Rust --- class: center, middle # ~~What it means to cross the barrier between Kotlin and Rust~~ # What it means to cross the barrier between any langauge and another? --- class: center, middle # A detour: The ABI --- class: center, middle # A detour: The ABI <h2>A contract that is enforced by machine code</h2> --- class: center, middle # A detour: The ABI <h2>A contract that is enforced by machine code</h2> <h3>Typically enforced by your compiler</h3> --- class: center, middle # A detour: The ABI <h2>A contract that is enforced by machine code</h2> <h3>Typically enforced by your compiler</h3> <h3>Controls how data is layed out in memory</h3> <h3>Controls Calling conventions</h3> --- # ABI .question1[ ```rs struct Question { content: String, id: u32, author_name: String } ``` ] <style> .question1 .remark-code { font-size: 30px; } </style> --- # ABI .parent-abi[ .slide-code[ ```rs struct Question { content: String, id: u32, author_name: String } ``` ] .question-img[ <div id="memory"> <p>24 Bytes for <code>String</code></p> <div class="divider"></div> <p>4 Bytes for <code>u32</code></p> <div class="divider"></div> <p>4 Bytes Padding</p> <div class="divider"></div> <p>24 Bytes for <code>String</code></p> </div> ] ] <style> #memory { text-align: center; border-style: solid; border-radius: 20px; } #memory .divider { border-bottom: 5px solid; } #memory p { margin-right: 10px; margin-left: 10px; } </style> --- # ABI ## Calling Conventions .parent-abi[ <div></div> .slide-code1[ ```rs fn add(a: i32, b: i32) -> i32 { a + b } ``` ] <div></div> ] <style> .slide-code1 .remark-code { font-size: 30px; } </style> --- # ABI ## Calling Conventions .parent-abi[ <div></div> .asm-code1[ ```asm add: mov eax, edi add eax, esi ret ``` ] <img src="../../slides/kotlinconf/cpu.drawio.png" width="300px"> ] <style> .parent-abi { display: flex; justify-content: space-between; } .slide-code2 .remark-code { font-size: 20px } .remark-code { border-style: solid; border-radius: 20px; } .asm-code1 .remark-code { font-size: 30px } </style> --- # ABI ## Calling Conventions .parent-abi[ <div></div> .slide-code1[ ```rs add(4, 3); ``` ] <div></div> ] --- # ABI ## Calling Conventions .parent-abi[ .asm-caller[ ```asm mov edi, 4 mov esi, 3 call add ``` ] .asm-code2[ ```asm add: mov eax, edi add eax, esi ret ``` ] <div></div> ] <style> .slide-code2 .remark-code { font-size: 20px; } .remark-code { border-style: solid; border-radius: 20px; } .asm-code2 .remark-code { font-size: 30px; } .asm-caller .remark-code { font-size: 30px; } </style> --- class: center, middle # ~~What it means to cross the barrier between Kotlin and Rust~~ # What it means to cross the barrier between any langauge and another? --- class: center, middle # ~~What it means to cross the barrier between Kotlin and Rust~~ # ~~What it means to cross the barrier between any langauge and another?~~ # What it means to create a shared ABI between languages? --- class: middle <img src="../../slides/kotlinconf/c_meme.jpg" width="100%"> --- class: center, middle <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> </div> --- class: center, middle <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="down-arrow"> ← </div> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> </div> --- class: center, middle <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="down-arrow"> ← </div> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> <div class="down-arrow"> ← </div> <div class="rust-c"> <h2>C-compatable Rust</h2> </div> </div> --- class: center, middle <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="down-arrow"> ← </div> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> <div class="down-arrow"> ← </div> <div class="rust-c"> <h2>C-compatable Rust</h2> </div> <div class="down-arrow"> ← </div> <div class="rust-bun"> <h2>Rust</h2> </div> </div> <style> .down-arrow { transform: rotate(270deg); -webkit-transform: rotate(270deg); font-size: 55px; } </style> --- class: center, middle <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-c"> <h2>C-compatable Rust</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-bun"> <h2>Rust</h2> </div> </div> <style> .arrows { display: flex; justify-content: center; } .up-arrow { transform: rotate(90deg); -webkit-transform: rotate(90deg); font-size: 55px; } </style> --- <div class="ffi-page"> <div></div> <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="ffi"> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-c"> <h2>C-compatable Rust</h2> </div> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-bun"> <h2>Rust</h2> </div> </div> <div></div> </div> <style> .ffi-page { display: flex; justify-content: space-between; align-items: center; } .ffi { border-style: solid; border-color: red; border-radius: 60%; padding-right: 60px; padding-left: 60px; } </style> --- <div class="ffi-page"> <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="ffi"> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-c"> <h2>C-compatable Rust</h2> </div> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-bun"> <h2>Rust</h2> </div> </div> <div class="right-arrow"> ← </div> <div class="ffi-name"> <p class="ffi-name"><b>The Foreign Function Interface (FFI)</b></p> </div> </div> <style> .right-arrow { transform: rotate(180deg); -webkit-transform: rotate(180deg); font-size: 90px; } .ffi-name p { font-size: 30px; width: 250px; } </style> --- <div class="sandwich-page"> <h1>The FFI Sandwich</h1> <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-c"> <h2>C-compatable Rust</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-bun"> <h2>Rust</h2> </div> </div> </div> <style> .sandwich-page { display: flex; justify-content: space-between; align-items: center; } .sandwich { text-align: center; } </style> --- class: center, middle # What it means to cross the barrier between Kotlin and Rust --- class: center, middle # What it means to cross the barrier between Kotlin and Rust <h2 class="it-means">It means traversing the FFI sandwich!</h2> <style> .it-means { color: red; } </style> --- class: center, middle # How to cross the barrier between Kotlin and Rust --- class: center, middle # Introducing UniFFI --- # UniFFI ## A multi-language bindings generator for Rust --- # UniFFI ## A multi-language bindings generator for Rust ## First class support for JVM Kotlin --- # UniFFI ## A multi-language bindings generator for Rust ## First class support for JVM Kotlin ## Community support for Kotlin Multiplatform --- <div class="sandwich-page-uniffi"> <h3>UniFFI generates the inside of the FFI Sandwich, so you only worry about the buns</h3> <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="kotin-c"> <h2>C-compatable Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-c"> <h2>C-compatable Rust</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-bun"> <h2>Rust</h2> </div> </div> </div> <style> .sandwich-page-uniffi { display: flex; justify-content: space-between; align-items: center; } .sandwich-page-uniffi h3 { width: 40%; font-size: 60px; } </style> --- <div class="sandwich-page-uniffi"> <h3>UniFFI generates the inside of the FFI Sandwich, so you only worry about the buns</h3> <div class="sandwich"> <div class="kotlin-bun"> <h2>Kotlin</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div> <h2>UniFFI Generated Code</h2> </div> <div class="arrows"> <div class="down-arrow"> ← </div> <div class="up-arrow"> ← </div> </div> <div class="rust-bun"> <h2>Rust</h2> </div> </div> </div> --- class: center, middle # A Conference Q&A app --- # Calling into Rust ```rs /// The type used to add, view and /// delete questions pub struct QAManager { ... } /// Represents a question to be asked pub struct Question { pub content: String, pub id: u32, pub author_name: String } ``` --- .qaManager1[ ```rs impl QAManager { pub fn new() -> Self { ... } pub fn add_question( &self, question: Question ) { ... } } ``` ] <style> .qaManager1 .remark-code { white-space: pre-wrap; } </style> --- ```rs #[derive(uniffi::Object)] // UniFFI will make QAManager an Object // that can be called with methods! pub struct QAManager { ... } ``` --- .qaManager1[ ```rs #[uniffi::export] // <- UniFFI will generate bindings for this block! impl QAManager { #[uniffi::constructor] // <- UniFFI will make this a constructor pub fn new() -> Self { ... } pub fn add_question( &self, question: Question ) { ... } } ``` ] --- .qaManager1[ ```rs #[derive(uniffi::Record)] // <- UniFFI will generate a FFI representation for this type! pub struct Question { pub content: String, pub id: u32, pub author_name: String } ``` ] --- .qaManager1[ ```kotlin // constructs a new QAManager by calling the Rust constructor val qaManager = QAManager() // Creates a new Question data class, does not call into Rust yet val question = Question( content: "How do I use UniFFI?", id: 0, authorName: "Tarik Eshaq" ) // Adds the question! qaManager.addQuestion(question) ``` ] --- # Calling Back into Kotlin .qaManager2[ ```rs #[uniffi::export(with_foreign)] trait HttpClient { fn get(&self) -> Vec<Question>; } ``` ] --- # Calling Back into Kotlin ```rs #[uniffi::export] fn get_questions( &self, http_client: Arc<dyn HttpClient> ) -> Vec<Question> { let remote_questions = http_client .get(); self .get_local_questions() .append(remote_questions) } ``` --- # Calling Back into Kotlin ```kotlin class KotlinHttpClient : HttpClient { override function get() : List<Question> { ... } } ... val questions = qaManager .get_questions(KotlinHttpClient()) ``` --- # Error Handling ```rs #[derive(uniffi::Error)] pub enum QAError { ... } pub fn add_question( &self, question: Question ) -> Result<(), QAError> { ... } ``` --- # Calling Async Rust ```rs #[uniffi::export] // UniFFI also works with Async Rust! pub async fn sync(&self) { ... } ``` --- # Calling Async Rust ```kotlin coroutineScope.launch { // `sync` is a suspend function! qaManager.sync() } ``` --- # Calling Async Kotlin ```rs #[uniffi::export(with_foriegn)] pub trait HttpClient { async fn get(&self) -> Vec<Question>; async fn post(&self, Vec<Question>); } ``` --- # Calling Async Kotlin ```kotlin class KotlinHttpClient : HttpClient { override suspend function get() : List<Question> { ... } override suspend function post( questions: List<question> ) { ... } } ``` --- ```rs #[uniffi::export] async fn sync( &self, http_client: Arc<dyn HttpClient> ) { let remote_questions = http_client .get() .await; let merged = self.merge_remote( &remote_questions ); http_client.post(merged).await; } ``` --- class: center, middle # Demo <ul id="questions-list"> </ul> <input id="question-input"/> <button class="s-question" id="submit-question">Submit</button> <button class="s-question" id="sync-questions">Sync</button> <style> #question-input { border-radius: 50px; padding-left: 20px; font-size: 40px; } .s-question { font-size: 20px; border-radius: 30px; padding: 20px; background: transparent; } .s-question:hover { background: black; color: white; cursor: pointer; } </style> --- <img src="../../slides/kotlinconf/closing.png", width="800px" height="600px"> --- # You can find the slides at ## https://tarikeshaq.com/slides/kotlin-conf2024 <img src="../../slides/kotlinconf/slides-qr.png", width="300px" height="300px"> ## Demo code in <https://github.com/tarikeshaq/kotlinconf2024> --- # Links - [UniFFI Docs](https://mozilla.github.io/uniffi-rs/) - [UniFFI Kotlin Multiplatform Support](https://gitlab.com/trixnity/uniffi-kotlin-multiplatform-bindings) - [Whitehouse report on securing software](https://www.whitehouse.gov/wp-content/uploads/2024/02/Final-ONCD-Technical-Report.pdf) - [The Rust Programming Language](https://doc.rust-lang.org/book/) - [Rust in Android](https://security.googleblog.com/2022/12/memory-safe-languages-in-android-13.html) - [Rust is the most admiried language](https://survey.stackoverflow.co/2023/#section-admired-and-desired-programming-scripting-and-markup-languages) --- class: center, middle <!-- Why you, the reader should pay attention --> # Rust is the most admired Programming Language <p align="center"> <img src="../../slides/kotlinconf/survey.png" width="100%"> </p> \*from [stackoverflow's 2023 Developer survey](https://survey.stackoverflow.co/2023/#section-admired-and-desired-programming-scripting-and-markup-languages) --- class: center, middle # Why is Rust so Loved? --- # Why is Rust so Loved? ## Memory Safety --- # Why is Rust so Loved? ## Memory Safety ## No Garbage collection --- # Why is Rust so Loved? ## Memory Safety ## No Garbage collection ## "Fearless concurrency" --- # Why is Rust so Loved? ## Memory Safety ## No Garbage collection ## "Fearless concurrency" ## A built-in package manager --- # Why is Rust so Loved? ## Memory Safety ## No Garbage collection ## "Fearless concurrency" ## A built-in package manager ## **Great inter-operability for cross-platform code** --- class: center, middle # Places where Rust is Used <div class="rust-projects"> <h2>Firefox</h2> <h2>Android</h2> <h2>AWS</h2> <h2>Windows</h2> <h2>Chrome</h2> </div> <style> .rust-projects { display: flex; justify-content: space-between; } </style> --- class: center, middle # Places where Rust is Used <div class="rust-projects"> <h2>Firefox</h2> <h2>Android</h2> <h2>AWS</h2> <h2>Windows</h2> <h2>Chrome</h2> </div> <h1>Your Kotlin Project? 👀</h1> <style> .rust-projects { display: flex; justify-content: space-between; } </style> --- <div id="whitehouse"> <img src="../../slides/kotlinconf/whitehouse.png" width="400px" height="500px"> <blockquote id="whitehouse-quote"><q>...in most cases, using a <b>memory safe programming language</b> is the most efficient way to substantially improve software security</q></blockquote> </div> <style> #whitehouse { display: flex; align-items: center; justify-content: space-between; } #whitehouse-quote { font-size: 30px; } </style>