[00:00.000 --> 00:21.360] All right, folks, here we go. [00:21.360 --> 00:27.200] Now on stage we have Matthias Geisler, this guy, and he just mentioned that if you're [00:27.200 --> 00:32.360] interested in the slides, we will find a way to share them with you, and I hope to get [00:32.360 --> 00:34.640] the other slides as well. [00:34.640 --> 00:42.040] Check out our channels for the IntelliJ giveaway on Slack, and on Twitter, and on Macedon. [00:42.040 --> 00:44.440] That's your mic now. [00:44.440 --> 00:49.920] Hello, it's the first time I speak with a microphone, to be honest, so it's super new [00:49.920 --> 00:50.920] to me. [00:50.920 --> 00:53.520] However, though, let's speak about Kotlin and Rust. [00:53.520 --> 00:55.720] Isn't that a great topic for the day? [00:55.720 --> 01:01.000] And how we can write one buck and ship it to as many platforms as we can. [01:01.000 --> 01:04.520] I think that is a very good idea, we should do that. [01:04.520 --> 01:11.520] However, though, before we start, just for your sanity, as I said, or as Holger just [01:11.520 --> 01:17.120] said, we will provide you the slides, and I also have an example repository I shared [01:17.120 --> 01:25.080] that somehow with you as well, so you don't need to be worried that there's all in it. [01:25.080 --> 01:32.680] So what I will speak today about is why should we ever try to put Rust into Kotlin multiplatform? [01:32.680 --> 01:35.640] By the way, are there any Rust developers here? [01:35.640 --> 01:36.640] One. [01:36.640 --> 01:40.920] Great, Unicorn. [01:40.920 --> 01:45.040] So why we even want to have Rust in our KMP? [01:45.040 --> 01:47.560] How does that look like? [01:47.560 --> 01:49.480] What are the cons and the pitfalls? [01:49.480 --> 01:52.240] And I can tell you there are many of them. [01:52.240 --> 01:58.000] And what are the to-dos if you want to progress further with the topic? [01:58.000 --> 02:01.440] And by the way, this wonderful slide deck is provided by my employer. [02:01.440 --> 02:05.160] I have to make a short advertisement because they pay the right. [02:05.160 --> 02:06.440] I've done that now. [02:06.440 --> 02:08.440] Great, why Rust? [02:08.440 --> 02:09.440] Kotlin is great. [02:09.440 --> 02:10.440] And multiplatform is great. [02:10.440 --> 02:17.600] I hope we all agree on that because we all want only one language to ship our code to [02:17.600 --> 02:18.920] all the platforms. [02:18.920 --> 02:22.440] And maybe a second language is okay, but three is already too much. [02:22.440 --> 02:25.400] Ideally, we just want to have one. [02:25.400 --> 02:27.280] So as I said, Kotlin is great. [02:27.280 --> 02:31.760] And I really love Kotlin, and I do it for a couple of years now, especially multiplatform. [02:31.760 --> 02:37.880] I developed a couple of SDKs, and I also have my own mocking library, so check it out. [02:37.880 --> 02:42.280] However, though, what's to say about Kotlin there is missing some functionality, which [02:42.280 --> 02:48.400] is not super easy to implement, but fortunately, Rust has that obviously already. [02:48.400 --> 02:50.320] For example, crypto libraries. [02:50.320 --> 02:51.320] That's a big thing. [02:51.320 --> 02:56.200] Or currently, there is this ICU package in development, which is dealing with daytime [02:56.200 --> 03:01.200] formatting and other good stuff, which you might already stumble upon in Android. [03:01.200 --> 03:07.240] But to have a multiplatform version of that is very, very unlikely because the crate itself [03:07.240 --> 03:14.200] is developed by the language people themselves, and I didn't see any activity in this regard, [03:14.200 --> 03:16.320] for example, for multiplatform. [03:16.320 --> 03:24.080] Anyhow, also, there is might be some behavior on multiplatform libraries you wouldn't expect, [03:24.080 --> 03:27.560] especially not at core libraries like daytime. [03:27.560 --> 03:32.120] If you compare the output of time zones, for example, you will be surprised. [03:32.120 --> 03:33.440] Let me call it like that. [03:33.440 --> 03:38.520] But if you write some tests and you are thinking there should be the same, I can tell you they [03:38.520 --> 03:39.520] are not. [03:39.520 --> 03:45.640] So also here, if you run over the case, maybe such functionality is already covered in Rust, [03:45.640 --> 03:49.000] so you don't have to reimplement the wheel, which is also great. [03:49.000 --> 03:54.280] And Kotlin native itself, if you ever had to write it, it can be really a menace. [03:54.280 --> 03:57.080] It just doesn't look great. [03:57.080 --> 04:03.680] And it's super hard to read sometimes, and it's also for that reason super hard to maintain. [04:03.680 --> 04:08.640] If you have a native language where you can write it on the bottom level, like Rust, it's [04:08.640 --> 04:14.480] much better because the code in itself is much more readable, yeah. [04:14.480 --> 04:18.400] And of course, you get out of us a much better performance, which you need, for example, if [04:18.400 --> 04:20.600] you do machine learning. [04:20.600 --> 04:23.300] That's also a good argument. [04:23.300 --> 04:25.600] So what are the soft arguments? [04:25.600 --> 04:30.680] For example, if you speak with some businesses nowadays, startups and so on, you will discover [04:30.680 --> 04:35.320] that people are more likely to adopt Rust and Kotlin, which was super surprising for [04:35.320 --> 04:36.920] me as well. [04:36.920 --> 04:42.200] But I speak with or spoken over the last couple of months with a lot of people. [04:42.200 --> 04:48.360] And I have no good answer why this is the case, even with KMP around, which is in most [04:48.360 --> 04:50.720] cases, I think, sufficient. [04:50.720 --> 04:57.200] So also, another business requirement is that the business itself might want to have the [04:57.200 --> 05:02.240] smallest team size possible, alone for budget reasons. [05:02.240 --> 05:07.160] And if you can do it maybe with two people instead of four people, they will go for the [05:07.160 --> 05:11.920] solution with two people, which is maybe backed up by Rust. [05:11.920 --> 05:18.720] And one very big argument for Rust is wasm support, which is Kotlin completely lacking [05:18.720 --> 05:25.640] right now, which is in the development, I know, but it's far from the state what Rust [05:25.640 --> 05:28.040] already has. [05:28.040 --> 05:35.480] And we have also to think about ourselves as developers. [05:35.480 --> 05:40.400] If you might be not aware, last year was a very great year not only for Kotlin due to [05:40.400 --> 05:43.880] the new memory management model, it was also for Rust. [05:43.880 --> 05:50.120] Rust did a lot of stuff, and there was happening in a lot of stuff, and one password launched [05:50.120 --> 05:55.960] their libraries, which are written in Rust, and only a very thin front-end layer is then [05:55.960 --> 05:57.680] done on the platforms. [05:57.680 --> 06:00.320] And they also have open source library for that. [06:00.320 --> 06:05.080] I will provide you with the link later when the slide deck goes around. [06:05.080 --> 06:06.160] So check it out. [06:06.160 --> 06:13.440] And the interesting thing is here, they took the Rust layer until the view model. [06:13.440 --> 06:15.320] So right until the top. [06:15.320 --> 06:20.600] And that's quite impressive with this kind of complexity. [06:20.600 --> 06:25.400] And what is maybe important for us, or at least for me, I really love the idea of multi-platform [06:25.400 --> 06:30.520] as I already stated, and to drive it further as much as possible, I think that's a good [06:30.520 --> 06:31.520] goal. [06:31.520 --> 06:36.320] And of course, because we can do it, maybe we should try it out. [06:36.320 --> 06:38.720] So how does that look like? [06:38.720 --> 06:43.680] Not to scare you, I have just a small portion of code examples. [06:43.680 --> 06:47.200] What you do on Android and JVM is basically GNI bindings. [06:47.200 --> 06:48.680] You might have seen that. [06:48.680 --> 06:53.040] You might already know that, and I bore you with that already. [06:53.040 --> 06:56.520] But that is what you have to dealing with that. [06:56.520 --> 07:01.600] But the good news is here, there is already a very good tooling there for Rust. [07:01.600 --> 07:06.360] So for example, what you see there, can you see my mouse here? [07:06.360 --> 07:07.360] Yes. [07:07.360 --> 07:15.120] It's coming from a crate in Rust from the GNI crate surprise, which provides you all [07:15.120 --> 07:24.800] the wrapping and transferring from JVM into Rust and back, which is super nice to use [07:24.800 --> 07:26.800] and easy to use even. [07:26.800 --> 07:30.040] So just to be aware of that. [07:30.040 --> 07:32.620] So how does that look on the content side? [07:32.620 --> 07:33.620] Something like that. [07:33.620 --> 07:36.080] So you have a couple of definitions. [07:36.080 --> 07:41.440] In this line, you just load the library, and if you've done it all correctly and somehow [07:41.440 --> 07:45.560] ship also the library and your resources with, that's it. [07:45.560 --> 07:52.840] Then you can use it like a normal library in Kotlin itself, which is great, I think. [07:52.840 --> 07:55.560] So here are some helpers for you. [07:55.560 --> 07:59.920] As I already mentioned, there's this GNI crate. [07:59.920 --> 08:05.040] There's also a NDK crate for Android, which is also super nice to use. [08:05.040 --> 08:06.440] So check it out. [08:06.440 --> 08:13.800] Floppy Gain is a generator for bindings in Rust for Kotlin and Java. [08:13.800 --> 08:19.840] So I don't like it, to be honest, because it takes out of much of flexibility, which [08:19.840 --> 08:21.760] you might need in some cases. [08:21.760 --> 08:27.120] Handwritten stuff might be more work-intensive, but less error-prone. [08:27.120 --> 08:29.280] But it's only my opinion. [08:29.280 --> 08:35.000] So this native loader is just that you can easily ship the library, and this plugin you [08:35.000 --> 08:41.720] will need simply to compile the entire Rust into your Android plugin. [08:41.720 --> 08:45.320] So how does that look on JavaScript? [08:45.320 --> 08:51.120] That's an easy one, because we don't ship it as something we bind directly, we bind [08:51.120 --> 08:52.840] it indirectly over Rust. [08:52.840 --> 08:59.560] Because as I already mentioned, Rust has a super cool Rust support and has all the crates [08:59.560 --> 09:00.960] to back them up. [09:00.960 --> 09:07.280] So that's on the Rust side, like the other function, and that's on the Kotlin side. [09:07.280 --> 09:12.040] That's a little bit more work-intensive, because you have to load them asynchronously, which [09:12.040 --> 09:13.760] you see here. [09:13.760 --> 09:19.680] And that brings a trade-off with it, because the entire library or the entire binding has [09:19.680 --> 09:22.040] to be asynchronous. [09:22.880 --> 09:26.560] You work then with promises and so on, and that can be super annoying, especially if [09:26.560 --> 09:29.560] you then go with React and so on. [09:29.560 --> 09:34.440] But it works, and it works sufficiently well and surprisingly well. [09:34.440 --> 09:40.320] And by the way, this is also a reason why many, many web developers these days also [09:40.320 --> 09:43.440] going for Rust. [09:43.440 --> 09:46.920] And you have also, as I mentioned, proper tooling for that. [09:46.920 --> 09:50.360] You have Wasmpec, which does all the hard work for you. [09:50.360 --> 09:55.400] NPM is just a bundler, you already know that, perhaps. [09:55.400 --> 10:00.160] And you need to have an understanding of promises, that's it. [10:00.160 --> 10:06.440] So now we come to native, and that's the hardest nut to crack, to be honest. [10:06.440 --> 10:12.680] What you have to do, basically, is writing a C-binding and a C-bridge, which just means [10:12.680 --> 10:20.920] you allocate your stuff on the native side, ship it to the other side in Kotlin, and somehow [10:20.920 --> 10:23.840] get your allocated stuff de-allocated. [10:23.840 --> 10:30.440] This is the most potential for memory leaks, but it works, somehow surprisingly sometimes. [10:30.440 --> 10:37.520] And also, you will encounter there are many problems, especially with the linker, when [10:37.520 --> 10:42.160] it comes to iOS, but it works still, not good. [10:42.160 --> 10:46.360] So that's the Kotlin site. [10:46.360 --> 10:52.480] So as I said, here you see the de-allocation, and this is just the bridging. [10:52.480 --> 10:57.880] So you copy the entire string, put it in, get the result back, copy it back, and then [10:57.880 --> 10:59.320] you de-allocate. [10:59.320 --> 11:04.680] So it's not that much, you could possibly even automate it, but it's not nice yet. [11:04.680 --> 11:07.880] Maybe there will be something better in the future, who knows. [11:07.880 --> 11:14.120] And also, one key ingredient you have to do is writing a definition file. [11:14.120 --> 11:21.040] You might have seen that if you ever had to deal with native Kotlin, and that's also something [11:21.040 --> 11:27.720] which can take a lot of time out of you, because it's also very error-prone in my experience. [11:27.720 --> 11:30.640] Maybe somebody else has better skills than me. [11:30.640 --> 11:33.760] I would gladly hear about it. [11:33.760 --> 11:41.840] So to do Rust with Kotlin native, you first of all need some greater skills, just to [11:41.840 --> 11:43.680] make it all work together. [11:43.680 --> 11:47.200] You need a lot of patience and a lot of time and good nerves. [11:47.200 --> 11:52.160] Because sometimes it's really like that, the one day it works, then you have an update [11:52.160 --> 11:58.440] on, let's say, Xcode, and then it doesn't work anymore, and that hits me today. [11:58.440 --> 12:02.840] Because I wrote a backup overnight, and I thought maybe it's a good idea, but it wasn't. [12:02.840 --> 12:08.560] So currently my native part isn't compiling anymore, because the linker says simply no. [12:08.560 --> 12:13.040] So what are the cons and the pitfalls? [12:13.040 --> 12:15.320] First of all, debugging is tricky. [12:15.320 --> 12:21.440] You don't want to debug this at all, because you have the Kotlin stack and you have the [12:21.440 --> 12:22.600] Rust stack. [12:22.600 --> 12:30.640] So my advice is here, write test, do TDD, that will take all the heat out of it. [12:30.640 --> 12:33.240] So far I tried it, to be honest. [12:33.240 --> 12:38.680] And this especially goes if you do a core concurrency, so if you do something with threads [12:38.680 --> 12:44.680] on the Kotlin side, if you do something with threads on the Rust side, it gets even harder. [12:44.680 --> 12:48.160] So test your code and go even for TDD. [12:48.160 --> 12:51.480] It will save you a lot of time and nerves. [12:51.480 --> 12:59.080] So Rust is bad with reactive programming, or let's say it doesn't has this pattern yet. [12:59.080 --> 13:02.320] Maybe there is something coming up in the future. [13:02.320 --> 13:08.920] I would love to see that in Tokyo, but that's something what I was talking about with somebody [13:08.920 --> 13:15.600] from one password about, because that means if you go up to the view model on the top, [13:15.600 --> 13:21.840] it's a little bit different to deal with this kind of stuff, because then you have to write [13:21.840 --> 13:26.400] the view model in a way that takes over the whole reactive stuff, and so on. [13:26.400 --> 13:33.240] And that's also not that nice, and can a little bit pollute your entire architecture. [13:33.240 --> 13:40.200] So about the sea bridge, I already spoke a little bit, so that's not fun. [13:40.200 --> 13:46.640] I spoke about this point in JavaScript and complex data, that's also a thing. [13:46.640 --> 13:54.080] Do yourself a favor, just don't try to bind single fields or properties into Rust. [13:54.400 --> 13:59.200] Take your data structure and just make a data class or something, serialize it, and then [13:59.200 --> 14:00.440] send it to Rust as a string. [14:00.440 --> 14:01.440] It's much easier. [14:01.440 --> 14:04.280] You save a lot of time and also a lot of nerves. [14:04.280 --> 14:09.200] And also here hint, I tried a little bit, and also spoke with other people. [14:09.200 --> 14:14.240] It's the best approach, and the fastest approach is at the current state, JSON. [14:14.240 --> 14:19.040] So the Rust JSON parser is really, really fast. [14:19.040 --> 14:30.680] And you can even make JSON schema sharing this scheme on both platforms, so you still [14:30.680 --> 14:33.840] have one definition, and it works on both sides. [14:33.840 --> 14:36.800] That's actually nice. [14:36.800 --> 14:43.440] So the first one, don't expect help or grievance or anything from anybody, because that's just [14:43.440 --> 14:44.600] a plain field. [14:44.600 --> 14:50.400] So I know there are some crazy people out there who are doing that, like me, and don't [14:50.400 --> 14:56.000] know why, maybe they have no friends like me also, but don't expect any help. [14:56.000 --> 15:01.000] And for your own sanity, try to find at least or speak with Rust people, they understand [15:01.000 --> 15:02.000] the pain. [15:02.000 --> 15:08.240] Cotton people, not anymore since the new memory model is here, and you don't have freezing [15:08.240 --> 15:10.160] errors or something. [15:10.160 --> 15:14.680] And the learning curve is quite high, because you basically learn a new language, and if [15:14.680 --> 15:20.640] you ever try it a little bit out of Rust, you will know there is a very big valley of [15:20.640 --> 15:29.000] pain, and yeah, the last one is simply, if you know a Kotlin native a little bit, you [15:29.000 --> 15:35.960] know that you can't just share, if you ship different models via Xcode, frameworks, or [15:35.960 --> 15:37.960] Swift package management. [15:37.960 --> 15:43.560] If you have one library, you can't just share them in between, you have to build up a monolith, [15:43.560 --> 15:49.640] and this also applies for that, because it's also static linked, so it's not nice. [15:49.640 --> 15:51.160] And what are the to-dos? [15:51.160 --> 15:55.440] I'm currently working on a plugin just to make it super more convenient, so nobody has [15:55.440 --> 15:57.440] to go to the pain I have. [15:57.440 --> 16:02.800] I try to make examples, but if you go with that as well, if you are interested, reach [16:02.800 --> 16:08.320] to me out, go to your local Rust community, right on Rust stack, there will be people [16:08.320 --> 16:14.760] which are appreciating that, and you can educate others, of course, and also the bridging layer [16:14.760 --> 16:20.240] maybe could be done in KSP, who knows, and not only in Rust, that would be nice. [16:20.240 --> 16:27.600] So just before we come to the questions, two nice projects are looking for maintainers, [16:27.600 --> 16:29.560] please take a photo. [16:29.560 --> 16:34.080] In Scandico codes, one of the maintainers is actually here to be asked, maybe raise [16:34.080 --> 16:40.040] your hand, say hello to the people, and just because they are paying for the trip, my company [16:40.040 --> 16:41.040] is hiring. [16:41.040 --> 16:47.200] So if you want to have an Android position and work with me together, there's a chance. [16:47.200 --> 16:53.880] And we have now questions, and I also prepared a higher-end demo, you see, that's all written [16:53.880 --> 16:56.480] and composed, and it goes over Rust. [16:56.480 --> 17:04.680] I have bridged big, big numbers, so you can start with the questions right now, and just [17:04.680 --> 17:06.600] copy-pasting stuff. [17:06.600 --> 17:10.440] So let's hope nothing is crashing. [17:10.440 --> 17:18.640] It actually crashed, I guess. [17:18.640 --> 17:25.720] Questions? [17:25.720 --> 17:47.200] I heard that JNI was being replaced for something else, I forgot what. [17:47.200 --> 17:55.200] There was JNA, something like that, which is, that's completely new to me. [17:55.200 --> 18:01.240] I just worked with JNI because it works, sometimes. [18:01.240 --> 18:12.840] So somebody else, maybe from the Rust unicorns, would you do Kotlin also, no, shame on you. [18:12.840 --> 18:20.920] So, okay, I hope I don't, ah, one is there. [18:20.920 --> 18:25.400] Yeah, I didn't try that. [18:25.400 --> 18:35.760] I was just asked if I used or no, you, damn it, I'm a little bit, I know of the library, [18:35.760 --> 18:37.720] but didn't use it so far. [18:37.720 --> 18:53.480] So maybe later, I can report back, okay, seemed, I talked you down, great, that's a good skill. [18:53.480 --> 18:56.000] Then we are done. [18:56.000 --> 19:05.800] Thank you very much again, we're going to have 10, 12 minutes till the next talk start.