Docsの目次

自作ライブラリとRustの資産を使う

Nagiでアプリの処理を書き、共通の関数を別ファイルにまとめたり、Rustのライブラリを呼んだりできます。HTTPやDBをすべて組み込み関数で実装する必要はありません。

このページの目次

共通の処理を複数のアプリで使う

料金計算CLIとJSONレポートは、同じ料金計算ライブラリを読み込みます。共通のNagiファイルが入力の検証と公開する型を決め、Rust側に計算の実装を置いています。

library-examples/
  shared/              共通のNagi宣言とRustの実装
  foundation-cli/      入力を受け取って見積もるアプリ
  foundation-report/   複数の見積もりをJSONにするアプリ

import "../shared/foundation.nagi"のように相対パスで共通ファイルを読み込みます。Rustの入口は各アプリのnagi.tomlに指定し、そのRustファイルから共通モジュールを読み込みます。サンプルはディレクトリ一式で使ってください。

現在のimportはファイルの定義を同じ名前空間へ読み込みます。公開範囲やaliasはないので、共通関数には名前が衝突しにくい名前を付けます。Cargoのcrateとしての配布や、Nagiのパッケージ管理とは別の仕組みです。

Rustライブラリとの境界を小さくする

Rust連携のリファレンスに、@rust・extern def・型の対応をまとめています。

Rustのcrateを使うときは、Rust側にNagiから呼ぶ関数を用意します。その関数でcrate固有の型をNagiの数値・文字列・class・Resultへ変換すると、アプリ側はRustの実装の詳細を知らずに使えます。

JSON読込では、serde_jsonがNagiのclassに対応するJSONを読みます。入力の文字列は借り、形式が合わない場合はResultの失敗を返します。非同期処理では、TokioのtimerをNagiからawaitします。

Nagiのcheckが検査するのは宣言と呼び出しです。Rustの関数との型の一致はbuildで検査します。Rustの任意の型、trait、genericをそのままNagiから使う仕組みではありません。Rust側のblocking処理や独自の共有状態は、そのライブラリ側で管理します。

アプリの処理をRust側から呼ぶ

引数に同期関数の型を宣言すると、Nagiの関数をRustへ渡せます。自作HTTP基盤はこの方法を使います。

HTTPの受付と停止はRustのAxum/Tokio、応答を作る関数はNagiが担当します。Nagiの組み込みserveやDbを使わずに、Rust側の基盤にアプリの処理を渡す例です。

このサーバーには、Nagiの組み込みHTTPサーバーの制限が自動で適用されません。サンプルが設定する上限はREADMEに記載しています。また、現在の生成アプリは共通ランタイムへ依存するため、Dbを呼ばないプログラムでもビルド時のSQLite依存は残ります。

Highの実装をLowへ置き換える

Low計算カーネルは、Highの呼び出しを変えずに、同じ型のLow実装へ置き換えます。Rustライブラリを追加せず、Nagi内で実装を差し替える方法です。

実装をLowに移すだけで速くなるとは限りません。結果の一致を確認し、必要な箇所で速度や割り当てを測定してください。

ライブラリ利用で今後整えること

以下は設計対象であり、現在使える設定・文法ではありません。

  • Rust依存のpath・features・default-featuresを指定し、手元のcrateや必要な機能だけを組み込む。
  • Nagiの名前付きmodule・as・from・公開範囲を定義し、ライブラリ同士の名前の衝突を防ぐ。
  • HTTP・DBを用途に応じて選べる標準ライブラリに分け、使わない依存をビルドから外す。
  • 自作の接続・clientなどを扱う型について、所有権・共有・終了・asyncの取消しの規則を決める。
  • DBを一般化する際は、PostgreSQLへの接続だけでなく、型付きのSQL引数・行の読込・transactionを設計する。

既存のファイルimport・extern・SQLiteの呼び出しを使うコードを保ちながら、これらの設計を確認して進めます。具体的な設計案とサンプル一覧があります。

Nagi 0.1のドキュメントこのページのソース