
Zig *
Жизнеспособная альтернатива языку C
AI-агенты уже переписывают не пет-проекты, а инфраструктуру уровня Bun

История с Bun выглядит как новый уровень вайбкодинга: не лендинг, не CRUD и не маленький сервис, а почти миллион строк системного кода.
Bun изначально был написан на Zig. После покупки Anthropic проект стал ещё важнее: на нём завязана инфраструктура Claude Code, поэтому любые проблемы runtime напрямую бьют по продукту.
И вот Джарред Самнер начал эксперимент с переносом Bun на Rust при помощи Claude. Сначала это звучало как черновой ресёрч, который легко могут выбросить.
Но через несколько дней Rust-ветка уже проходила около 99.8% тестов на Linux x64 glibc, а в обсуждениях всплыл масштаб порядка 960 тысяч строк портированного кода.
AI-агенты выглядят как инструмент для радикальных миграций: язык, runtime, архитектура, огромная кодовая база.
Да, качество такого порта ещё будут долго разбирать. Да, миллион строк от агента - это не автоматически production-ready. Но сам факт уже меняет планку.
Раньше переписывание большого проекта на другой язык было историей на месяцы или годы.
Теперь это может начинаться как эксперимент на неделю.
https://github.com/oven-sh/bun/pull/30412
Источник: https://t.me/rust_code/1287 - когда посмотрим код порта, поделюсь в канале впечатлениями
Столкнулся с проблемой отсутствия простых операций со строками, содержащими символы юникода (например, русские буквы), в стандартной библиотеке Zig.
Конкретно, требовалось привести строку в нижний регистр. И оказалось, впрочем ожидаемо, что методы модуля std.ascii не годятся для этого, прямо совсем. Ибо константа lowercase содержит только латинские символы.
А в модуле std.unicode в принципе нет методов, для реализации приведения к нижнему/верхнему регистру символов. В итоге пришлось городить небольшой костыль:
// Кастомное преобразование строки в нижний регистр, с поддержкой
// обработки русских символов, латиницы и акцентированных знаков.
fn toLowerCustom(allocator: Allocator, str: []const u8) ![]const u8 {
var result = std.ArrayList(u8).init(allocator);
var iter = std.unicode.Utf8Iterator{ .bytes = str, .i = 0 };
while (iter.nextCodepoint()) |cp| {
const lower = blk: {
// Русские символы
if (cp >= 'А' and cp <= 'Я') break :blk cp + ('а' - 'А');
if (cp == 'Ё') break :blk 'ё';
// Базовые латинские символы
if (cp >= 'A' and cp <= 'Z') break :blk cp + 32;
// Обработка акцентированных символов
break :blk switch (cp) {
0xC0...0xD6 => cp + 32, // À-Ö → à-ö
0xD8...0xDE => cp + 32, // Ø-Þ → ø-þ
0x100...0x17F => handleLatinExtended(cp),
else => cp,
};
};
var buf: [4]u8 = undefined;
const len = std.unicode.utf8Encode(lower, &buf) catch unreachable;
try result.appendSlice(buf[0..len]);
}
return result.toOwnedSlice();
}Знаю про существование библиотек для работы со строками на Zig, но ни одна не завелась, да и ради одного метода, тащить всю библиотеку, ИМХО, избыточно. Возможно, что я что-то пропустил и есть проверенные готовые решения?
Вынос тестов Zig в отдельные файлы
Когда читаешь статьи о разработке на Zig, часто видишь примеры, где тесты находятся в одном файле с основным кодом. Однако при активной разработке такой подход становится неудобным.
Выносить тесты в отдельные файлы — хорошая практика. Рассмотрим это на примере проекта https://github.com/ktarasov/zigrep.
Для начала создадим директорию tests в корне проекта и файл unit_tests.zig. Перенесем туда все тесты из src/main.zig. В список зависимостей добавим импорт главного модуля: const main_mod = @import("../src/main.zig");. Вызовы функций и структур в тестах модифицируем, добавив к ним модуль, например: main_mod.parseArgs.
Важно сделать тестируемые функции публичными, иначе тесты не скомпилируются.
Далее нужно сообщить компилятору, что тесты теперь находятся в другом месте. Для этого изменим файл build.zig. После строки run_step.dependOn(&run_cmd.step) добавим создание модуля с тестами:
const unit_test_mod = b.createModule({
.root_source_file = b.path("tests/unit_tests.zig"),
.target = target,
.optimize = optimize,
});
Также изменим блок добавления константы exe_unit_tests, указав unit_test_mod в качестве root_module.
Вроде всё готово. Попробуем скомпилировать и запустить тесты...
О нет, ошибка: "error: import of file outside module path: './src/main.zig'". Компилятор не импортирует файлы за пределами модуля unit_tests.zig.
Придется явно добавить основной модуль в импорт test-модуля. Для этого вернемся в build.zig и добавим после создания exe_unit_tests следующую строку:
exe_unit_tests.root_module.addImport("zigrep", exe_mod);
Снова запустим тесты — и они успешно пройдут!
Итого: мы вынесли тесты в отдельный файл и создали иерархию директорий, разделив основной код и тесты.
Новый релиз языка Zig 0.14.0
Я информирую о релизе постом только потому, что у меня лично сейчас нет свободного времени написать полноценную статью об всех изменениях. Изменений много.
Важное изменение, которое всё же я упомяну - появился свой backend для компилятора. То есть отказ от LLVM состоялся, но на данный момент только для Linux x86_64.
Первая вакансия на Zig в России
Собственно вот: https://career.habr.com/vacancies/1000147586
Вот мы (те кто следит за языком Zig) и дожили до этого момента. Большой вопрос зачем Zig в проде сейчас. Но сам факт такого похвальный. Начали появляться смельчаки, готовые взять ещё очень молодой язык в работу. Я туда не откликнусь, не мой стек. Но может найдутся желающие