Найти в Дзене
Один Rust не п...Rust

Rust & KMM

t.me/oneRustnoqRust Для чего нужна данная статья? :
- Изучить интеграцию Kotlin Multiplatform с Rust через FFI.
- Написать код для работы с ML. Зачем Вам это уметь? : Научиться работать с разными моделями памяти Rust и Kotlin, и научиться передавать данные pytorch между Rust и Kotlin. Что это?
Это как папка или контейнер для всех функций, классов и типов, связанных с TodoList. Все имена внутри namespace todolist не будут конфликтовать с такими же именами в других частях программы. Пример:
Представьте, что у вас есть две папки: "Работа" и "Дом". В каждой может быть файл "Список дел". Так и здесь: все функции и типы внутри todolist относятся только к этому списку дел. Что это?
Функция, которая возвращает стандартный список дел (TodoList). Знак ? означает, что она может вернуть либо список, либо null (то есть ничего). Пример:
Как если бы вы спросили: "Дай мне мой основной список покупок", а вам ответили: "Вот он" или "У тебя нет основного списка". Что это?
Функция, которая устанавливает н
Оглавление
GitHub - nicktretyakov/todo_ml
ML на RUST без заморочек

t.me/oneRustnoqRust

Для чего нужна данная статья? :
- Изучить интеграцию Kotlin Multiplatform с Rust через FFI.
- Написать код для работы с ML.

Зачем Вам это уметь? :

Научиться работать с разными моделями памяти Rust и Kotlin, и научиться передавать данные pytorch между Rust и Kotlin.

Код создает список дел с использованием ML:

  • namespace — папка для кода.
  • TodoList — интерфейс списка дел.
  • TodoEntry — одна задача в списке.
  • TodoError — возможные ошибки.
  • Пишется на Kotlin и Rust.
  • Работает на Android, iOS, десктопе и других платформах.
  • Использует Uniffi для связи между Rust и Kotlin.
  • Собирается с помощью Gradle специальных плагинов и команды, например cargo build --target aarch64-linux-android.

namespace todolist { ... }

Что это?
Это как папка или контейнер для всех функций, классов и типов, связанных с TodoList. Все имена внутри namespace todolist не будут конфликтовать с такими же именами в других частях программы.

Пример:
Представьте, что у вас есть две папки: "Работа" и "Дом". В каждой может быть файл "Список дел". Так и здесь: все функции и типы внутри todolist относятся только к этому списку дел.

TodoList? get_default_list();

Что это?
Функция, которая возвращает стандартный список дел (TodoList). Знак ? означает, что она может вернуть либо список, либо null (то есть ничего).

Пример:
Как если бы вы спросили: "Дай мне мой основной список покупок", а вам ответили: "Вот он" или "У тебя нет основного списка".

undefined set_default_list(TodoList list);

Что это?
Функция, которая устанавливает новый стандартный список дел. undefined означает, что функция ничего не возвращает (просто выполняет действие).

Пример:
Как если бы вы сказали: "Сделай этот список моим основным".

[Throws=TodoError]

Что это?
Это значит, что функция может "выбросить" ошибку типа TodoError. То есть, если что-то пойдёт не так, программа может остановиться и сказать, что именно пошло не так.

Пример:
Если вы пытаетесь добавить пустую строку в список, функция может сказать: "Ошибка: EmptyString".

dictionary TodoEntry { string text; }

Что это?
Определение типа TodoEntry — это как запись в списке дел. У неё есть одно поле: text (строка).

Пример:
{ text: "Купить молоко" }

enum TodoError { ... }

Что это?
Список возможных ошибок, которые могут произойти при работе со списком дел.

Примеры ошибок:

  • TodoDoesNotExist — такой задачи нет.
  • EmptyTodoList — список пуст.
  • DuplicateTodo — такая задача уже есть.
  • EmptyString — нельзя добавить пустую строку.
  • DeligatedError — ошибка от другой функции.

interface TodoList { ... }

Что это?
Описание того, что должен уметь делать любой список дел (TodoList). Это как договор: если класс реализует этот интерфейс, он обязан иметь все эти функции.

Примеры функций:

  • add_item(string todo) — добавить задачу (например, "Купить хлеб").
  • get_entries() — получить все задачи в виде списка.
  • get_last_sentiment() — получить "настроение" последней задачи (например, 0.8 — позитивное).

[Self=ByArc] и undefined make_default();

Что это?

  • [Self=ByArc] — техническая деталь, означает, что объект будет передан "по ссылке" (эффективно, без копирования).
  • make_default() — функция, которая делает текущий список стандартным.

Пример:
Как если бы вы сказали: "Сделай этот список моим основным".

Импорты (import)

Что это?
Это подключение готовых библиотек или модулей, чтобы использовать их функции в вашем проекте.
Пример:

import gobley.gradle.GobleyHost

Здесь подключается модуль GobleyHost, чтобы потом можно было проверить, на какой платформе (например, MacOS) запущен проект.

Плагины (plugins)

Что это?
Плагины добавляют новые возможности в процесс сборки проекта.
Пример:

kotlin("multiplatform")
id("dev.gobley.cargo")

  • kotlin("multiplatform") — позволяет писать код, который будет работать на разных платформах (Android, iOS, десктоп).
  • dev.gobley.cargo — плагин для работы с Rust-кодом (например, для сборки библиотек на Rust).

Cargo (Rust)

Что это?
Это блок для настройки сборки Rust-кода. Здесь указывается, как и для каких платформ собирать Rust-библиотеки.
Пример:

cargo {
builds.appleMobile {
variants {
if (rustTarget.tier(project.rustVersion.get()) >= 3) {
buildTaskProvider.configure {
nightly = true
extraArguments.add("-Zbuild-std")
}
}
}
}
}

  • builds.appleMobile — сборка для мобильных устройств Apple.
  • nightly = true — использование ночной (экспериментальной) версии компилятора Rust.
  • extraArguments.add("-Zbuild-std") — дополнительные флаги для компилятора.

Uniffi

Что это?
Инструмент для генерации связок (bindings) между Rust и Kotlin, чтобы можно было вызывать Rust-код из Kotlin.
Пример:

uniffi {
bindgenFromPath(rootProject.layout.projectDirectory.dir("crates/gobley-uniffi-bindgen"))
generateFromUdl {
udlFile = layout.projectDirectory.file("src/todolist.udl")
namespace = "todolist"
}
}

  • bindgenFromPath — путь к инструменту, который генерирует связки.
  • udlFile — файл с описанием интерфейсов (что и как будет доступно из Kotlin).
  • namespace — пространство имён для сгенерированного кода.

Kotlin Multiplatform

Что это?
Настройка целевых платформ, для которых будет собираться Kotlin-код.
Пример:

kotlin {
androidTarget { ... }
jvm("desktop")
iosArm64()
macosArm64()
...
}

  • androidTarget — сборка под Android.
  • jvm("desktop") — сборка под десктоп (Java-машина).
  • iosArm64() — сборка под iPhone.

Android

Что это?
Настройка специфичных для Android параметров сборки.
Пример:

android {
namespace = "dev.gobley.uniffi.examples.todolist"
compileSdk = libs.versions.android.compileSdk.get().toInt()
...
}

  • namespace — уникальный идентификатор вашего приложения.
  • compileSdk — версия Android SDK, под которую компилируется проект.

Java Toolchain

Что это?
Указание версии Java, которая будет использоваться для сборки.
Пример:

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

  • languageVersion = JavaLanguageVersion.of(17) — проект будет собираться с использованием Java 17.

SentimentModel — анализ тональности текста

Что это?
Это модель машинного обучения, которая анализирует текст и определяет, положительный он, отрицательный или нейтральный.

Пример:

fn get_last_sentiment(&self) -> Result<f64> {
let last = self.get_last()?;
let inputs = [last.as_str()];
let sentiments: Vec<Sentiment> = SENTIMENT_MODEL.predict(&inputs);
// ...
}

Здесь функция берёт последний элемент из списка дел и анализирует его тональность.

uniffi::include_scaffolding! — связь с другими языками

Что это?
Это макрос, который позволяет использовать Rust-код из других языков программирования (например, Kotlin или Swift).

Работа с памятью (destroy, use)

Что это?
В этом коде используется Rust-библиотека, поэтому важно правильно освобождать память, чтобы не было "утечек". Для этого есть методы destroy и блок use.

Пример:

TodoList().use { todo2 ->
// Здесь todo2 будет автоматически уничтожен после блока
}

→ После выполнения кода в блоке todo2 будет удалён, память освобождена.

Анализ настроения (sentiment analysis)

Что это?
В коде есть функция, которая оценивает "настроение" текста задачи (положительное, отрицательное, нейтральное) и возвращает число от -1 до 1.

Примеры:

todo.addItem("Отличная задача! :)")
todo.getLastSentiment() shouldBeGreaterThan 0.5
// Положительное настроение
todo.addItem("Ужасная задержка :(")
todo.getLastSentiment() shouldBeLessThan -0.5
// Отрицательное настроение

Работа с дефолтным списком (default list)

Что это?
Можно сделать один из списков "дефолтным" (основным), и с ним будут работать другие части программы.

Пример:

setDefaultList(todo) // Устанавливаем todo как дефолтный список
getDefaultList()
// Получаем дефолтный список