Как стать автором
Обновить
675.46
OTUS
Цифровые навыки от ведущих экспертов

Как реализовывается WebAssembly в Rust: кратко

Время на прочтение4 мин
Количество просмотров4.8K

Привет, Хабр!

Rust - язык, который за последние годы завоевал сердца разработчиков своей надежностью, а в особенности безопасностью. WebAssembly в свою очередь позволяет нам перенести производительность и мощь нативных приложений в браузер. Вместе эти инструменты позволяют сделать веб-приложения с высокой скоростью, ну и кончечно - высокой безопасностью.

з.ы: предполагается, что читатель знает основы webassembly и про что-то из rust

Реализация

wasm-bindgen

wasm-bindgen – это библиотека и инструмент командной строки, который облегчает взаимодействие между кодом на Rust и JavaScript, позволяет вызывать функции JavaScript из Rust и наоборот, а также работать с различными типами данных.

Можно вызывать функции JavaScript прямо из Rust. Это позволяет использовать возможности браузера и веб-API, не покидая экосистему Rust.

wasm-bindgen позволяет экспортировать функции Rust в WebAssembly, которые затем могут быть вызваны из JavaScript, также он облегчает обмен сложными типами данных между Rust и JavaScript, например, строками, структурами и даже целыми классами.

Допустим, у нас есть следующая функция JavaScript, которая выводит сообщение в консоль:

function greet(name) {
    console.log(`Hello, ${name}!`);
}

Вызываем эту функцию из Rust следующим образом:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    fn greet(name: &str);
}

#[wasm_bindgen(start)]
pub fn run() {
    greet("World");
}

Теперь сделаем наоборот. Напишем функцию на Rust и вызовем её из JavaScript:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add(x: i32, y: i32) -> i32 {
    x + y
}

Теперь мы можем вызвать эту функцию из JavaScript:

import { add } from './my_module';

console.log(add(5, 7)); // Выведет 12

wasm-bindgen также позволяет работать со структурами Rust в JavaScript. Например:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct Point {
    x: i32,
    y: i32,
}

#[wasm_bindgen]
impl Point {
    pub fn new(x: i32, y: i32) -> Point {
        Point { x, y }
    }

    pub fn x(&self) -> i32 {
        self.x
    }

    pub fn y(&self) -> i32 {
        self.y
    }
}

В JavaScript мы можем создать и использовать объект Point так:

import { Point } from './my_module';

const p = Point.new(2, 3);
console.log(p.x()); // Выведет 2
console.log(p.y()); // Выведет 3

wasm-pack

wasm-pack – это инструмент, предназначенный для сборки Rust-кода в WebAssembly и управления всем процессом от начала до конца.

wasm-pack компилирует Rust-код в WebAssembly, оптимизируя его для использования в вебе. После сборки wasm-pack помогает упаковать проект в формат, совместимый с npm, что упрощает его распространение и использование.

wasm-pack поддерживает тестирование кода на WebAssembly.

Установку wasm-pack можно сделать через cargo:

cargo install wasm-pack

Затем создаем новый проект с использованием cargo:

cargo new --lib my_wasm_project
cd my_wasm_project

В файле Cargo.toml проекта указывается зависимостьwasm-bindgen, так как wasm-pack работает в тандеме с ним:

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

В файле src/lib.rs создадим простую функцию:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn greet(name: &str) -> String {
    format!("Hello, {}!", name)

Теперь можно собрать проект с помощью wasm-pack:

wasm-pack build

Команда создаст папку pkg, в которой будет находиться скомпилированный WebAssembly код и автоматически сгенерированные JavaScript-обвязки.

После успешной сборки можно опубликовать свой пакет в npm:

wasm-pack publish

Теперь WebAssembly-модуль готов к использованию в JavaScript-проекте. Можно импортировать и использовать функцию greet в JavaScript-коде:

import { greet } from 'my_wasm_project';

console.log(greet('World')); // Выведет "Hello, World!"

cargo-web

cargo-web предоставляет простой в использовании локальный веб-сервер, который автоматически перезагружает ваше приложение при изменении кода.

Для начала установим cargo-web:

cargo install cargo-web

Затем создадим новый проект:

cargo new --lib my_web_project
cd my_web_project

В Cargo.toml, укажем тип сборки и добавим зависимости:

[package]
name = "my_project"
version = "1"
edition = "2"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

В src/lib.rs добавим простую функцию, которая будет использоваться в веб-приложении:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn say_hello() -> String {
    "Hello from Rust!".to_string()
}

Теперь можно запустить локальный веб-сервер с помощью cargo-web:

cargo web start

Эта команда запустит веб-сервер и откроет приложение в браузере. Любые изменения в коде будут автоматически отображаться.

Чтобы использовать функцию say_hello в веб-странице, создадим HTML-файл:

<!DOCTYPE html>
<html>
<head>
    <title>Rust WebAssembly App</title>
    <script type="module">
        import init, { say_hello } from './my_web_project.js';

        async function run() {
            await init();
            alert(say_hello());
        }

        run();
    </script>
</head>
<body>
    <h1>Hello from Rust and WebAssembly!</h1>
</body>
</html>

Этот код загрузит и инициализирует сгенерированный WebAssembly-модуль, а затем вызовет функцию say_hello.


Rust имеет хорошие инструменты для реализации WASM. Спасибо за прочтение статьи

В продолжение темы хочу напомнить про бесплатные вебинары от экспертов рынка про безопасный unsafe Rust и про то, как Rust побуждает использовать композицию.

А больше курсов от экспертов OTUS можно найти в полном каталоге.

Теги:
Хабы:
Всего голосов 14: ↑12 и ↓2+11
Комментарии1

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS