<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Varyk - Blog</title>
    <subtitle>Build backend services simply. Ship Rust binaries. Varyk is an experimental language for APIs, workers, and microservices that compiles to Rust, with Rust&#39;s safety and Go&#39;s simplicity.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://varyk.com/blog/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://varyk.com/blog/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-12T00:00:00+00:00</updated>
    <id>https://varyk.com/blog/atom.xml</id>
    <entry xml:lang="en">
        <title>Varyk 0.9.0: errors in your editor</title>
        <published>2026-10-12T00:00:00+00:00</published>
        <updated>2026-10-12T00:00:00+00:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-9-0/"/>
        <id>https://varyk.com/blog/varyk-0-9-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-9-0/">&lt;p&gt;Varyk 0.9.0 is on crates.io. It is the first release of milestone 6 on the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;: tooling. It brings three things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;varyk lsp&lt;/code&gt;, a language server, so the errors and fixes of &lt;code&gt;varyk check&lt;/code&gt; show up in your editor;&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;varyk-std&lt;/code&gt; line that names the oldest varyk a package needs, so a new varyk no longer breaks published packages;&lt;/li&gt;
&lt;li&gt;Rust 1.88 as the minimum.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;errors-in-your-editor&quot;&gt;Errors in your editor&lt;/h2&gt;
&lt;p&gt;Until now, you saw Varyk&#39;s errors when you ran &lt;code&gt;varyk check&lt;/code&gt;. Now your editor shows them. Each time you open or save a &lt;code&gt;.vr&lt;/code&gt; file, &lt;code&gt;varyk lsp&lt;/code&gt; checks the program the file belongs to, exactly as &lt;code&gt;varyk check&lt;/code&gt; would. The editor underlines every error where it is, with its message, notes, and code. When an error has a suggested fix, the editor offers it as a quick fix. A fix can change another file: a missing &lt;code&gt;pub&lt;/code&gt; is added where the item is declared.&lt;/p&gt;
&lt;p&gt;The server checks what is on disk, so a fixed error disappears once you save. You never run &lt;code&gt;varyk lsp&lt;/code&gt; yourself. The editor starts it. The &lt;a href=&quot;/learn/reference/#editors&quot;&gt;reference&lt;/a&gt; explains which program a file belongs to.&lt;/p&gt;
&lt;p&gt;The editor support lives in a new repository, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-editors&quot;&gt;&lt;code&gt;varyk-editors&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;VS Code&lt;/strong&gt;, and the editors built on it: install &lt;strong&gt;Varyk&lt;/strong&gt; from the Visual Studio Marketplace, or from Open VSX in VSCodium and the others that use it. It colours &lt;code&gt;.vr&lt;/code&gt; files, toggles comments, matches brackets, indents, and starts &lt;code&gt;varyk lsp&lt;/code&gt;. In a folder VS Code does not trust, it only highlights and runs nothing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zed&lt;/strong&gt;: the &lt;strong&gt;Varyk&lt;/strong&gt; extension is &lt;a rel=&quot;external&quot; href=&quot;https://github.com/zed-industries/extensions/pull/8007&quot;&gt;submitted&lt;/a&gt; to Zed&#39;s extension registry. It will be in the extensions panel as soon as the Zed team merges it. Until then, run &quot;zed: install dev extension&quot; and choose the &lt;code&gt;zed/&lt;/code&gt; folder of a checkout of &lt;code&gt;varyk-editors&lt;/code&gt;. It is built on a Tree-sitter grammar, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/tree-sitter-varyk&quot;&gt;&lt;code&gt;tree-sitter-varyk&lt;/code&gt;&lt;/a&gt;. It colours &lt;code&gt;.vr&lt;/code&gt; files, gives you the outline panel, and starts &lt;code&gt;varyk lsp&lt;/code&gt;. In a folder Zed does not trust, it only highlights and runs nothing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JetBrains IDEs&lt;/strong&gt;: colours, comment toggling, and bracket matching, through the TextMate Bundles setting pointed at the &lt;code&gt;vscode/&lt;/code&gt; folder of a checkout of &lt;code&gt;varyk-editors&lt;/code&gt;. &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-editors#jetbrains&quot;&gt;Its README&lt;/a&gt; has the steps. No diagnostics there yet: those need a plugin on the IDE&#39;s own language server API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Any other editor&lt;/strong&gt; that speaks the Language Server Protocol can run &lt;code&gt;varyk lsp&lt;/code&gt; itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With &lt;code&gt;varyk&lt;/code&gt; 0.9 on your &lt;code&gt;PATH&lt;/code&gt;, there is nothing to set up. If it lives somewhere else, VS Code has a &lt;code&gt;varyk.path&lt;/code&gt; setting. Highlighting never depends on the language server, so with an older &lt;code&gt;varyk&lt;/code&gt;, or none, you still get colours.&lt;/p&gt;
&lt;h2 id=&quot;packages-keep-building&quot;&gt;Packages keep building&lt;/h2&gt;
&lt;p&gt;Up to 0.8, a program and every Varyk package in its build had to name the compiler&#39;s own minor version of &lt;code&gt;varyk-std&lt;/code&gt;. So every minor release of the compiler, even one that changed nothing in &lt;code&gt;varyk-std&lt;/code&gt;, broke every published package until that package released again. I did not want every varyk release to force a release of every package.&lt;/p&gt;
&lt;p&gt;From 0.9, &lt;code&gt;varyk-std = &quot;0.8&quot;&lt;/code&gt; means &quot;needs varyk 0.8 or later&quot;. This varyk and every later one accept it, and the build always uses the compiler&#39;s own &lt;code&gt;varyk-std&lt;/code&gt;, in the program and in every package. A compiler older than the line refuses it with V0404. From 0.9 on, that error says &quot;this package needs varyk X.Y or later&quot; and tells you to run &lt;code&gt;cargo install varyk&lt;/code&gt;. When a package written for an older varyk does not pass the check, every error it shows gets one more note, here for a package called &lt;code&gt;units&lt;/code&gt;: &quot;&lt;code&gt;units&lt;/code&gt; was written for varyk 0.8; a newer release of it may build with this compiler&quot;.&lt;/p&gt;
&lt;p&gt;So &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http&quot;&gt;varyk-http&lt;/a&gt; 0.2, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql&quot;&gt;varyk-sql&lt;/a&gt; 0.4, and &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-mongo&quot;&gt;varyk-mongo&lt;/a&gt; 0.1, all written for varyk 0.8, build with 0.9 as they are. No new releases needed.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;varyk publish&lt;/code&gt; keeps the old, strict rule. A published crate is built by plain cargo from its own &lt;code&gt;Cargo.toml&lt;/code&gt; and lock. Nothing rewrites them there. So you publish with a varyk on the minor your line names.&lt;/p&gt;
&lt;h2 id=&quot;rust-1-88&quot;&gt;Rust 1.88&lt;/h2&gt;
&lt;p&gt;The compiler now needs Rust 1.88 or newer, up from 1.85, and CI checks it. varyk-mongo needed 1.88 from the start, for its MongoDB driver.&lt;/p&gt;
&lt;h2 id=&quot;for-rust-readers&quot;&gt;For Rust readers&lt;/h2&gt;
&lt;p&gt;Before 1.0, cargo treats &lt;code&gt;varyk-std&lt;/code&gt; 0.8 and 0.9 as two different crates whose types do not mix. An open requirement like &lt;code&gt;&amp;gt;=0.8&lt;/code&gt; does not help either: cargo picks the newest release, which can be yet another minor. So I did not loosen the requirement. varyk already writes every manifest of the build under &lt;code&gt;target/varyk/&lt;/code&gt;. Now it also puts its own &lt;code&gt;varyk-std&lt;/code&gt; version in each one, so every Varyk crate of the build uses the same &lt;code&gt;varyk-std&lt;/code&gt;. Your own &lt;code&gt;Cargo.toml&lt;/code&gt; and &lt;code&gt;Cargo.lock&lt;/code&gt; are left alone.&lt;/p&gt;
&lt;p&gt;A package&#39;s Varyk code is generated by your compiler against that &lt;code&gt;varyk-std&lt;/code&gt;, so it always matches. Only a package&#39;s own &lt;code&gt;.rs&lt;/code&gt; files were written against an older one. If a newer &lt;code&gt;varyk-std&lt;/code&gt; removed something they call, rustc says so at that file.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;varyk lsp&lt;/code&gt; adds no dependency to the compiler. The protocol is JSON-RPC with &lt;code&gt;Content-Length&lt;/code&gt; framing, read and written with the &lt;code&gt;serde_json&lt;/code&gt; the compiler already uses, and positions are in UTF-16, the protocol&#39;s default.&lt;/p&gt;
&lt;h2 id=&quot;what-is-not-there-yet&quot;&gt;What is not there yet&lt;/h2&gt;
&lt;p&gt;Hover, go-to-definition, and completion need a parser that recovers from an error and keeps going, and Varyk&#39;s does not yet. Checking as you type needs the server to read unsaved files and a checker fast enough to run on every keystroke. For now it checks on open and save. A file that no &lt;code&gt;mod&lt;/code&gt; line reaches yet gets no errors until one does. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has the rest of milestone 6.&lt;/p&gt;
&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;
&lt;p&gt;The three crates, &lt;code&gt;varyk&lt;/code&gt;, &lt;code&gt;varyk-syntax&lt;/code&gt;, and &lt;code&gt;varyk-std&lt;/code&gt;, are released together as 0.9.0. One thing is breaking: the compiler needs Rust 1.88, so run &lt;code&gt;rustup update&lt;/code&gt; first if yours is older. Then &lt;code&gt;cargo install varyk --locked&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A program written for 0.8 builds as it is, but move its &lt;code&gt;varyk-std&lt;/code&gt; line anyway, and do it again after each new minor varyk. The build uses varyk-std 0.9. It never touches your &lt;code&gt;Cargo.toml&lt;/code&gt; or &lt;code&gt;Cargo.lock&lt;/code&gt;. So while the line says 0.8, the lock has no varyk-std 0.9, and every build asks crates.io for it again. Online, that is a bit slower. Offline, or in a CI job or container build without network access, the build fails. In the program&#39;s folder:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;change the line to &lt;code&gt;varyk-std = &quot;0.9.0&quot;&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;cargo update -p varyk-std&lt;/code&gt;. Cargo may say the name is ambiguous. That happens when the lock also holds the varyk-std 0.8 that a package like varyk-http was written for. Then run &lt;code&gt;cargo update -p varyk-std@0.9.0&lt;/code&gt; instead.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Commit both files, and builds work offline again. A program made with &lt;code&gt;varyk init&lt;/code&gt; 0.9 starts on the new line. The &lt;a href=&quot;/learn/reference/#varyk-add-and-upgrading&quot;&gt;reference&lt;/a&gt; has the details.&lt;/p&gt;
&lt;p&gt;To publish with varyk 0.9, move the line to 0.9 first: &lt;code&gt;varyk publish&lt;/code&gt; wants the compiler&#39;s own minor and no older &lt;code&gt;varyk-std&lt;/code&gt; anywhere in the build. A package that uses varyk-http, varyk-sql, or varyk-mongo is published with varyk 0.8 until the packages it uses have a release written for varyk 0.9. That goes for a library and for a program.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain, 1.88 or newer, installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk --locked&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then install the Varyk extension in VS Code, or in Zed once it is listed, open the folder, break something in &lt;code&gt;src/main.vr&lt;/code&gt;, and save. &lt;a href=&quot;/learn/getting-started/&quot;&gt;Getting started&lt;/a&gt; goes on to &lt;a href=&quot;/learn/getting-started/#a-first-service&quot;&gt;a first service&lt;/a&gt;, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;The rest of milestone 6: &lt;code&gt;varyk fmt&lt;/code&gt;, the rest of the language server, nested modules in &lt;code&gt;.rs&lt;/code&gt; files, Rust tuple and unit structs imported from &lt;code&gt;.rs&lt;/code&gt; files, &lt;code&gt;Debug&lt;/code&gt; on imported Rust structs, and a decision on a native backend. Next to it, &lt;code&gt;varyk-redis&lt;/code&gt;, the next package. None of it has a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Open a &lt;code&gt;.vr&lt;/code&gt; file, save it with a mistake in it, and tell me where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>varyk-mongo 0.1.0: MongoDB for Varyk</title>
        <published>2026-10-10T16:30:00+02:00</published>
        <updated>2026-10-10T16:30:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-mongo-0-1-0/"/>
        <id>https://varyk.com/blog/varyk-mongo-0-1-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-mongo-0-1-0/">&lt;p&gt;varyk-mongo 0.1.0 is on crates.io. It is the official MongoDB package for &lt;a href=&quot;/&quot;&gt;Varyk&lt;/a&gt;, a language for backend services that compiles to Rust, over the official &lt;code&gt;mongodb&lt;/code&gt; crate. It covers what an ordinary service does with MongoDB and nothing more: connect over TLS, read and write typed documents, filter with MongoDB&#39;s own operators, aggregate, index, run transactions, and test against a real server. It lives in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-mongo&quot;&gt;its own repository&lt;/a&gt;, and its &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-mongo#readme&quot;&gt;README&lt;/a&gt; is the full documentation. varyk-mongo is not affiliated with or endorsed by MongoDB, Inc.&lt;/p&gt;
&lt;p&gt;Milestone 5 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, the batteries for services, is complete, and varyk-mongo is the first of &lt;a href=&quot;/design/roadmap/#the-next-packages&quot;&gt;the next packages&lt;/a&gt; it lists after that, not a milestone of its own. Its work is done in a &lt;code&gt;.rs&lt;/code&gt; facade over the driver, its tests against a real server are written in Varyk, and a program that uses it writes no Rust. The compiler side came as two patch releases, Varyk 0.8.1 and 0.8.2, and varyk-sql 0.4.0 came in the same round; all three are below.&lt;/p&gt;
&lt;h2 id=&quot;adding-it&quot;&gt;Adding it&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; install varyk&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; --locked&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; init users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; add mongo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;varyk add mongo&lt;/code&gt; runs &lt;code&gt;cargo add varyk-mongo --rename mongo&lt;/code&gt;, so the manifest gets &lt;code&gt;mongo = { version = &quot;0.1.0&quot;, package = &quot;varyk-mongo&quot; }&lt;/code&gt; and code names the package &lt;code&gt;mongo::&lt;/code&gt;. varyk-mongo 0.1 works with Varyk 0.8.1 and later 0.8 releases, and programs that use it need Rust 1.88 or later, because the &lt;code&gt;mongodb&lt;/code&gt; crate does; &lt;code&gt;rustup update&lt;/code&gt; gets it. The compiler and the other packages stay at Rust 1.85.&lt;/p&gt;
&lt;h2 id=&quot;a-first-program&quot;&gt;A first program&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;src/main.vr&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Config&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mongo_url: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[rename(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Uuid&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    email: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    created_at: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Time&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; run&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; config: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; env::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; mongo::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;connect&lt;/span&gt;&lt;span&gt;(config.mongo_url).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; users &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collection&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;users&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;create_index&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ email: 1 }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ unique: true }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;delete_many&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ email: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;ada@example.com&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;   &lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;// a rerun starts clean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; ada &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; { id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Uuid&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(), email: &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;ada@example.com&amp;quot;&lt;/span&gt;&lt;span&gt;, name: &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span&gt;, created_at: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Time&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;now&lt;/span&gt;&lt;span&gt;() };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;insert&lt;/span&gt;&lt;span&gt;(ada).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; found: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;first&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ email: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;ada@example.com&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; recent: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{ created_at: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ $gte: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; }&amp;quot;&lt;/span&gt;&lt;span&gt;, ada.created_at)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;sort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ created_at: -1 }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;limit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;20&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;all&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;update&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ _id: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{ $set: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ name: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; }&amp;quot;&lt;/span&gt;&lt;span&gt;, ada.id, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada L.&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; gone: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;delete&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ _id: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, ada.id).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{} {} {}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, found.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_some&lt;/span&gt;&lt;span&gt;(), recent.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;len&lt;/span&gt;&lt;span&gt;(), gone);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    run&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MONGO_URL&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;mongodb://127.0.0.1:27017/app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With a server running, &lt;code&gt;varyk run&lt;/code&gt; prints &lt;code&gt;true 1 1&lt;/code&gt;: Ada was found, she is the one recent user, and one document was deleted. The URL names the one database a service uses, and &lt;code&gt;mongo::connect&lt;/code&gt; sends &lt;code&gt;ping&lt;/code&gt;, so a wrong URL, a server that cannot be reached, or a refused password fails at startup rather than at the first request. &lt;code&gt;#[rename(&quot;_id&quot;)]&lt;/code&gt; makes &lt;code&gt;id&lt;/code&gt; the document&#39;s &lt;code&gt;_id&lt;/code&gt;, and &lt;code&gt;ada&lt;/code&gt; stays usable after &lt;code&gt;users.insert(ada)&lt;/code&gt;: the call reads the document and does not take it. The same program is in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-mongo/tree/main/demo/users&quot;&gt;&lt;code&gt;demo/users&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-calls&quot;&gt;The calls&lt;/h2&gt;
&lt;p&gt;On a collection, &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;first&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt;, and &lt;code&gt;count&lt;/code&gt; read; &lt;code&gt;find&lt;/code&gt; builds a query that &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;skip&lt;/code&gt;, and &lt;code&gt;limit&lt;/code&gt; refine, and sends nothing until its &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;first&lt;/code&gt;, or &lt;code&gt;all&lt;/code&gt;; &lt;code&gt;aggregate&lt;/code&gt; runs a pipeline. &lt;code&gt;insert&lt;/code&gt; and &lt;code&gt;insert_many&lt;/code&gt; write documents, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;update_many&lt;/code&gt;, &lt;code&gt;upsert&lt;/code&gt;, and &lt;code&gt;replace&lt;/code&gt; change them, &lt;code&gt;delete&lt;/code&gt; and &lt;code&gt;delete_many&lt;/code&gt; remove them, and &lt;code&gt;create_index&lt;/code&gt; makes an index, which does nothing when it exists with the same options, so a service makes its indexes at startup. &lt;code&gt;T&lt;/code&gt; comes from where the result goes, as in varyk-sql.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; user: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ email: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, email).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; adults: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;count&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{ age: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ $gte: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; }&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;18&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; page: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;find&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ city: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, city)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;sort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ name: 1 }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;skip&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;20&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;limit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;10&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;all&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; one: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;update&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ _id: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{ $set: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ name: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, $inc: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ age: 1 }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; }&amp;quot;&lt;/span&gt;&lt;span&gt;, id, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada L.&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; added: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;upsert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ email: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{ $set: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ name: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, $setOnInsert: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ created_at: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; }&amp;quot;&lt;/span&gt;&lt;span&gt;, email, name, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Time&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;now&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; gone: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;delete_many&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ city: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Paris&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;the-query-text&quot;&gt;The query text&lt;/h2&gt;
&lt;p&gt;Each text in quotes is MongoDB&#39;s own query syntax, as the shell and Compass write it, with &lt;code&gt;?&lt;/code&gt; where a value goes, and it is a literal string: a query built from input does not compile. The values follow the text, one per &lt;code&gt;?&lt;/code&gt;, from left to right across all the texts of the call. This is the package&#39;s guard against injection: a value is always data, so input cannot become an operator (&lt;code&gt;{ &quot;$ne&quot;: null }&lt;/code&gt;) or a part of the query. The rules that keep input out of the query are each an &lt;code&gt;Error&lt;/code&gt; naming the place in the text, before anything is sent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A value stands only where MongoDB reads plain data&lt;/strong&gt;: anywhere in a filter, and in a top-level &lt;code&gt;$match&lt;/code&gt; stage of a pipeline, except under &lt;code&gt;$expr&lt;/code&gt; and &lt;code&gt;$jsonSchema&lt;/code&gt;; as a value under &lt;code&gt;$set&lt;/code&gt;, &lt;code&gt;$setOnInsert&lt;/code&gt;, &lt;code&gt;$inc&lt;/code&gt;, &lt;code&gt;$mul&lt;/code&gt;, &lt;code&gt;$min&lt;/code&gt;, &lt;code&gt;$max&lt;/code&gt;, &lt;code&gt;$push&lt;/code&gt;, and &lt;code&gt;$addToSet&lt;/code&gt;, and in the condition of &lt;code&gt;$pull&lt;/code&gt;; and as the number of a top-level &lt;code&gt;$skip&lt;/code&gt; or &lt;code&gt;$limit&lt;/code&gt; stage. Anywhere else MongoDB reads a string as a field path (&lt;code&gt;&quot;$passwordHash&quot;&lt;/code&gt;), a variable, or a collection name, so a value from input could read another field or another collection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A &lt;code&gt;None&lt;/code&gt; cannot be matched.&lt;/strong&gt; In a filter, a &lt;code&gt;$match&lt;/code&gt; stage, or a &lt;code&gt;$pull&lt;/code&gt; condition it is an &lt;code&gt;Error&lt;/code&gt;, since &lt;code&gt;{ reset_token: null }&lt;/code&gt; matches every document without a reset token. Write &lt;code&gt;null&lt;/code&gt; in the text to match a missing or null field; under &lt;code&gt;$set&lt;/code&gt; a &lt;code&gt;None&lt;/code&gt; stores null.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A value is never a pattern.&lt;/strong&gt; A &lt;code&gt;?&lt;/code&gt; under &lt;code&gt;$regex&lt;/code&gt; takes a &lt;code&gt;string&lt;/code&gt;, and the package escapes every character with a meaning in a pattern, so &lt;code&gt;users.all(&quot;{ name: { $regex: ?, $options: &#39;i&#39; } }&quot;, search)&lt;/code&gt; finds every name that holds &lt;code&gt;search&lt;/code&gt;, in any case, and nothing else.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No JavaScript on the server.&lt;/strong&gt; &lt;code&gt;$where&lt;/code&gt;, &lt;code&gt;$function&lt;/code&gt;, and &lt;code&gt;$accumulator&lt;/code&gt; are an &lt;code&gt;Error&lt;/code&gt; as a key anywhere in a text.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;?&lt;/code&gt; is never a key&lt;/strong&gt;, a key written twice in one document is an &lt;code&gt;Error&lt;/code&gt;, and the number of &lt;code&gt;?&lt;/code&gt;s must be the number of values.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The collection&#39;s name is a literal too, so input cannot choose which collection is read.&lt;/p&gt;
&lt;h2 id=&quot;documents-and-types&quot;&gt;Documents and types&lt;/h2&gt;
&lt;p&gt;A document is written from a struct, and read into one, by field name; &lt;code&gt;#[rename]&lt;/code&gt;, &lt;code&gt;#[skip]&lt;/code&gt;, and &lt;code&gt;#[default]&lt;/code&gt; work as they do for JSON. &lt;code&gt;Time&lt;/code&gt;, &lt;code&gt;Uuid&lt;/code&gt;, and &lt;code&gt;Bytes&lt;/code&gt; are stored as real BSON types, so TTL indexes, date operators, Compass, and other drivers see dates, ids, and binary data as such:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Varyk&lt;/th&gt;&lt;th&gt;Stored as&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Time&lt;/code&gt;&lt;/td&gt;&lt;td&gt;date, in milliseconds&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Uuid&lt;/code&gt;&lt;/td&gt;&lt;td&gt;binary subtype 4, which Compass shows as &lt;code&gt;UUID(&quot;…&quot;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Bytes&lt;/code&gt;&lt;/td&gt;&lt;td&gt;binary&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Option&lt;/code&gt;&lt;/td&gt;&lt;td&gt;null for &lt;code&gt;None&lt;/code&gt;, the value for &lt;code&gt;Some&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;array&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;a struct, a &lt;code&gt;HashMap&amp;lt;string, V&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;embedded document&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;BSON dates hold milliseconds, so a &lt;code&gt;Time&lt;/code&gt;&#39;s microseconds are dropped when it is stored, and a &lt;code&gt;Time&lt;/code&gt; beside a text is rounded the same way, so a &lt;code&gt;Time&lt;/code&gt; read back matches its own value. A new collection uses &lt;code&gt;#[rename(&quot;_id&quot;)] id: Uuid&lt;/code&gt; and &lt;code&gt;Uuid::new()&lt;/code&gt;, a new id ordered by time, as an ObjectId is. An existing collection whose &lt;code&gt;_id&lt;/code&gt;s are ObjectIds reads them into a &lt;code&gt;string&lt;/code&gt; as 24 hex digits and queries them with &lt;code&gt;ObjectId(?)&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;transactions&quot;&gt;Transactions&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Order&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[rename(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Uuid&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    item: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; place&lt;/span&gt;&lt;span&gt;(db: mongo::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Database&lt;/span&gt;&lt;span&gt;, order: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Order&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; tx &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;begin&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; orders &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collection&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;orders&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; stock &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collection&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;stock&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    orders.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;insert&lt;/span&gt;&lt;span&gt;(order).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; taken &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; stock.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;update&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{ _id: ?, left: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ $gte: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; }&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{ $inc: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{ left: ? }&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; }&amp;quot;&lt;/span&gt;&lt;span&gt;, order.item, order.count, &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&lt;/span&gt;&lt;span&gt;order.count).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; taken &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 0&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;out of stock&amp;quot;&lt;/span&gt;&lt;span&gt;));   &lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;// drops tx: rolls back the insert&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;commit&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;Tx&lt;/code&gt; dropped without &lt;code&gt;commit&lt;/code&gt; rolls back, so an early &lt;code&gt;return&lt;/code&gt; or a &lt;code&gt;?&lt;/code&gt; undoes it, as in varyk-sql. When a call inside the transaction fails in MongoDB, every later call on its collections is an &lt;code&gt;Error&lt;/code&gt; without reaching the server, and &lt;code&gt;commit&lt;/code&gt; rolls it back. A failure MongoDB calls temporary, a write conflict or an election, ends its message with &quot;run it again&quot;, and the README shows a loop that does. Transactions need a replica set or a sharded cluster; Atlas is one. On a single server that is not a replica set, the first call inside a transaction is an &lt;code&gt;Error&lt;/code&gt; saying so. For development, the README runs &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-mongo#a-server-for-development&quot;&gt;a replica set of one server&lt;/a&gt; in Docker; the package is tested against MongoDB 8.0.&lt;/p&gt;
&lt;h2 id=&quot;when-something-goes-wrong&quot;&gt;When something goes wrong&lt;/h2&gt;
&lt;p&gt;Every failure is an &lt;code&gt;Error&lt;/code&gt; whose message the package writes, and no call panics. A connection failure says which step failed and never contains the URL, so a password cannot reach a log that way. A mistake in a text names its place, and a value or a field that cannot be read names the value&#39;s number or the field, never the value. A server error keeps the server&#39;s message and code, and MongoDB puts the duplicate value in a duplicate-key message, so treat these messages as data: log them, and give clients a message of your own. The driver&#39;s command logging stays off, since it would log every command with its values, and the package logs nothing of its own. The driver is built with rustls and the webpki root certificates, so TLS works in a minimal container with no CA bundle and no OpenSSL.&lt;/p&gt;
&lt;h2 id=&quot;what-is-not-in-it&quot;&gt;What is not in it&lt;/h2&gt;
&lt;p&gt;A client with several databases; cursors; change streams; GridFS; bulk writes; &lt;code&gt;find_one_and_update&lt;/code&gt; and the other find-and-modify calls; a projection; &lt;code&gt;distinct&lt;/code&gt;; a transaction call that retries by itself; a pattern taken from input; a list beside the text (&lt;code&gt;{ _id: { $in: ? } }&lt;/code&gt;: write one &lt;code&gt;?&lt;/code&gt; for each element); collection names chosen at run time; and Decimal128, regex, and timestamp values beside the text; the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-mongo#not-in-this-version&quot;&gt;README&lt;/a&gt; has the full list. A document literal in the language, with values written inline, for MongoDB and JSON, is on the &lt;a href=&quot;/design/roadmap/#unscheduled&quot;&gt;roadmap&lt;/a&gt; as unscheduled, with no date; until then varyk-mongo builds its documents from structs, and the literal&#39;s shape is an open question.&lt;/p&gt;
&lt;h2 id=&quot;varyk-sql-0-4-0&quot;&gt;varyk-sql 0.4.0&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql&quot;&gt;varyk-sql&lt;/a&gt; 0.4.0 takes &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, and so on, on every database, SQLite, Postgres, and MySQL, so the same placeholders work on all three:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; user: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;first&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select id, name from users where id = $1&amp;quot;&lt;/span&gt;&lt;span&gt;, id).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;$2&lt;/code&gt; may come before &lt;code&gt;$1&lt;/code&gt;, and &lt;code&gt;$1&lt;/code&gt; may be written twice; it takes the same value each time. &lt;code&gt;?&lt;/code&gt; still works on SQLite and MySQL, one per value in order, so no query that bound correctly breaks. A &lt;code&gt;$&lt;/code&gt; inside a string, a quoted name, or a comment is text, not a placeholder. On SQLite and MySQL a query that mixes &lt;code&gt;?&lt;/code&gt; and &lt;code&gt;$1&lt;/code&gt;, or numbers its placeholders other than &lt;code&gt;$1&lt;/code&gt; up to the number of values, each used, is an &lt;code&gt;Error&lt;/code&gt; before it runs. varyk-sql&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#queries&quot;&gt;README&lt;/a&gt; now leads with &lt;code&gt;$1&lt;/code&gt;, and so do this site&#39;s first service and the figure on the home page. No compiler change was needed.&lt;/p&gt;
&lt;h2 id=&quot;varyk-0-8-1-and-0-8-2&quot;&gt;Varyk 0.8.1 and 0.8.2&lt;/h2&gt;
&lt;p&gt;Varyk 0.8.1 is what lets varyk-mongo store &lt;code&gt;Time&lt;/code&gt;, &lt;code&gt;Uuid&lt;/code&gt;, and &lt;code&gt;Bytes&lt;/code&gt; as BSON dates and binaries. A facade whose serializer is not human-readable, a binary database format, now gets a &lt;code&gt;Time&lt;/code&gt; as its Unix microseconds and a &lt;code&gt;Uuid&lt;/code&gt; as its 16 raw bytes, each in a form named in &lt;code&gt;varyk_std::serde_names&lt;/code&gt;, and a &lt;code&gt;Bytes&lt;/code&gt; as raw bytes, so it can store each as a native type. A human-readable serializer, JSON included, still gets the written string, so no output of an existing program changes. The &lt;a href=&quot;/learn/reference/#a-facade-for-a-package&quot;&gt;reference&lt;/a&gt; has the sentence for facade authors.&lt;/p&gt;
&lt;p&gt;Varyk 0.8.2 adds &lt;code&gt;varyk add mongo&lt;/code&gt;, beside &lt;code&gt;varyk add http&lt;/code&gt; and &lt;code&gt;varyk add sql&lt;/code&gt;; a path starting &lt;code&gt;mongo::&lt;/code&gt; that names nothing gets a note that &lt;code&gt;varyk add mongo&lt;/code&gt; adds varyk-mongo. It came after varyk-mongo 0.1.0 was on crates.io, so the short name never named a crate anyone else could register first.&lt;/p&gt;
&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk --locked&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then run &lt;code&gt;varyk check&lt;/code&gt; in a package, and it says what to change, if anything: the &lt;code&gt;varyk-std&lt;/code&gt; line in &lt;code&gt;Cargo.toml&lt;/code&gt;, or &lt;code&gt;cargo update -p varyk-std&lt;/code&gt;. Neither patch release breaks a program. To move to varyk-sql 0.4.0, change the version on the &lt;code&gt;sql&lt;/code&gt; line in &lt;code&gt;Cargo.toml&lt;/code&gt; to &lt;code&gt;&quot;0.4.0&quot;&lt;/code&gt;; &lt;code&gt;varyk add sql&lt;/code&gt; again does not do it, since &lt;code&gt;cargo add&lt;/code&gt; keeps the version of a dependency the manifest already lists. varyk-sql 0.3 keeps working with Varyk 0.8.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;varyk&lt;/th&gt;&lt;th&gt;varyk-sql&lt;/th&gt;&lt;th&gt;varyk-http&lt;/th&gt;&lt;th&gt;varyk-mongo&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0.8&lt;/td&gt;&lt;td&gt;0.4 or 0.3&lt;/td&gt;&lt;td&gt;0.2&lt;/td&gt;&lt;td&gt;0.1 (Varyk 0.8.1 or later)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;varyk-redis&lt;/code&gt; is the next package. Milestone 6 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, tooling and beyond, with &lt;code&gt;varyk fmt&lt;/code&gt; and a language server, is planned but not started, and has no date. Nothing on the roadmap is a date.&lt;/p&gt;
&lt;p&gt;Varyk and varyk-mongo are experimental and pre-1.0. Point a small service at MongoDB and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-mongo/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.8.0: time, ids, and bytes</title>
        <published>2026-10-07T00:00:00+00:00</published>
        <updated>2026-10-07T00:00:00+00:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-8-0/"/>
        <id>https://varyk.com/blog/varyk-0-8-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-8-0/">&lt;p&gt;Varyk 0.8.0 is on crates.io. It is milestone 5c of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, the last part of the batteries for services. Milestone 5b4 made the golden path: a users API on a database is &lt;code&gt;varyk init&lt;/code&gt;, &lt;code&gt;varyk add http sql&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away. What that API could not say well was when a user was made: a &lt;code&gt;created_at&lt;/code&gt; had to be a string. Milestone 5c adds three built-in types, &lt;code&gt;Time&lt;/code&gt;, &lt;code&gt;Uuid&lt;/code&gt;, and &lt;code&gt;Bytes&lt;/code&gt;, known without a declaration, as &lt;code&gt;Error&lt;/code&gt; is.&lt;/p&gt;
&lt;p&gt;The two official packages follow it. varyk-sql 0.3.0 drops sqlx&#39;s &lt;code&gt;Any&lt;/code&gt; driver for the concrete SQLite, Postgres, and MySQL pools, so the three types are native columns. varyk-http 0.2.0 reads a &lt;code&gt;Time&lt;/code&gt; or a &lt;code&gt;Uuid&lt;/code&gt; from a route, and sends and receives bytes: request and response bodies, uploads, binary WebSocket messages, and the client&#39;s bodies. Both need Varyk 0.8, and Varyk 0.8 needs them, since a program and its packages share one &lt;code&gt;varyk-std&lt;/code&gt;. With them, milestones 5b4 and 5c are done, and milestone 5&#39;s bar is met.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Time&lt;/code&gt;.&lt;/strong&gt; One point in time in UTC, to the microsecond, from the year 0000 to the year 9999. &lt;code&gt;Time::now()&lt;/code&gt; reads the clock. &lt;code&gt;Time::from_iso(text)&lt;/code&gt; and &lt;code&gt;text.parse()&lt;/code&gt; read RFC 3339 text, &lt;code&gt;2026-10-07T12:00:00Z&lt;/code&gt;, or one with an offset, which is taken to UTC; &lt;code&gt;Time::from_unix(seconds)&lt;/code&gt; and &lt;code&gt;Time::from_unix_micros(n)&lt;/code&gt; read a Unix time. &lt;code&gt;to_iso&lt;/code&gt;, &lt;code&gt;to_unix&lt;/code&gt;, and &lt;code&gt;to_unix_micros&lt;/code&gt; go the other way, and &lt;code&gt;{}&lt;/code&gt; prints what &lt;code&gt;to_iso&lt;/code&gt; writes. &lt;code&gt;t.add_seconds(n)&lt;/code&gt; and &lt;code&gt;t.seconds_since(u)&lt;/code&gt; do the arithmetic, in whole seconds; &lt;code&gt;+&lt;/code&gt; on a &lt;code&gt;Time&lt;/code&gt; is an error. Times compare with &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, and the rest, a later time being the greater, and a &lt;code&gt;Vec&amp;lt;Time&amp;gt;&lt;/code&gt; sorts, earliest first. Microseconds are what a Postgres &lt;code&gt;timestamptz&lt;/code&gt; and a MySQL &lt;code&gt;datetime(6)&lt;/code&gt; hold, so a time read back from the database equals the one written. No call of &lt;code&gt;Time&lt;/code&gt; stops the program: each one that can leave the range, &lt;code&gt;add_seconds&lt;/code&gt; among them, gives a &lt;code&gt;Result&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Uuid&lt;/code&gt;.&lt;/strong&gt; A 128-bit id. &lt;code&gt;Uuid::new()&lt;/code&gt; makes a version 7, time-ordered, which keeps a primary key index compact; &lt;code&gt;Uuid::v7()&lt;/code&gt; is the same, and &lt;code&gt;Uuid::v4()&lt;/code&gt; makes a random one. A version 7 id holds the millisecond it was made in, readable by anyone who has the id, so a service that publishes ids and does not want their creation times known makes them with &lt;code&gt;Uuid::v4()&lt;/code&gt;. &lt;code&gt;text.parse()&lt;/code&gt; reads the 36-character form with hyphens, in either case, and &lt;code&gt;{}&lt;/code&gt; writes it in lower case. Ids compare with &lt;code&gt;==&lt;/code&gt; and &lt;code&gt;!=&lt;/code&gt;, and a &lt;code&gt;Uuid&lt;/code&gt; is a &lt;code&gt;HashMap&lt;/code&gt; key; ids have no order.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Bytes&lt;/code&gt;.&lt;/strong&gt; An immutable run of bytes: like a struct, a parameter borrows it, a field owns it, and &lt;code&gt;let c = b&lt;/code&gt; moves it. &lt;code&gt;Bytes::from_text&lt;/code&gt; and &lt;code&gt;Bytes::from_base64&lt;/code&gt; make one, &lt;code&gt;to_text&lt;/code&gt; and &lt;code&gt;to_base64&lt;/code&gt; read it, and &lt;code&gt;len&lt;/code&gt; and &lt;code&gt;is_empty&lt;/code&gt; measure it. &lt;code&gt;.clone()&lt;/code&gt; gives a second &lt;code&gt;Bytes&lt;/code&gt; that shares the first one&#39;s buffer, with no byte copied. Bytes have no one printed form, so &lt;code&gt;{}&lt;/code&gt; on a &lt;code&gt;Bytes&lt;/code&gt; is an error whose note names &lt;code&gt;to_text&lt;/code&gt; and &lt;code&gt;to_base64&lt;/code&gt;, and the &lt;code&gt;Err&lt;/code&gt; of &lt;code&gt;from_base64&lt;/code&gt; or &lt;code&gt;to_text&lt;/code&gt; says what is wrong without repeating the bytes, which can be a whole request body.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where they go.&lt;/strong&gt; All three go through JSON, where a &lt;code&gt;Time&lt;/code&gt; is RFC 3339 text, a &lt;code&gt;Uuid&lt;/code&gt; its text with hyphens, and a &lt;code&gt;Bytes&lt;/code&gt; standard base64 with padding; through &lt;code&gt;assert_eq&lt;/code&gt;, and &lt;code&gt;==&lt;/code&gt; and &lt;code&gt;.clone()&lt;/code&gt; on a struct that holds them; as the values after a query; and in the signatures of a &lt;code&gt;.rs&lt;/code&gt; facade. &lt;code&gt;Time&lt;/code&gt; and &lt;code&gt;Uuid&lt;/code&gt; also go through &lt;code&gt;env::parse&lt;/code&gt;, &lt;code&gt;parse&lt;/code&gt;, &lt;code&gt;{}&lt;/code&gt;, and a route&#39;s path and query parameters, where text that does not read as the type is a 400 and the handler is not called. The compiler&#39;s new example, &lt;code&gt;records&lt;/code&gt;, puts the three in one struct:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Upload&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Uuid&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    at: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Time&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    data: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Bytes&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; first_upload&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Upload&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Uuid&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;0192F0C4-7A3E-7B5C-9D1E-2F3A4B5C6D7E&amp;quot;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; at &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Time&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;from_iso&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;2026-10-07T12:00:00+02:00&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Upload&lt;/span&gt;&lt;span&gt; { id: id, at: at, data: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Bytes&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;from_text&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;hello, world&amp;quot;&lt;/span&gt;&lt;span&gt;) })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// Writes `upload` as JSON, reads it back, and compares the two.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; report&lt;/span&gt;&lt;span&gt;(upload: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Upload&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; at &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, upload.id, upload.at);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; expires &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; upload.at.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;add_seconds&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;3600&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;expires at &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; seconds later&amp;quot;&lt;/span&gt;&lt;span&gt;, expires, expires.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;seconds_since&lt;/span&gt;&lt;span&gt;(upload.at));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; json::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;stringify&lt;/span&gt;&lt;span&gt;(upload);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, text);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; back: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Upload&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; json::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;(text)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(back &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span&gt; upload)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The whole program, on the &lt;a href=&quot;/learn/examples/#records&quot;&gt;examples page&lt;/a&gt;, prints:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0192f0c4-7a3e-7b5c-9d1e-2f3a4b5c6d7e at 2026-10-07T10:00:00Z&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;expires at 2026-10-07T11:00:00Z, 3600 seconds later&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&amp;quot;id&amp;quot;:&amp;quot;0192f0c4-7a3e-7b5c-9d1e-2f3a4b5c6d7e&amp;quot;,&amp;quot;at&amp;quot;:&amp;quot;2026-10-07T10:00:00Z&amp;quot;,&amp;quot;data&amp;quot;:&amp;quot;aGVsbG8sIHdvcmxk&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;read back the same: true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hello, world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;aGVsbG8sIHdvcmxk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;a new upload has its own id: true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;`42` is not a Uuid like 01890a5d-ac96-774b-bcce-b302099a8057&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;`2026-10-07 12:00` is not a time like 2026-10-07T12:00:00Z&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Facades.&lt;/strong&gt; A &lt;code&gt;.rs&lt;/code&gt; function, method, or &lt;code&gt;pub&lt;/code&gt; field names the three by their full paths: &lt;code&gt;varyk_std::Time&lt;/code&gt; and &lt;code&gt;varyk_std::Uuid&lt;/code&gt;, copied as numbers are, &lt;code&gt;&amp;amp;varyk_std::Bytes&lt;/code&gt; for bytes it only reads, and &lt;code&gt;varyk_std::Bytes&lt;/code&gt; for bytes it takes. An imported enum may hold them in its variants, which is how varyk-http&#39;s WebSocket message carries a binary message.&lt;/p&gt;
&lt;p&gt;There is no new diagnostic code: the existing ones gain cases, such as V0113 for a type named &lt;code&gt;Time&lt;/code&gt;, V0200 for &lt;code&gt;&amp;lt;&lt;/code&gt; on a &lt;code&gt;Uuid&lt;/code&gt;, V0203 for &lt;code&gt;{}&lt;/code&gt; on a &lt;code&gt;Bytes&lt;/code&gt;, and V0219 for a &lt;code&gt;Bytes&lt;/code&gt; path parameter. The &lt;a href=&quot;/learn/reference/#time-ids-and-bytes&quot;&gt;reference&lt;/a&gt; has every call, and the &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;error codes&lt;/a&gt; the full table.&lt;/p&gt;
&lt;h2 id=&quot;varyk-sql-0-3-0&quot;&gt;varyk-sql 0.3.0&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql&quot;&gt;varyk-sql&lt;/a&gt; 0.3.0 is on crates.io. sqlx&#39;s &lt;code&gt;Any&lt;/code&gt; driver, which served the three databases through one pool, has no date or uuid kind, so 0.3 holds one of the concrete pools, chosen from the URL&#39;s scheme as before, each behind its cargo feature. &lt;code&gt;connect&lt;/code&gt;, &lt;code&gt;Pool&lt;/code&gt;, &lt;code&gt;Tx&lt;/code&gt;, and their calls are unchanged. The README&#39;s first service now stores a time:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    created_at: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Time&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; load&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; config: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; env::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;connect&lt;/span&gt;&lt;span&gt;(config.database_url).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;migrate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;migrations&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name, created_at) values (?, ?)&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Time&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;now&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select id, name, created_at from users&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Config&lt;/code&gt; reads &lt;code&gt;DATABASE_URL&lt;/code&gt; from the environment, and &lt;code&gt;varyk run&lt;/code&gt; prints &lt;code&gt;1 Ada&lt;/code&gt; and the time the row was added. A &lt;code&gt;Time&lt;/code&gt;, a &lt;code&gt;Uuid&lt;/code&gt;, and a &lt;code&gt;Bytes&lt;/code&gt; each go into a column of their own, and back, with no cast in the query:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Database&lt;/th&gt;&lt;th&gt;&lt;code&gt;Time&lt;/code&gt;&lt;/th&gt;&lt;th&gt;&lt;code&gt;Uuid&lt;/code&gt;&lt;/th&gt;&lt;th&gt;&lt;code&gt;Bytes&lt;/code&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Postgres&lt;/td&gt;&lt;td&gt;&lt;code&gt;timestamptz&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;uuid&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;bytea&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;MySQL&lt;/td&gt;&lt;td&gt;&lt;code&gt;datetime(6)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;char(36)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;blob&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;SQLite&lt;/td&gt;&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;blob&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;SQLite has no time type, so varyk-sql writes a &lt;code&gt;Time&lt;/code&gt; there as text of a fixed width, always with six fraction digits, so that &lt;code&gt;order by&lt;/code&gt; and &lt;code&gt;&amp;lt;&lt;/code&gt; in SQL put times in the order Varyk does. A &lt;code&gt;Uuid&lt;/code&gt; is its 36-character text on MySQL and SQLite, readable in a SQL shell as in JSON. A Postgres time is read from its raw microseconds, so &lt;code&gt;infinity&lt;/code&gt; in a column is an &lt;code&gt;Error&lt;/code&gt;, not a crash. On Postgres:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// Postgres; SQLite takes `$1` as well as `?`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name, created_at) values ($1, $2) returning id&amp;quot;&lt;/span&gt;&lt;span&gt;, name, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Time&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;now&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Two things a program had to write go. A &lt;code&gt;None&lt;/code&gt; on Postgres is now a &lt;code&gt;NULL&lt;/code&gt; with no type, which takes its type from where the parameter is first used, so &lt;code&gt;set done = $1&lt;/code&gt; needs no cast; only a parameter first used where nothing gives it a type, as in &lt;code&gt;$1 is null&lt;/code&gt;, still needs one. And MySQL&#39;s unsigned integers, &lt;code&gt;tinyint&lt;/code&gt;, &lt;code&gt;mediumint&lt;/code&gt;, and &lt;code&gt;boolean&lt;/code&gt; columns read with no cast; under &lt;code&gt;Any&lt;/code&gt;, an unsigned value at or above 2^31 in an &lt;code&gt;int unsigned&lt;/code&gt; read back as a negative number. A field that refuses a column says so by the column&#39;s name, never by its value. The README&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#column-types&quot;&gt;column types&lt;/a&gt; have the rest.&lt;/p&gt;
&lt;h2 id=&quot;varyk-http-0-2-0&quot;&gt;varyk-http 0.2.0&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http&quot;&gt;varyk-http&lt;/a&gt; 0.2.0 is on crates.io. Its first service, and its &lt;code&gt;users&lt;/code&gt; demo, store &lt;code&gt;created_at&lt;/code&gt; as a &lt;code&gt;Time&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; create_user&lt;/span&gt;&lt;span&gt;(user: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;NewUser&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; user.name.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_empty&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;bad_request&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;a user needs a name&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; created_at &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Time&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;now&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; state.db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name, created_at) values (?, ?) returning id&amp;quot;&lt;/span&gt;&lt;span&gt;, user.name, created_at).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;json&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt; { id: id, name: user.name.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;(), created_at: created_at });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;201&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;location&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users/&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, id));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(r)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with &lt;code&gt;created_at: Time&lt;/code&gt; on &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;created_at text not null&lt;/code&gt; in the migration. Every read gives the time back:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -i -H&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;x-api-key: dev-key&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -d&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;{&amp;quot;name&amp;quot;:&amp;quot;Ada&amp;quot;}&amp;#39; 127.0.0.1:3000/users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;# 201, location: /users/1,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;# {&amp;quot;id&amp;quot;:1,&amp;quot;name&amp;quot;:&amp;quot;Ada&amp;quot;,&amp;quot;created_at&amp;quot;:&amp;quot;2026-10-07T12:00:00.123456Z&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -H&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;x-api-key: dev-key&amp;#39; 127.0.0.1:3000/users/1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;# {&amp;quot;id&amp;quot;:1,&amp;quot;name&amp;quot;:&amp;quot;Ada&amp;quot;,&amp;quot;created_at&amp;quot;:&amp;quot;2026-10-07T12:00:00.123456Z&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -H&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;x-api-key: dev-key&amp;#39; 127.0.0.1:3000/users/2&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;   # 404 {&amp;quot;error&amp;quot;:&amp;quot;not found&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; 127.0.0.1:3000/users&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;                             # 401&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; 127.0.0.1:3000/health&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;                            # &amp;quot;ok&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Times and ids in routes.&lt;/strong&gt; A path or query parameter may be a &lt;code&gt;Time&lt;/code&gt; or a &lt;code&gt;Uuid&lt;/code&gt;, and a query parameter an &lt;code&gt;Option&lt;/code&gt; of one. A &lt;code&gt;Time&lt;/code&gt; reads as &lt;code&gt;Time::from_iso&lt;/code&gt; reads it, and a &lt;code&gt;Uuid&lt;/code&gt; in its 36-character form; anything else is a 400 naming the parameter. In a query string a &lt;code&gt;+&lt;/code&gt; reads as a space, as forms encode it, so an offset is sent as &lt;code&gt;%2B&lt;/code&gt;: &lt;code&gt;?since=2026-10-07T12:00:00%2B02:00&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bytes in and out.&lt;/strong&gt; Each bytes call has a name of its own, beside the text call it matches, since Varyk has no overloading and the server&#39;s &lt;code&gt;Response&lt;/code&gt; is also what the client gives back:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Call&lt;/th&gt;&lt;th&gt;Gives&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;req.body_bytes()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the request body as it came, with no copy&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;http::Response::bytes(b, content_type)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;a 200 with the body &lt;code&gt;b&lt;/code&gt;, that &lt;code&gt;content-type&lt;/code&gt;, and &lt;code&gt;x-content-type-options: nosniff&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;r.body_bytes()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;a response&#39;s body with no UTF-8 check, in a test or from the client&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;part.bytes().await&lt;/code&gt;, &lt;code&gt;part.content_type()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;an uploaded part&#39;s content as it came, and the content type the client declared, not checked&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ws.recv_message().await&lt;/code&gt;, &lt;code&gt;ws.send_bytes(b).await&lt;/code&gt;&lt;/td&gt;&lt;td&gt;WebSocket messages, text or binary&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;client.post_bytes(url, b, content_type)&lt;/code&gt;, &lt;code&gt;client.put_bytes(url, b, content_type)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;a request with &lt;code&gt;b&lt;/code&gt; as its body&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;req.set_body_bytes(b)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;a body of bytes, for a request sent with &lt;code&gt;app.request&lt;/code&gt; in a test&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A content type is always written, so no binary body goes out without a declared type. A &lt;code&gt;Bytes&lt;/code&gt; given to the JSON calls, or returned by a handler, is sent as a JSON string of base64, as any value is. &lt;code&gt;ws.recv()&lt;/code&gt; stays text, and still closes the connection on a binary message; a handler that takes binary messages asks for them by name:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; echo&lt;/span&gt;&lt;span&gt;(ws: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;WebSocket&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    while let&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Some&lt;/span&gt;&lt;span&gt;(message) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; ws.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;recv_message&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        match&lt;/span&gt;&lt;span&gt; message {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            http::live::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Message&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Text&lt;/span&gt;&lt;span&gt;(text) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; ws.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;send&lt;/span&gt;&lt;span&gt;(text).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            http::live::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Message&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Binary&lt;/span&gt;&lt;span&gt;(b) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; ws.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;send_bytes&lt;/span&gt;&lt;span&gt;(b).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;empty&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The README&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http#live-connections-and-uploads&quot;&gt;live connections and uploads&lt;/a&gt; section has the rest.&lt;/p&gt;
&lt;h2 id=&quot;for-rust-readers&quot;&gt;For Rust readers&lt;/h2&gt;
&lt;p&gt;In the generated Rust the three are &lt;code&gt;::varyk_std::Time&lt;/code&gt;, &lt;code&gt;::varyk_std::Uuid&lt;/code&gt;, and &lt;code&gt;::varyk_std::Bytes&lt;/code&gt;, held by &lt;code&gt;varyk-std&lt;/code&gt; on the crates &lt;code&gt;time&lt;/code&gt;, &lt;code&gt;uuid&lt;/code&gt;, &lt;code&gt;bytes&lt;/code&gt;, and &lt;code&gt;base64&lt;/code&gt;. &lt;code&gt;Time&lt;/code&gt; and &lt;code&gt;Uuid&lt;/code&gt; are &lt;code&gt;Copy&lt;/code&gt; and passed by value, as numbers are. &lt;code&gt;varyk-std&lt;/code&gt; builds every &lt;code&gt;Bytes&lt;/code&gt; in the &lt;code&gt;bytes&lt;/code&gt; crate&#39;s shared form, so the compiler hands a &lt;code&gt;Bytes&lt;/code&gt; over as a trailing value by adding one to a reference count, allocating nothing, and axum&#39;s request body reaches &lt;code&gt;req.body_bytes()&lt;/code&gt; without a copy. The compiler still inserts exactly two allocations, a string literal placed into an owned slot and a string passed as a trailing value, and &lt;code&gt;--emit-rust&lt;/code&gt; shows both.&lt;/p&gt;
&lt;h2 id=&quot;what-is-not-yet&quot;&gt;What is not yet&lt;/h2&gt;
&lt;p&gt;From the language: a calendar date, a time of day, a duration type, time zones and local time, formatting a &lt;code&gt;Time&lt;/code&gt; by a pattern, and a monotonic clock; ordering &lt;code&gt;Uuid&lt;/code&gt;s, the nil id, and other versions; indexing, slicing, or building &lt;code&gt;Bytes&lt;/code&gt; piece by piece, and &lt;code&gt;Bytes&lt;/code&gt; from a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt;; &lt;code&gt;Bytes&lt;/code&gt; in &lt;code&gt;env::parse&lt;/code&gt;; &lt;code&gt;Time&lt;/code&gt; or &lt;code&gt;Bytes&lt;/code&gt; as a map key; and a handler parameter bound to the raw body. From varyk-sql: &lt;code&gt;numeric&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt; of day, interval, and array columns without a cast, a &lt;code&gt;Uuid&lt;/code&gt; written as 16 bytes, and session time zones other than UTC. From varyk-http: a bytes body sent in pieces, a &lt;code&gt;patch&lt;/code&gt; with a bytes body, and checking a part&#39;s declared content type against its content. The &lt;a href=&quot;/learn/reference/#not-in-milestone-5c&quot;&gt;reference&lt;/a&gt; lists the language&#39;s cuts, and the open questions, such as whether Varyk should have a &lt;code&gt;Date&lt;/code&gt; or a &lt;code&gt;Duration&lt;/code&gt;, are in the compiler&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/blob/main/docs/open-questions.md&quot;&gt;open-questions.md&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;
&lt;p&gt;The three crates, &lt;code&gt;varyk&lt;/code&gt;, &lt;code&gt;varyk-syntax&lt;/code&gt;, and &lt;code&gt;varyk-std&lt;/code&gt;, are released together as 0.8.0, and two things in it are breaking. &lt;code&gt;Time&lt;/code&gt;, &lt;code&gt;Uuid&lt;/code&gt;, and &lt;code&gt;Bytes&lt;/code&gt; are now reserved names, as &lt;code&gt;Error&lt;/code&gt; is: a program that declares a type, an enum, or a module by one of them renames it, and &lt;code&gt;varyk check&lt;/code&gt; reports V0113 until it does. And &lt;code&gt;varyk_std::Value&lt;/code&gt;, the type of the values after a facade&#39;s other arguments, has three new variants, so a &lt;code&gt;.rs&lt;/code&gt; facade that matches on a &lt;code&gt;Value&lt;/code&gt; needs arms for them. After &lt;code&gt;cargo install varyk --locked&lt;/code&gt;, run &lt;code&gt;varyk check&lt;/code&gt; in a package, and it says what to change: the &lt;code&gt;varyk-std&lt;/code&gt; line in &lt;code&gt;Cargo.toml&lt;/code&gt;, or &lt;code&gt;cargo update -p varyk-std&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A program that uses varyk-sql or varyk-http moves to their new releases at the same time: in &lt;code&gt;Cargo.toml&lt;/code&gt;, change the version on the &lt;code&gt;http&lt;/code&gt; line to &lt;code&gt;&quot;0.2.0&quot;&lt;/code&gt; and on the &lt;code&gt;sql&lt;/code&gt; line to &lt;code&gt;&quot;0.3.0&quot;&lt;/code&gt;. Running &lt;code&gt;varyk add http sql&lt;/code&gt; again does not do it, since &lt;code&gt;cargo add&lt;/code&gt; keeps the version of a dependency the manifest already lists. Until then, &lt;code&gt;varyk check&lt;/code&gt; reports V0404, since varyk-sql 0.2 and varyk-http 0.1 need &lt;code&gt;varyk-std&lt;/code&gt; 0.7. varyk-sql&#39;s calls are unchanged, and most of the casts 0.2 asked for are no longer needed.&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;varyk&lt;/th&gt;&lt;th&gt;varyk-sql&lt;/th&gt;&lt;th&gt;varyk-http&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0.8&lt;/td&gt;&lt;td&gt;0.3&lt;/td&gt;&lt;td&gt;0.2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.7&lt;/td&gt;&lt;td&gt;0.2&lt;/td&gt;&lt;td&gt;0.1&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk --locked&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there to &lt;a href=&quot;/learn/getting-started/#a-first-service&quot;&gt;a first service&lt;/a&gt; on HTTP and a database, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts. The READMEs of &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http#readme&quot;&gt;varyk-http&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#readme&quot;&gt;varyk-sql&lt;/a&gt; are the full documentation of the packages.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 6 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;: tooling and beyond, &lt;code&gt;varyk fmt&lt;/code&gt;, a language server, nested modules in &lt;code&gt;.rs&lt;/code&gt; files, Rust tuple and unit structs imported from &lt;code&gt;.rs&lt;/code&gt; files, &lt;code&gt;Debug&lt;/code&gt; on imported Rust structs, and a decision on a native backend. Beside it, as their own work, &lt;code&gt;varyk-mongo&lt;/code&gt; and &lt;code&gt;varyk-redis&lt;/code&gt;, the next packages, and an agent evaluation: the examples written by a model from the language reference alone, with pass rates published, before any page claims that agents write Varyk well. Nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Store a time, an id, or an upload with it, and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>varyk-http 0.1.0: HTTP for Varyk</title>
        <published>2026-10-06T14:00:00+02:00</published>
        <updated>2026-10-06T14:00:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-http-0-1-0/"/>
        <id>https://varyk.com/blog/varyk-http-0-1-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-http-0-1-0/">&lt;p&gt;varyk-http 0.1.0 is on crates.io. It is the official Varyk package for HTTP: a server on &lt;a rel=&quot;external&quot; href=&quot;https://github.com/tokio-rs/axum&quot;&gt;axum&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://github.com/tower-rs/tower-http&quot;&gt;tower-http&lt;/a&gt;, and a client on &lt;a rel=&quot;external&quot; href=&quot;https://github.com/seanmonstar/reqwest&quot;&gt;reqwest&lt;/a&gt;. It covers what an ordinary production API needs and nothing more: routes the compiler checks, hooks, safe defaults, errors that never leak, WebSockets, server-sent events, uploads, a client, metrics, and tests without a port. It lives in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http&quot;&gt;its own repository&lt;/a&gt;, and its &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http#readme&quot;&gt;README&lt;/a&gt; is the full documentation.&lt;/p&gt;
&lt;p&gt;varyk-http ships with &lt;a href=&quot;/blog/varyk-0-7-0/&quot;&gt;Varyk 0.7.0&lt;/a&gt; because it needs that release&#39;s compiler side: the compiler knows this one package by name, checks every route against its handler, and writes the small adapter that calls the package for each route. The package is a &lt;code&gt;.rs&lt;/code&gt; facade over axum, tower-http, and reqwest, with its error constructors and its tests written in Varyk; the generated program never names axum, and the first service below writes no Rust. varyk-http 0.1 works with Varyk 0.7, and each minor Varyk release is followed by a varyk-http release, since a program and its packages must resolve to one &lt;code&gt;varyk-std&lt;/code&gt;. &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql&quot;&gt;varyk-sql&lt;/a&gt; 0.2.0 ships alongside for the same reason, with nothing else changed.&lt;/p&gt;
&lt;h2 id=&quot;adding-it&quot;&gt;Adding it&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; install varyk&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; --version&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;^0.7&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; --locked&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; init users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; add http sql&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;varyk add http sql&lt;/code&gt; adds varyk-http as &lt;code&gt;http&lt;/code&gt; and varyk-sql as &lt;code&gt;sql&lt;/code&gt;, so code writes &lt;code&gt;http::App&lt;/code&gt; and &lt;code&gt;sql::connect&lt;/code&gt;. varyk-sql&#39;s default driver, SQLite, is compiled from C on the first build, which needs a C compiler; its &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql&quot;&gt;README&lt;/a&gt; has the rest.&lt;/p&gt;
&lt;h2 id=&quot;a-first-service&quot;&gt;A first service&lt;/h2&gt;
&lt;p&gt;A users API on a database, behind an API key, in one file. &lt;code&gt;src/main.vr&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Config&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    database_url: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    api_key: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[default(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;3000&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    port: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u16&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[default(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;127.0.0.1&amp;quot;&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    address: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; NewUser&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; State&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db: sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Pool&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    api_key: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; list_users&lt;/span&gt;&lt;span&gt;(state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    state.db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select id, name from users order by id&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; get_user&lt;/span&gt;&lt;span&gt;(id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    state.db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;first&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select id, name from users where id = ?&amp;quot;&lt;/span&gt;&lt;span&gt;, id).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; create_user&lt;/span&gt;&lt;span&gt;(user: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;NewUser&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; user.name.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_empty&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;bad_request&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;a user needs a name&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; state.db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name) values (?) returning id&amp;quot;&lt;/span&gt;&lt;span&gt;, user.name).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;json&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt; { id: id, name: user.name.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;() });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;201&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;location&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users/&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, id));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(r)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; delete_user&lt;/span&gt;&lt;span&gt;(id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; deleted &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; state.db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;delete from users where id = ?&amp;quot;&lt;/span&gt;&lt;span&gt;, id).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; deleted &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 0&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;not_found&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;no such user&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;empty&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; health&lt;/span&gt;&lt;span&gt;(state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; _ok &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; state.db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select 1&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; check_key&lt;/span&gt;&lt;span&gt;(req: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; req.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;x-api-key&amp;quot;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Some&lt;/span&gt;&lt;span&gt;(key) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Ok&lt;/span&gt;&lt;span&gt;(key &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span&gt; state.api_key),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        None&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;unauthorized&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;an x-api-key header is needed&amp;quot;&lt;/span&gt;&lt;span&gt;)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; open_db&lt;/span&gt;&lt;span&gt;(url: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Pool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;connect&lt;/span&gt;&lt;span&gt;(url).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;migrate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;migrations&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(db)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; build_app&lt;/span&gt;&lt;span&gt;(state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;App&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; app &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;App&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(state.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/health&amp;quot;&lt;/span&gt;&lt;span&gt;, health);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users&amp;quot;&lt;/span&gt;&lt;span&gt;, list_users);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users/&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{id}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, get_user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;post&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users&amp;quot;&lt;/span&gt;&lt;span&gt;, create_user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;delete&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users/&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{id}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, delete_user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;before_on&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users&amp;quot;&lt;/span&gt;&lt;span&gt;, check_key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; start&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; config: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; env::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; open_db&lt;/span&gt;&lt;span&gt;(config.database_url).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; app &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; build_app&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span&gt; { db: db, api_key: config.api_key.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;() }));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_address&lt;/span&gt;&lt;span&gt;(config.address);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;serve&lt;/span&gt;&lt;span&gt;(config.port).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if let&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; start&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        log::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, e);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;migrations/0001_users.sql&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;create table&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; users&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;integer primary key&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    name text not null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DATABASE_URL&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;sqlite::memory:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;API_KEY&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;dev-key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;varyk run&lt;/code&gt; serves on &lt;code&gt;127.0.0.1:3000&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -i -H&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;x-api-key: dev-key&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -d&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;{&amp;quot;name&amp;quot;:&amp;quot;Ada&amp;quot;}&amp;#39; 127.0.0.1:3000/users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;# 201, location: /users/1, {&amp;quot;id&amp;quot;:1,&amp;quot;name&amp;quot;:&amp;quot;Ada&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -H&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;x-api-key: dev-key&amp;#39; 127.0.0.1:3000/users/1&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;   # {&amp;quot;id&amp;quot;:1,&amp;quot;name&amp;quot;:&amp;quot;Ada&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; -H&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;#39;x-api-key: dev-key&amp;#39; 127.0.0.1:3000/users/2&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;   # 404 {&amp;quot;error&amp;quot;:&amp;quot;not found&amp;quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; 127.0.0.1:3000/users&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;                             # 401&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;curl&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; 127.0.0.1:3000/health&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;                            # &amp;quot;ok&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same program, with its tests, is the package&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http/tree/main/demo/users&quot;&gt;&lt;code&gt;demo/users&lt;/code&gt;&lt;/a&gt;. A handler is an ordinary &lt;code&gt;async fn&lt;/code&gt;. Its parameters are bound by name to the path (&lt;code&gt;{id}&lt;/code&gt;) and the query string, and by type to the JSON body, the shared state, and the request; its return value is the response: a value is JSON with 200, &lt;code&gt;None&lt;/code&gt; is 404, nothing is 204, and an &lt;code&gt;http::Response&lt;/code&gt; is sent as built. &lt;code&gt;varyk check&lt;/code&gt; checks every route against its handler before anything builds. A path or query value that does not parse as its type, a missing query value, and a body that is not JSON of its type are each a 400 naming the parameter, and the handler is not called. The &lt;a href=&quot;/blog/varyk-0-7-0/#what-is-in-it&quot;&gt;Varyk 0.7.0 post&lt;/a&gt; and the &lt;a href=&quot;/learn/reference/#http&quot;&gt;language reference&lt;/a&gt; have the rules.&lt;/p&gt;
&lt;h2 id=&quot;safe-defaults&quot;&gt;Safe defaults&lt;/h2&gt;
&lt;p&gt;The settings are calls on the app before &lt;code&gt;serve&lt;/code&gt;:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Call&lt;/th&gt;&lt;th&gt;Default&lt;/th&gt;&lt;th&gt;Meaning&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.set_address(addr)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&quot;127.0.0.1&quot;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the IP address to listen on; &lt;code&gt;&quot;0.0.0.0&quot;&lt;/code&gt; in a container&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.set_body_limit(bytes)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;2 MiB&lt;/td&gt;&lt;td&gt;a larger request body is a 413&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.set_timeout(ms)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;30 000&lt;/td&gt;&lt;td&gt;a request that takes longer is a 503&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.set_shutdown_grace(ms)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;30 000&lt;/td&gt;&lt;td&gt;on SIGTERM or ctrl-c, how long requests in flight have to finish&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.set_idle_timeout(ms)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;75 000&lt;/td&gt;&lt;td&gt;how long a connection may wait for a request&#39;s headers, idle between kept-alive requests or still sending them, before it is closed&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.set_max_in_flight(n)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;none&lt;/td&gt;&lt;td&gt;beyond &lt;code&gt;n&lt;/code&gt; requests at once, a 503 &lt;code&gt;{&quot;error&quot;:&quot;server busy&quot;}&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.allow_origin(origin)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;none&lt;/td&gt;&lt;td&gt;adds one CORS origin; &lt;code&gt;&quot;*&quot;&lt;/code&gt; allows any&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.compress()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;off&lt;/td&gt;&lt;td&gt;gzip for responses whose client accepts it&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;app.metrics(path)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;off&lt;/td&gt;&lt;td&gt;Prometheus text at &lt;code&gt;path&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The server listens on &lt;code&gt;127.0.0.1&lt;/code&gt; until the program sets an address, so a service run on a laptop is not open to its network; &lt;code&gt;serve&lt;/code&gt; says so as it starts, &lt;code&gt;listening on http://127.0.0.1:3000 (set_address(&quot;0.0.0.0&quot;) to accept outside connections)&lt;/code&gt;. A body limit, a request timeout, and an idle timeout are on without being asked; each bounds one request or connection, not the service as a whole, and the idle timeout means a client that sends its headers slowly or not at all cannot hold connections open. There is no limit on requests in flight unless &lt;code&gt;set_max_in_flight&lt;/code&gt; sets one, since memory is the platform&#39;s to manage; that limit is load shedding, a 503 beyond a number of requests at once, for a service that wants it. CORS is off until an origin is allowed, and once on it never allows credentials. Compression is off too: compressing a secret beside text an attacker chose leaks it through the length.&lt;/p&gt;
&lt;p&gt;A setting with a value that cannot work, a limit of 0 or an address that is not an IP address, makes &lt;code&gt;serve&lt;/code&gt; an &lt;code&gt;Err&lt;/code&gt; naming the setting, and every &lt;code&gt;app.request&lt;/code&gt; a 500, rather than a panic. On SIGTERM or ctrl-c, &lt;code&gt;serve&lt;/code&gt; stops accepting, gives requests in flight the shutdown grace, and gives &lt;code&gt;Ok(true)&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;nothing-internal-reaches-a-client&quot;&gt;Nothing internal reaches a client&lt;/h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Call&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;http::bad_request(text)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;400&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;http::unauthorized(text)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;401&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;http::forbidden(text)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;403&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;http::not_found(text)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;404&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;http::conflict(text)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;409&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;http::error(status, text)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;status&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;An &lt;code&gt;Err&lt;/code&gt; from a handler or a &lt;code&gt;before&lt;/code&gt; hook with a status from 400 to 599 is sent with that status and &lt;code&gt;{&quot;error&quot;:&quot;&amp;lt;text&amp;gt;&quot;}&lt;/code&gt;: its text is written for the client. Any other error, one passed on with &lt;code&gt;?&lt;/code&gt; from a database call, say, or one with a status outside 400 to 599, is a 500 with the fixed body &lt;code&gt;{&quot;error&quot;:&quot;internal error&quot;}&lt;/code&gt;, and its message is logged with the method and path. A panic in a handler or a hook is the same fixed 500. So a database message, a file path, or a secret inside an error stays in the log.&lt;/p&gt;
&lt;p&gt;The package keeps input out of places it could do harm. &lt;code&gt;Response::file(dir, name)&lt;/code&gt; serves a file from a folder and refuses a name that is absolute, has an empty, &lt;code&gt;.&lt;/code&gt;, or &lt;code&gt;..&lt;/code&gt; part, has a part starting with &lt;code&gt;.&lt;/code&gt;, or leads outside the folder through a link, as a 404, as a missing file is, so a client cannot tell them apart. A header that is not valid HTTP, and a cookie name or value that could add attributes, make the response a 500 with the reason logged. &lt;code&gt;set_cookie&lt;/code&gt; writes &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt;, and &lt;code&gt;SameSite=Lax&lt;/code&gt;. Log lines carry the path still percent-encoded and without its query string, and a name or message a client chose is written escaped, so it cannot start a log line of its own.&lt;/p&gt;
&lt;h2 id=&quot;hooks-and-auth&quot;&gt;Hooks and auth&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; check_key&lt;/span&gt;&lt;span&gt;(req: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; req.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;x-api-key&amp;quot;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Some&lt;/span&gt;&lt;span&gt;(key) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Ok&lt;/span&gt;&lt;span&gt;(key &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span&gt; state.api_key),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        None&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;unauthorized&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;an x-api-key header is needed&amp;quot;&lt;/span&gt;&lt;span&gt;)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; stamp&lt;/span&gt;&lt;span&gt;(req: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;mut&lt;/span&gt;&lt;span&gt; res: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    res.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;x-served-by&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;users&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;app.before(f)&lt;/code&gt; runs &lt;code&gt;f&lt;/code&gt; before every route, &lt;code&gt;app.before_on(&quot;/admin&quot;, f)&lt;/code&gt; before the routes whose path, as the program wrote it, is &lt;code&gt;/admin&lt;/code&gt; or starts with &lt;code&gt;/admin/&lt;/code&gt; (not &lt;code&gt;/administrators&lt;/code&gt;), and &lt;code&gt;app.after(f)&lt;/code&gt; on every response the router makes. Each hook covers every route, wherever its line is, and hooks run in the order they were added. A &lt;code&gt;before&lt;/code&gt; hook gives &lt;code&gt;Ok(true)&lt;/code&gt; to let the request through, &lt;code&gt;Ok(false)&lt;/code&gt; for a 403 &lt;code&gt;{&quot;error&quot;:&quot;forbidden&quot;}&lt;/code&gt;, or an &lt;code&gt;Err&lt;/code&gt;, sent as above. Because &lt;code&gt;before_on&lt;/code&gt; tests the route the request matched, no spelling of a path reaches an &lt;code&gt;/admin&lt;/code&gt; route without its hook. &lt;code&gt;before&lt;/code&gt; hooks run after routing, so a request no route matches is a 404 without running any; a client can therefore tell a route that exists (refused by its hook, 401 or 403) from one that does not (404).&lt;/p&gt;
&lt;p&gt;A handler that needs the user calls a function of the program, &lt;code&gt;let user = current_user(req, state)?;&lt;/code&gt;. The first service compares its key with &lt;code&gt;==&lt;/code&gt;, which is not constant time; a production check compares in constant time in a facade function of the program or uses bearer tokens. The README has a Rust facade of the program over &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/jsonwebtoken&quot;&gt;jsonwebtoken&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/argon2&quot;&gt;argon2&lt;/a&gt; for tokens and password hashes, and the Varyk function that gives a refused token its 401. The package checks neither a body&#39;s &lt;code&gt;content-type&lt;/code&gt; nor a request&#39;s &lt;code&gt;Origin&lt;/code&gt;: against a cross-site request, the defence is the &lt;code&gt;SameSite=Lax&lt;/code&gt; cookie &lt;code&gt;set_cookie&lt;/code&gt; writes, and a service that takes cookies some other way checks &lt;code&gt;Origin&lt;/code&gt; in a &lt;code&gt;before&lt;/code&gt; hook.&lt;/p&gt;
&lt;h2 id=&quot;websockets-server-sent-events-and-uploads&quot;&gt;WebSockets, server-sent events, and uploads&lt;/h2&gt;
&lt;p&gt;A handler takes a WebSocket, an event stream, or a multipart form as a parameter, bound by type as the request is. A live handler returns nothing, or &lt;code&gt;Result&amp;lt;http::Response, Error&amp;gt;&lt;/code&gt; so that &lt;code&gt;?&lt;/code&gt; works on its calls; the response it returns is ignored, since the connection was already answered, and an &lt;code&gt;Err&lt;/code&gt; is logged. The connection closes when the handler returns.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; chat&lt;/span&gt;&lt;span&gt;(ws: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;WebSocket&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    while let&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Some&lt;/span&gt;&lt;span&gt;(text) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; ws.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;recv&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ws.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;send&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;you said: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, text)).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;empty&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with &lt;code&gt;app.get(&quot;/chat&quot;, chat);&lt;/code&gt;. Messages are text, and the package answers pings. A client&#39;s fault, a binary message, a malformed one, or one larger than the body limit, closes the connection with its code and makes &lt;code&gt;recv&lt;/code&gt; give &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; ticks&lt;/span&gt;&lt;span&gt;(events: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Sse&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    while&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 10&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        events.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;send_event&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;tick&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, i)).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        time::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;sleep&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1000&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        i &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;empty&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;events.send(text)&lt;/code&gt; sends one &lt;code&gt;data:&lt;/code&gt; event and &lt;code&gt;events.send_event(name, text)&lt;/code&gt; one with a name; the package sends a comment every 15 seconds while the handler is quiet, so proxies keep the connection open.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; upload_avatar&lt;/span&gt;&lt;span&gt;(id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, form: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Multipart&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    while let&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Some&lt;/span&gt;&lt;span&gt;(part) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; form.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;next&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        if&lt;/span&gt;&lt;span&gt; part.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;name&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;avatar&amp;quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            let&lt;/span&gt;&lt;span&gt; _written &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; part.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;save_to&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;uploads&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;.png&amp;quot;&lt;/span&gt;&lt;span&gt;, id)).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;empty&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with &lt;code&gt;app.post(&quot;/users/{id}/avatar&quot;, upload_avatar);&lt;/code&gt;. Save an upload under a name and extension the program chooses, as here, never under &lt;code&gt;part.file_name()&lt;/code&gt;, which is whatever the client sent. &lt;code&gt;save_to&lt;/code&gt; refuses a name by the rule of &lt;code&gt;Response::file&lt;/code&gt; and writes to a temporary file first, so a failed upload leaves nothing behind. What the handler reads counts against the body limit, and what it leaves unread is never read. Messages and parts are text and files until milestone 5c brings a bytes type.&lt;/p&gt;
&lt;h2 id=&quot;the-client-metrics-and-tests&quot;&gt;The client, metrics, and tests&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Forecast&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    summary: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; State&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    client: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Client&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; forecast&lt;/span&gt;&lt;span&gt;(state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Forecast&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; state.client.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;https://weather.example/today&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;status&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 200&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;502&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;the weather service did not answer&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;read_json&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; weather_client&lt;/span&gt;&lt;span&gt;(key: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Client&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; client &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Client&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    client.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;authorization&amp;quot;&lt;/span&gt;&lt;span&gt;, key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    client&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;client.get(url)&lt;/code&gt; and &lt;code&gt;client.delete(url)&lt;/code&gt;, and &lt;code&gt;post&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt;, and &lt;code&gt;patch&lt;/code&gt; with a body sent as JSON, each give &lt;code&gt;Result&amp;lt;http::Response, Error&amp;gt;&lt;/code&gt;. A response of any status is &lt;code&gt;Ok&lt;/code&gt;; an &lt;code&gt;Err&lt;/code&gt; is a response that could not be had, and its message names the scheme and host, never the path or query, which may hold a token. Redirects are followed only to the same scheme, host, and port, so a default header such as an API key never goes to a host the program did not name. The client uses rustls with built-in root certificates, so it works in a minimal container, with a 30-second timeout and a 10 MiB body limit by default. Make one at startup and keep it in the state; &lt;code&gt;client.clone()&lt;/code&gt; shares its connections.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app.metrics(&quot;/metrics&quot;)&lt;/code&gt; serves Prometheus text: &lt;code&gt;http_requests_total&lt;/code&gt; by method, route, and status, and &lt;code&gt;http_request_duration_seconds&lt;/code&gt;, a histogram by method and route. The route label is the route&#39;s pattern, &lt;code&gt;/users/{id}&lt;/code&gt;, never the path a client sent. The metrics path is open to anyone who can reach the service, so a service that listens beyond &lt;code&gt;127.0.0.1&lt;/code&gt; keeps it from the public at its proxy.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app.request(req).await&lt;/code&gt; runs one request through the same router, settings, and hooks as &lt;code&gt;serve&lt;/code&gt;, without a port, under &lt;code&gt;varyk test&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; test_app&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;App&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;connect_with&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;sqlite::memory:&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;migrate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;migrations&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;build_app&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span&gt; { db: db, api_key: &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;test-key&amp;quot;&lt;/span&gt;&lt;span&gt; })))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; creates_a_user&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; app &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;= match&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; test_app&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(app) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; app,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;            assert_eq&lt;/span&gt;&lt;span&gt;(e.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;message&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;no error&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; req &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    req.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;x-api-key&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;test-key&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    req.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_body&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;Ada&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;}&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;request&lt;/span&gt;&lt;span&gt;(req).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    assert_eq&lt;/span&gt;&lt;span&gt;(r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;status&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;201&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    assert_eq&lt;/span&gt;&lt;span&gt;(r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;location&amp;quot;&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Some&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users/1&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each &lt;code&gt;sqlite::memory:&lt;/code&gt; pool is a database of its own, so every test starts empty. An event stream&#39;s events are collected whole once its handler returns, so &lt;code&gt;r.body()&lt;/code&gt; gives them; a WebSocket route answers a 400, since no request &lt;code&gt;app.request&lt;/code&gt; sends is an upgrade. Run &lt;code&gt;varyk test&lt;/code&gt; from the package&#39;s folder, where &lt;code&gt;migrations&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt; are.&lt;/p&gt;
&lt;h2 id=&quot;in-production&quot;&gt;In production&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Configuration.&lt;/strong&gt; The port, the address, and secrets come from the environment with &lt;code&gt;env::parse&lt;/code&gt;, as the first service does: in development from &lt;code&gt;.env&lt;/code&gt;, which &lt;code&gt;varyk init&lt;/code&gt; keeps out of git.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Containers.&lt;/strong&gt; In a container the service listens on &lt;code&gt;0.0.0.0&lt;/code&gt;: the first service reads &lt;code&gt;ADDRESS&lt;/code&gt; and calls &lt;code&gt;set_address&lt;/code&gt; with it. The README has a &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http#production&quot;&gt;Dockerfile&lt;/a&gt; that builds with &lt;code&gt;varyk build --release&lt;/code&gt; on Debian 12 and copies the executable and &lt;code&gt;migrations/&lt;/code&gt; into a distroless image with &lt;code&gt;ADDRESS=0.0.0.0&lt;/code&gt;. On SIGTERM the service gives requests in flight the shutdown grace.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idle connections.&lt;/strong&gt; The service closes a connection that has sent no request for 75 seconds, so a load balancer or proxy in front must close its idle connections sooner, or an occasional request fails with a 502. AWS&#39;s Application Load Balancer and nginx&#39;s upstream keep-alive default to 60 seconds, which is sooner; behind Google Cloud&#39;s Application Load Balancers, which keep idle connections for 600 seconds, set &lt;code&gt;app.set_idle_timeout(620000);&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TLS&lt;/strong&gt; is the proxy&#39;s or the load balancer&#39;s: the package serves plain HTTP/1.1. So are security headers and rate limiting per client.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Health.&lt;/strong&gt; A &lt;code&gt;get(&quot;/health&quot;, health)&lt;/code&gt; route whose handler runs &lt;code&gt;db.run(&quot;select 1&quot;)&lt;/code&gt;, outside any &lt;code&gt;before_on&lt;/code&gt; prefix, so the platform needs no key.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logging.&lt;/strong&gt; One line per request after its response, &lt;code&gt;GET /users/1 200 3ms&lt;/code&gt;, a 500&#39;s message at error level, and startup and shutdown at info level, through Varyk&#39;s &lt;code&gt;log&lt;/code&gt;, which a program with an &lt;code&gt;http::App&lt;/code&gt; starts by itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-not-in-it&quot;&gt;What is not in it&lt;/h2&gt;
&lt;p&gt;HTTP/2 and TLS in the server, which are the proxy&#39;s; binary WebSocket messages and bytes bodies, until milestone 5c brings a bytes type; streaming request and response bodies beyond &lt;code&gt;Response::file&lt;/code&gt; and &lt;code&gt;save_to&lt;/code&gt;; per-request client headers and a request builder; client cookies and proxies (the client ignores &lt;code&gt;HTTP_PROXY&lt;/code&gt; and always connects directly); route groups and a wrapping hook; OpenTelemetry; rate limiting per client; serving a whole folder of static files; and templates.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 5c of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;: a date-time type, a UUID type, and a bytes type, which lets varyk-http read uploads and binary bodies, so the users API does not send a date as a string. Milestone 5&#39;s bar, a users API on a database that is &lt;code&gt;varyk init&lt;/code&gt;, &lt;code&gt;varyk add http sql&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away, is met when 5b4 and 5c are done. After 5b4, &lt;code&gt;varyk-mongo&lt;/code&gt; and &lt;code&gt;varyk-redis&lt;/code&gt; are the next packages. Nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk and varyk-http are experimental and pre-1.0. Put a small service behind it and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.7.0: routes the compiler checks</title>
        <published>2026-10-06T12:00:00+02:00</published>
        <updated>2026-10-06T12:00:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-7-0/"/>
        <id>https://varyk.com/blog/varyk-0-7-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-7-0/">&lt;p&gt;Varyk 0.7.0 is on crates.io. It is milestone 5b4 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, the fifth part of the batteries for services. Milestone 5b3 gave a package&#39;s &lt;code&gt;.rs&lt;/code&gt; facade what the database package &lt;code&gt;varyk-sql&lt;/code&gt; needs. Milestone 5b4 does the same for HTTP: a handler is an ordinary &lt;code&gt;async fn&lt;/code&gt;, a route names it, and &lt;code&gt;varyk check&lt;/code&gt; checks the route against the handler&#39;s parameters before anything is built. With it, a users API on a database is &lt;code&gt;varyk init&lt;/code&gt;, &lt;code&gt;varyk add http sql&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away.&lt;/p&gt;
&lt;p&gt;The HTTP package itself, &lt;code&gt;varyk-http&lt;/code&gt;, lives in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-http&quot;&gt;its own repository&lt;/a&gt; and is released on its own; its first release, &lt;a href=&quot;/blog/varyk-http-0-1-0/&quot;&gt;varyk-http 0.1.0&lt;/a&gt;, ships with this one, and has the server&#39;s settings, the client, WebSockets, and the rest. This release is the compiler side. varyk-sql 0.2.0 ships with it too: it moves to &lt;code&gt;varyk-std&lt;/code&gt; 0.7, with nothing else changed, because a program and its packages share one &lt;code&gt;varyk-std&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-the-compiler-knows-one-package&quot;&gt;Why the compiler knows one package&lt;/h2&gt;
&lt;p&gt;Varyk has no function values, so a route table cannot be an ordinary call that takes a function: some part of it must be known to the compiler. A general mechanism, a facade parameter that takes a function, would need the same knowledge and a mechanism nothing else uses; attributes on handlers would scatter the route table across the program. So the compiler knows &lt;code&gt;varyk-http&lt;/code&gt; by its crate name, as it knows &lt;code&gt;varyk-std&lt;/code&gt;. When a build holds that package, under whatever key, the calls that add routes and hooks to its &lt;code&gt;App&lt;/code&gt; are the compiler&#39;s own, and every other call on the app is an ordinary call of an imported struct. A package nobody designed with the compiler can still offer a plain function through the facade shapes every package has.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Routes and handlers.&lt;/strong&gt; This is the language reference&#39;s example, after &lt;code&gt;varyk add http&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; NewUser&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; State&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    users: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; get_user&lt;/span&gt;&lt;span&gt;(id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Option&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    for&lt;/span&gt;&lt;span&gt; user &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span&gt; state.users {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        if&lt;/span&gt;&lt;span&gt; user.id &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span&gt; id {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Some&lt;/span&gt;&lt;span&gt;(user.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; create_user&lt;/span&gt;&lt;span&gt;(user: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;NewUser&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; user.name.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_empty&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;bad_request&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;a user needs a name&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; created &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; { id: state.users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;len&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; +&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 1&lt;/span&gt;&lt;span&gt;, name: user.name.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;() };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;json&lt;/span&gt;&lt;span&gt;(created);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_status&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;201&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(r)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; build_app&lt;/span&gt;&lt;span&gt;(state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;App&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; app &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;App&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(state.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users/&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{id}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, get_user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;post&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users&amp;quot;&lt;/span&gt;&lt;span&gt;, create_user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and in &lt;code&gt;async fn main()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; users &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt; { id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;, name: &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span&gt; }];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; app &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; build_app&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span&gt; { users: users }));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; port: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 3000&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;if let&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;serve&lt;/span&gt;&lt;span&gt;(port).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    log::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;cannot serve: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, e);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;GET /users/1&lt;/code&gt; is answered with a 200 and &lt;code&gt;{&quot;id&quot;:1,&quot;name&quot;:&quot;Ada&quot;}&lt;/code&gt;, &lt;code&gt;GET /users/2&lt;/code&gt; with a 404, and &lt;code&gt;GET /users/abc&lt;/code&gt; with a 400 saying that the path parameter &lt;code&gt;id&lt;/code&gt; cannot be read from &lt;code&gt;abc&lt;/code&gt;; &lt;code&gt;get_user&lt;/code&gt; is not called for &lt;code&gt;abc&lt;/code&gt;. &lt;code&gt;POST /users&lt;/code&gt; with &lt;code&gt;{&quot;name&quot;: &quot;Bo&quot;}&lt;/code&gt; is answered with a 201.&lt;/p&gt;
&lt;p&gt;A route is &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;post&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt;, &lt;code&gt;patch&lt;/code&gt;, or &lt;code&gt;delete&lt;/code&gt;, with a path written in quotes, whose parts are either written out or a name in braces, &lt;code&gt;{id}&lt;/code&gt;. Each parameter of the handler gets its value from the request by the first rule that fits: a parameter named after a &lt;code&gt;{name}&lt;/code&gt; of the path is that part of the path; a &lt;code&gt;Shared&lt;/code&gt; of the app&#39;s state is the state; an &lt;code&gt;http::Request&lt;/code&gt; is the request itself, to read headers, cookies, or the body; on &lt;code&gt;post&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt;, and &lt;code&gt;patch&lt;/code&gt;, one parameter of a type JSON can hold is the body; and any other integer, &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, or &lt;code&gt;Option&lt;/code&gt; of one is read by its name from the query string, so &lt;code&gt;search(prefix: Option&amp;lt;string&amp;gt;, exact: bool)&lt;/code&gt; reads &lt;code&gt;/search?prefix=A&amp;amp;exact=true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Anything that fits no rule is an error at the route, one per problem: a &lt;code&gt;{name}&lt;/code&gt; with no parameter, a body on &lt;code&gt;get&lt;/code&gt;, two states, a parameter that gets no value from the request. So renaming a parameter cannot quietly stop it from getting its value. The request is read before the handler runs: a value that is not of its type, a missing query value, or a body that is not JSON of its type is a 400 naming the parameter, and the handler is not called, so inside a handler every parameter is a real value of its type.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Responses.&lt;/strong&gt; What a handler returns is its answer: nothing is a 204, a value JSON can write a 200 with the value as JSON, an &lt;code&gt;Option&lt;/code&gt; a 200 or, for &lt;code&gt;None&lt;/code&gt;, a 404, and an &lt;code&gt;http::Response&lt;/code&gt; is sent as built, for another status, a header, or plain text. A &lt;code&gt;Result&lt;/code&gt; of one of these with &lt;code&gt;Error&lt;/code&gt; gives the value&#39;s answer for &lt;code&gt;Ok&lt;/code&gt; and the error&#39;s for &lt;code&gt;Err&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hooks.&lt;/strong&gt; &lt;code&gt;app.before(f)&lt;/code&gt; runs &lt;code&gt;f&lt;/code&gt; before every request a route matches, &lt;code&gt;app.before_on(prefix, f)&lt;/code&gt; before the routes under a prefix, and &lt;code&gt;app.after(f)&lt;/code&gt; on every response the router makes. A &lt;code&gt;before&lt;/code&gt; hook gives &lt;code&gt;Ok(true)&lt;/code&gt; to let the request through, &lt;code&gt;Ok(false)&lt;/code&gt; for a 403, or an &lt;code&gt;Err&lt;/code&gt;; an &lt;code&gt;after&lt;/code&gt; hook changes the response through a &lt;code&gt;mut&lt;/code&gt; parameter:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; check_key&lt;/span&gt;&lt;span&gt;(req: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;, state: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; req.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;x-key&amp;quot;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Some&lt;/span&gt;&lt;span&gt;(key) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Ok&lt;/span&gt;&lt;span&gt;(key &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span&gt; state.key),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        None&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;unauthorized&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;an `x-key` header is needed&amp;quot;&lt;/span&gt;&lt;span&gt;)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; stamp&lt;/span&gt;&lt;span&gt;(req: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;mut&lt;/span&gt;&lt;span&gt; res: http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    res.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;set_header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;x-served-by&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;users&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These run with &lt;code&gt;app.before_on(&quot;/admin&quot;, check_key);&lt;/code&gt; and &lt;code&gt;app.after(stamp);&lt;/code&gt; in &lt;code&gt;build_app&lt;/code&gt;, for a &lt;code&gt;State&lt;/code&gt; with a &lt;code&gt;key&lt;/code&gt; field. &lt;code&gt;before_on&lt;/code&gt; is matched against the path of the route the request matched, as the program wrote it, on whole parts: &lt;code&gt;&quot;/admin&quot;&lt;/code&gt; covers &lt;code&gt;/admin/users/{id}&lt;/code&gt;, not &lt;code&gt;/administrators&lt;/code&gt;, and no spelling of a request&#39;s path skips it. Each hook covers every route of the app, wherever its line is. A handler that needs to know who is asking calls a function of the program, &lt;code&gt;let user = current_user(req, state)?;&lt;/code&gt;; a hook hands it nothing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Requests in a test.&lt;/strong&gt; &lt;code&gt;app.request(req).await&lt;/code&gt; sends one request through the app, hooks included, without a port, and gives the response the server would have sent:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; gets_a_user&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; users &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt; { id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;, name: &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span&gt; }];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; app &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; build_app&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Shared&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span&gt; { users: users }));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; r &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; app.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;request&lt;/span&gt;&lt;span&gt;(http::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;/users/1&amp;quot;&lt;/span&gt;&lt;span&gt;)).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    assert_eq&lt;/span&gt;&lt;span&gt;(r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;status&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;200&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    assert_eq&lt;/span&gt;&lt;span&gt;(r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;body&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;:1,&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;Ada&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;}&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;build_app&lt;/code&gt; is the function &lt;code&gt;main&lt;/code&gt; uses too, so a test sends its requests to the same app the service serves. A program that makes an app starts logging in &lt;code&gt;main&lt;/code&gt; and in every async test, so the message of a 500 is on the screen under &lt;code&gt;varyk test&lt;/code&gt; too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Error&lt;/code&gt; with a status.&lt;/strong&gt; &lt;code&gt;Error&lt;/code&gt; gains an optional HTTP status. &lt;code&gt;Error::with_status(status, text)&lt;/code&gt; makes one from Varyk, and &lt;code&gt;e.status()&lt;/code&gt; reads it, an &lt;code&gt;Option&amp;lt;u16&amp;gt;&lt;/code&gt;. &lt;code&gt;varyk-http&lt;/code&gt;&#39;s constructors are Varyk functions over it: &lt;code&gt;http::bad_request(text)&lt;/code&gt; (400), &lt;code&gt;http::unauthorized(text)&lt;/code&gt; (401), &lt;code&gt;http::forbidden(text)&lt;/code&gt; (403), &lt;code&gt;http::not_found(text)&lt;/code&gt; (404), &lt;code&gt;http::conflict(text)&lt;/code&gt; (409), and &lt;code&gt;http::error(status, text)&lt;/code&gt; for any other.&lt;/p&gt;
&lt;p&gt;How an error is sent is fixed by the compiler&#39;s design, because it is the rule that keeps a service&#39;s internals from its clients. An error with a status from 400 to 599 is sent with that status and the body &lt;code&gt;{&quot;error&quot;:&quot;&amp;lt;message&amp;gt;&quot;}&lt;/code&gt;. Any other error, one made by &lt;code&gt;Error::new&lt;/code&gt; or passed on with &lt;code&gt;?&lt;/code&gt; from a database query, or one with a status outside 400 to 599, is a 500 with the fixed body &lt;code&gt;{&quot;error&quot;:&quot;internal error&quot;}&lt;/code&gt;, and its message is logged with the request&#39;s method and path. A status therefore means the message was written for the client, and only Varyk code sets one: no official package&#39;s Rust does. A database message, a file path, or an address inside an error stays in the log.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Two facade shapes.&lt;/strong&gt; A &lt;code&gt;.rs&lt;/code&gt; facade function may take a value JSON can write, as &lt;code&gt;&amp;amp;T&lt;/code&gt; with &lt;code&gt;T: serde::Serialize + ?Sized&lt;/code&gt; (or &lt;code&gt;varyk_std::serde::Serialize + ?Sized&lt;/code&gt;), the half of the type parameter that milestone 5b3 left for this one. At a call it takes any type &lt;code&gt;json::stringify&lt;/code&gt; writes, with the same checks, and the value is read, not given away. &lt;code&gt;varyk-http&lt;/code&gt;&#39;s &lt;code&gt;Response::json(value)&lt;/code&gt; and its client&#39;s &lt;code&gt;post(url, body)&lt;/code&gt; take their values this way. The reference&#39;s in-memory store gains a method of this shape:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; save&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; varyk_std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;serde&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Serialize&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; + ?&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Sized&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;amp;mut&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    key&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;static str&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    value&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;T&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;u64&lt;/span&gt;&lt;span&gt;, varyk_std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Error&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;    // stores `value` under `key` with `serde_json::to_value`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which Varyk code calls with a struct the facade has never seen, &lt;code&gt;db.save(&quot;user/2&quot;, bo)?;&lt;/code&gt;, and &lt;code&gt;bo&lt;/code&gt; stays usable after the call. A facade may also return a bare &lt;code&gt;varyk_std::Error&lt;/code&gt;, for a function that makes an error of its own.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;varyk add http sql&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;varyk add http&lt;/code&gt; runs &lt;code&gt;cargo add varyk-http --rename http&lt;/code&gt;, so code writes &lt;code&gt;http::App&lt;/code&gt;, as &lt;code&gt;varyk add sql&lt;/code&gt; does for the database. Name several and each runs its own &lt;code&gt;cargo add&lt;/code&gt;, in order, stopping at the first failure; the full crate names work too (&lt;code&gt;varyk add varyk-http varyk-sql&lt;/code&gt;). That form takes no other argument; with one official name, any later arguments go to cargo as written (&lt;code&gt;varyk add sql --features postgres&lt;/code&gt;). A short name with &lt;code&gt;--rename&lt;/code&gt; is refused, since &lt;code&gt;http&lt;/code&gt; and &lt;code&gt;sql&lt;/code&gt; are also names of unrelated crates: write the full name, &lt;code&gt;varyk add varyk-http --rename web&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New diagnostic codes.&lt;/strong&gt; V0219 is a route whose path and handler do not fit. V0220 is a handler or hook of the wrong shape: not an async function of the package, a return type outside the list, a hook&#39;s parameters out of order. V0221 is a route or hook added to an app that is not a local made with &lt;code&gt;http::App::new&lt;/code&gt; in the same function, inside a loop, or an assignment to a name holding an app. V0222 is a path or prefix that is not valid, or a method and path already taken. V0407 is a &lt;code&gt;varyk-http&lt;/code&gt; that does not match this compiler. Others gain a case: V0901 names a route whose handler, or an app whose state, holds a Rust value that cannot go to another thread, and V0214 a route or hook that leads back to the function adding it. The &lt;a href=&quot;/learn/reference/#http&quot;&gt;reference&lt;/a&gt; has the new HTTP section, and the &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;error codes&lt;/a&gt; the full table.&lt;/p&gt;
&lt;p&gt;There is no new example program in the compiler&#39;s &lt;code&gt;examples/&lt;/code&gt; this time. Its test suite proves the routes with a stub &lt;code&gt;varyk-http&lt;/code&gt;, an in-memory router with no network, and a program that uses it; the real package&#39;s own tests and its &lt;code&gt;users&lt;/code&gt; demo run on axum.&lt;/p&gt;
&lt;h2 id=&quot;for-rust-readers&quot;&gt;For Rust readers&lt;/h2&gt;
&lt;p&gt;For each route the compiler writes one small function with concrete types, in the module of the route call. This is the one it writes for &lt;code&gt;app.get(&quot;/users/{id}&quot;, get_user)&lt;/code&gt;, from the users API at the top of the home page, as it is in the generated &lt;code&gt;src/main.rs&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[allow(warnings, arithmetic_overflow, unconditional_panic)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; varyk_route_0&lt;/span&gt;&lt;span&gt;(varyk_req&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: ::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Request&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt; ::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Response&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; varyk_0&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; = match&lt;/span&gt;&lt;span&gt; varyk_req&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;i64&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(v)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; v,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(r)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt; return&lt;/span&gt;&lt;span&gt; r,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; varyk_1&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; = match&lt;/span&gt;&lt;span&gt; varyk_req&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;State&lt;/span&gt;&lt;span&gt;&amp;gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(v)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; v,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(r)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt; return&lt;/span&gt;&lt;span&gt; r,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; get_user&lt;/span&gt;&lt;span&gt;(varyk_0,&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span&gt;varyk_1)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(v)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt; ::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;respond_option&lt;/span&gt;&lt;span&gt;(v),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt; ::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;respond_error&lt;/span&gt;&lt;span&gt;(e),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the route becomes &lt;code&gt;app.get(&quot;/users/{id}&quot;, ::http::route(varyk_route_0));&lt;/code&gt;. The program names only the package&#39;s items, never axum, so axum&#39;s &lt;code&gt;Handler&lt;/code&gt; trait and its errors never reach a writer; &lt;code&gt;--emit-rust&lt;/code&gt; shows every adapter, and a rustc error inside one is reported at its route.&lt;/p&gt;
&lt;h2 id=&quot;what-is-not-yet&quot;&gt;What is not yet&lt;/h2&gt;
&lt;p&gt;From HTTP: a hook that wraps the handler and calls it itself; groups of routes as values; a handler reading a header or cookie by name without taking &lt;code&gt;http::Request&lt;/code&gt;; a body read as anything but JSON or a multipart upload; headers for one client request beyond the client&#39;s defaults; adding a route to an app a function was given rather than one it made; a handler that is a method, a function of a &lt;code&gt;.rs&lt;/code&gt; file, or a function of another package; TLS in the server, which is the job of the proxy in front of it; request and response bodies sent in pieces; an OpenAPI document written from the routes; and types for dates, times, UUIDs, and bytes, which come in milestone 5c. From facades: two type parameters, both kinds at once, a &lt;code&gt;where&lt;/code&gt; clause, or another bound, and &lt;code&gt;varyk_std::Error&lt;/code&gt; in a parameter or a field. The &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/blob/varyk-v0.7.0/docs/language.md#not-in-milestone-5b4&quot;&gt;reference&lt;/a&gt; lists them all.&lt;/p&gt;
&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;
&lt;p&gt;The three crates, &lt;code&gt;varyk&lt;/code&gt;, &lt;code&gt;varyk-syntax&lt;/code&gt;, and &lt;code&gt;varyk-std&lt;/code&gt;, are released together as 0.7.0; &lt;code&gt;varyk-std&lt;/code&gt;&#39;s &lt;code&gt;Error&lt;/code&gt; gains its status. Nothing in 0.7.0 breaks an existing Varyk program; before 1.0, a new feature bumps the minor version, as a breaking change does. After &lt;code&gt;cargo install varyk&lt;/code&gt;, run &lt;code&gt;varyk check&lt;/code&gt; in a package, and it says what to change: the &lt;code&gt;varyk-std&lt;/code&gt; line in &lt;code&gt;Cargo.toml&lt;/code&gt;, or &lt;code&gt;cargo update -p varyk-std&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A program that uses &lt;code&gt;varyk-sql&lt;/code&gt; moves to varyk-sql 0.2 at the same time: run &lt;code&gt;varyk add sql&lt;/code&gt; again, which rewrites the &lt;code&gt;sql&lt;/code&gt; line to varyk-sql 0.2.0. Until it does, &lt;code&gt;varyk check&lt;/code&gt; reports V0404 at varyk-sql 0.1&#39;s own manifest, not at the program&#39;s. The two releases differ only in the &lt;code&gt;varyk-std&lt;/code&gt; they need: a program and its packages resolve to one &lt;code&gt;varyk-std&lt;/code&gt;, so varyk-sql 0.2 works with Varyk 0.7, and varyk-sql 0.1 stays with Varyk 0.6. varyk-sql&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#versions&quot;&gt;README&lt;/a&gt; has the table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Varyk 0.7.1&lt;/strong&gt;, on 7 October, is a patch release: &lt;code&gt;varyk init&lt;/code&gt; also writes a &lt;code&gt;.dockerignore&lt;/code&gt; with &lt;code&gt;target&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt;, so a container build copies neither, and V0219&#39;s note for a path parameter of the wrong type names the types that fit. Nothing else changed. After &lt;code&gt;cargo install varyk --locked&lt;/code&gt;, &lt;code&gt;varyk check&lt;/code&gt; in a package made with 0.7.0 asks for &lt;code&gt;cargo update -p varyk-std&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Varyk 0.7.2&lt;/strong&gt;, the same day, is another patch release from the same walkthrough. &lt;code&gt;main&lt;/code&gt; may return a &lt;code&gt;Result&lt;/code&gt; of something and &lt;code&gt;Error&lt;/code&gt;: &lt;code&gt;?&lt;/code&gt; then works in it, and an &lt;code&gt;Err&lt;/code&gt; is logged, or printed on stderr in a program that does not log, and the program exits with code 1, so a service that cannot start says so to whatever runs it. A &lt;code&gt;main&lt;/code&gt; that returns nothing works as before. A &lt;code&gt;Result&lt;/code&gt; used where its value is wanted now suggests &lt;code&gt;?&lt;/code&gt;; &lt;code&gt;http::&lt;/code&gt; or &lt;code&gt;sql::&lt;/code&gt; used before &lt;code&gt;varyk add http sql&lt;/code&gt; says how to add the package; and text that is not JSON at all, such as a form sent where a JSON body is expected, is reported as &quot;it is not JSON&quot;.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts. For a service, &lt;code&gt;varyk add http sql&lt;/code&gt; and the &lt;a href=&quot;/blog/varyk-http-0-1-0/#a-first-service&quot;&gt;varyk-http post&lt;/a&gt; take it from there.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;First, &lt;code&gt;varyk-http&lt;/code&gt; 0.1.0, which ships with this release and has &lt;a href=&quot;/blog/varyk-http-0-1-0/&quot;&gt;its own post&lt;/a&gt;: the server on axum with safe defaults, the client, WebSockets, server-sent events, uploads, metrics, and the users API as its demo.&lt;/p&gt;
&lt;p&gt;Then milestone 5c, time, ids, and bytes: a date-time type, a UUID type, and a bytes type, so the users API does not send a date as a string, and &lt;code&gt;varyk-http&lt;/code&gt; can read binary bodies. Milestone 5&#39;s bar, the golden path, is met when 5b4 and 5c are done. Beside them, as its own work, an agent evaluation: the examples written by a model from the language reference alone, with pass rates published, before any page claims that agents write Varyk well. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has every item, and nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Write a small service with it and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>varyk-sql 0.1.0: SQL databases for Varyk</title>
        <published>2026-10-04T14:00:00+02:00</published>
        <updated>2026-10-04T14:00:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-sql-0-1-0/"/>
        <id>https://varyk.com/blog/varyk-sql-0-1-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-sql-0-1-0/">&lt;p&gt;varyk-sql 0.1.0 is on crates.io. It is the official Varyk package for SQL databases: SQLite, Postgres, and MySQL through sqlx. It covers what an ordinary service does with a database and nothing more: connect, over TLS when the URL asks for it, run migrations, query, write inside transactions, log, and test against an in-memory SQLite database. It lives in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql&quot;&gt;its own repository&lt;/a&gt;, and its &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#readme&quot;&gt;README&lt;/a&gt; is the full documentation.&lt;/p&gt;
&lt;p&gt;varyk-sql ships with &lt;a href=&quot;/blog/varyk-0-6-0/&quot;&gt;Varyk 0.6.0&lt;/a&gt; because it needs that release&#39;s facade features. The package is a &lt;code&gt;.rs&lt;/code&gt; facade over sqlx, with its tests written in Varyk: a query call reads its rows into whatever struct the caller names, takes the query&#39;s values after the text, and takes the text itself only as written in the program. A program that uses it writes no Rust. varyk-sql 0.1 works with Varyk 0.6, and each minor Varyk release is followed by a varyk-sql release, since a program and the package must resolve to one &lt;code&gt;varyk-std&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;adding-it&quot;&gt;Adding it&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; init users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; add sql&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;varyk add sql&lt;/code&gt; runs &lt;code&gt;cargo add varyk-sql --rename sql&lt;/code&gt;, so code names the package &lt;code&gt;sql::&lt;/code&gt;. The default driver is SQLite, compiled from its C source on the first build: that needs a C compiler (Xcode&#39;s command-line tools on macOS, &lt;code&gt;build-essential&lt;/code&gt; on Debian and Ubuntu) and takes a few minutes, once. A server driver is a feature:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; add sql&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; --features&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; postgres&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;                        # Postgres, and SQLite for tests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; add sql&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; --no-default-features --features&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; postgres&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;  # Postgres only, skips the SQLite build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;varyk&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; add sql&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; --features&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; mysql&lt;/span&gt;&lt;span class=&quot;z-5&quot;&gt;                           # MySQL, and SQLite for tests&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;a-first-service&quot;&gt;A first service&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;src/main.vr&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Config&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    database_url: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; load&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; config: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; env::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;connect&lt;/span&gt;&lt;span&gt;(config.database_url).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;migrate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;migrations&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name) values (?)&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select id, name from users&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; load&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(users) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            for&lt;/span&gt;&lt;span&gt; user &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span&gt; users {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;                println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{} {}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, user.id, user.name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; log::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, e.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;message&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;migrations/0001_users.sql&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;create table&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; users&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;integer primary key&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    name text not null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DATABASE_URL&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;sqlite::memory:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;varyk run&lt;/code&gt; prints &lt;code&gt;1 Ada&lt;/code&gt;. &lt;code&gt;main&lt;/code&gt; returns nothing in Varyk, so the work is in &lt;code&gt;load&lt;/code&gt;, and &lt;code&gt;main&lt;/code&gt; matches on its result; &lt;code&gt;all&lt;/code&gt; takes its row type from &lt;code&gt;load&lt;/code&gt;&#39;s return type. The URL&#39;s scheme picks the driver. On Postgres the query writes &lt;code&gt;$1&lt;/code&gt; for &lt;code&gt;?&lt;/code&gt;, and the migration differs: &lt;code&gt;integer primary key&lt;/code&gt; numbers new rows by itself only on SQLite; on Postgres the column is &lt;code&gt;id integer primary key generated always as identity&lt;/code&gt;, and on MySQL &lt;code&gt;id integer primary key auto_increment&lt;/code&gt; (see the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#a-first-service&quot;&gt;README&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;the-calls&quot;&gt;The calls&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sql::connect(url)&lt;/code&gt; gives a pool of up to 10 connections, which waits up to 30 s for a free one; &lt;code&gt;sql::connect_with(url, max_connections)&lt;/code&gt; sets the count. &lt;code&gt;db.clone()&lt;/code&gt; is another handle to the same pool, for a started task that needs one.&lt;/li&gt;
&lt;li&gt;On a pool and on a transaction, &lt;code&gt;one&lt;/code&gt; gives the first row as a &lt;code&gt;T&lt;/code&gt; or an &lt;code&gt;Error&lt;/code&gt; when there is none, &lt;code&gt;first&lt;/code&gt; the first row or &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt; every row, and &lt;code&gt;run&lt;/code&gt; runs a statement and gives the number of rows it changed. &lt;code&gt;T&lt;/code&gt; comes from where the result goes, and a struct is read by column name, a field&#39;s &lt;code&gt;#[rename(&quot;..&quot;)]&lt;/code&gt; included.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;db.begin()&lt;/code&gt; starts a transaction on one connection of the pool, and &lt;code&gt;commit&lt;/code&gt; commits it. A transaction dropped without &lt;code&gt;commit&lt;/code&gt; rolls back, so an early &lt;code&gt;return&lt;/code&gt; or a &lt;code&gt;?&lt;/code&gt; undoes it; there is no &lt;code&gt;rollback&lt;/code&gt; call and no nested transaction.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;db.migrate(&quot;migrations&quot;)&lt;/code&gt; applies, in order, every &lt;code&gt;.sql&lt;/code&gt; file in the folder (not &lt;code&gt;.down.sql&lt;/code&gt;) not yet recorded in the database&#39;s &lt;code&gt;_sqlx_migrations&lt;/code&gt; table. The files use sqlx&#39;s format, so the same folder works with sqlx&#39;s own CLI.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; rename&lt;/span&gt;&lt;span&gt;(db: sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Pool&lt;/span&gt;&lt;span&gt;, id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;bool&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; tx &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;begin&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; changed &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;update users set name = ? where id = ?&amp;quot;&lt;/span&gt;&lt;span&gt;, name, id).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; changed &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 1&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;no such user&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into audit (user_id, action) values (?, &amp;#39;rename&amp;#39;)&amp;quot;&lt;/span&gt;&lt;span&gt;, id).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;commit&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;why-the-query-is-literal&quot;&gt;Why the query is literal&lt;/h2&gt;
&lt;p&gt;The query is literal text: a query built from input does not compile. The package&#39;s guard against SQL injection is a compiler check: the query parameter of &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;first&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt;, and &lt;code&gt;run&lt;/code&gt; is a &lt;code&gt;&amp;amp;&#39;static str&lt;/code&gt;, which Varyk 0.6.0 lets take only text written in the program, and a name or a &lt;code&gt;format!&lt;/code&gt; there is V0217, checked at the program&#39;s call site. The values go after the text, one per placeholder: &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, floats, integers up to &lt;code&gt;i64&lt;/code&gt;, and an &lt;code&gt;Option&lt;/code&gt; of each, where &lt;code&gt;None&lt;/code&gt; is &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; user: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;first&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select id, name from users where id = ?&amp;quot;&lt;/span&gt;&lt;span&gt;, id).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The placeholders are the database&#39;s own, passed through: &lt;code&gt;?&lt;/code&gt; on SQLite and MySQL, &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt; on Postgres. A program that runs on two databases keeps two queries. On SQLite and MySQL the number of values is checked against the number of placeholders before the query runs, and a mismatch is an &lt;code&gt;Error&lt;/code&gt; naming both, because SQLite would otherwise bind a missing value as &lt;code&gt;NULL&lt;/code&gt; and ignore an extra one. On Postgres the server rejects too few values and ignores an extra one.&lt;/p&gt;
&lt;h2 id=&quot;when-something-goes-wrong&quot;&gt;When something goes wrong&lt;/h2&gt;
&lt;p&gt;Every failure is an &lt;code&gt;Error&lt;/code&gt; whose message the package writes, and no call panics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A failed statement ends its transaction.&lt;/strong&gt; When a statement in a transaction fails in the database, with a duplicate key, a deadlock, or a missing table, the transaction is over: every later query on it is an &lt;code&gt;Error&lt;/code&gt;, &quot;a statement in this transaction failed; it will roll back&quot;, without reaching the database, and &lt;code&gt;commit&lt;/code&gt; rolls it back and is an &lt;code&gt;Error&lt;/code&gt;, &quot;the transaction was rolled back: a statement in it failed&quot;. To try again, start a new transaction. The rule is the same on all three databases, because each would otherwise behave differently: Postgres aborts the transaction at the failure, and a MySQL deadlock and some SQLite errors end it on the server. An &lt;code&gt;Error&lt;/code&gt; from reading the rows into &lt;code&gt;T&lt;/code&gt; does not end the transaction, nor does the package&#39;s own count of values on SQLite and MySQL; on Postgres too few values is a database error and does.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;An error on a later row is an error.&lt;/strong&gt; &lt;code&gt;one&lt;/code&gt; and &lt;code&gt;first&lt;/code&gt; add no &lt;code&gt;limit&lt;/code&gt;. On Postgres and MySQL both read the rest of the result and drop it, so a statement that fails on a later row is an &lt;code&gt;Error&lt;/code&gt;, not the first row, and the connection&#39;s next statement is not handed that error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A failed migration lets go.&lt;/strong&gt; On Postgres and MySQL sqlx takes a lock while it applies migrations, so replicas starting together apply each one once. A failed migration is an &lt;code&gt;Error&lt;/code&gt; naming its version and the database&#39;s message, and it releases the lock, so another replica&#39;s &lt;code&gt;migrate&lt;/code&gt; does not wait on it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Errors carry no secrets they can avoid.&lt;/strong&gt; A connection failure says which step failed and never contains the URL, so a password cannot reach a log that way. A database error keeps the database&#39;s own message, which names the constraint or column where there is one, and never includes Postgres&#39;s &quot;detail&quot; field, which can hold the row&#39;s values. Postgres and MySQL may still quote the offending value in the message itself, a duplicate key for example, so treat these messages as data: log them, and give clients a message of your own.&lt;/p&gt;
&lt;h2 id=&quot;columns-and-ids&quot;&gt;Columns and ids&lt;/h2&gt;
&lt;p&gt;sqlx&#39;s &lt;code&gt;Any&lt;/code&gt; driver, which serves all three databases through one pool, reads booleans, integers, floats, and text; anything else is cast in the query, such as &lt;code&gt;id::text&lt;/code&gt; for a Postgres &lt;code&gt;uuid&lt;/code&gt; or &lt;code&gt;timestamptz&lt;/code&gt;, and &lt;code&gt;cast(x as char)&lt;/code&gt; for a MySQL &lt;code&gt;datetime&lt;/code&gt;. Every selected column must be one the driver reads, whether or not &lt;code&gt;T&lt;/code&gt; has a field for it, so name the columns instead of &lt;code&gt;select *&lt;/code&gt;. The README has the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#column-types&quot;&gt;table for each database&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One case reads wrong without an &lt;code&gt;Error&lt;/code&gt;: the driver reads MySQL&#39;s &lt;code&gt;smallint unsigned&lt;/code&gt;, &lt;code&gt;int unsigned&lt;/code&gt;, and &lt;code&gt;bigint unsigned&lt;/code&gt; as signed, so a large value wraps to a negative number. Read a &lt;code&gt;smallint unsigned&lt;/code&gt; or an &lt;code&gt;int unsigned&lt;/code&gt; with &lt;code&gt;cast(x as signed)&lt;/code&gt; into an &lt;code&gt;i64&lt;/code&gt;, and a &lt;code&gt;bigint unsigned&lt;/code&gt; that may reach 2^63 with &lt;code&gt;cast(x as char)&lt;/code&gt; into a &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Each call on a pool may run on a different connection, so a new row&#39;s id is read in the statement that makes it, with &lt;code&gt;returning&lt;/code&gt; on Postgres and SQLite:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// Postgres ($1) and SQLite (?)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name) values ($1) returning id&amp;quot;&lt;/span&gt;&lt;span&gt;, name).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MySQL has no &lt;code&gt;returning&lt;/code&gt;, and &lt;code&gt;select last_insert_id()&lt;/code&gt; on a pool may run on another connection than the insert, so both go in one transaction, which holds one connection:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let mut&lt;/span&gt;&lt;span&gt; tx &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;begin&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; _added &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name) values (?)&amp;quot;&lt;/span&gt;&lt;span&gt;, name).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select last_insert_id()&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tx.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;commit&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; count_users&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; sql::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;connect_with&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;sqlite::memory:&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;migrate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;migrations&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;insert into users (name) values (?)&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;select count(*) from users&amp;quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[test]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; adds_a_user&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; counted: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; count_users&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; counted {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(n) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; assert_eq&lt;/span&gt;&lt;span&gt;(n, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; assert_eq&lt;/span&gt;&lt;span&gt;(e.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;message&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;no error&amp;quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each &lt;code&gt;sqlite::memory:&lt;/code&gt; pool is a database of its own, alive while the pool is, so every test starts empty. It is a pool of one connection whatever the count, which keeps the test&#39;s queries in order; a query on the pool while a transaction is open waits for that connection and fails after 30 s, so finish the transaction first. Run &lt;code&gt;varyk test&lt;/code&gt; from the package root, since &lt;code&gt;migrate(&quot;migrations&quot;)&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt; are read relative to the working directory.&lt;/p&gt;
&lt;h2 id=&quot;in-production&quot;&gt;In production&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TLS.&lt;/strong&gt; sqlx is built with rustls and the webpki root certificates, so TLS works in a minimal container with no CA bundle and no OpenSSL. The URL asks for it: &lt;code&gt;?sslmode=verify-full&lt;/code&gt; on Postgres and &lt;code&gt;?ssl-mode=VERIFY_IDENTITY&lt;/code&gt; on MySQL check the certificate and host name; &lt;code&gt;require&lt;/code&gt; and &lt;code&gt;REQUIRED&lt;/code&gt; encrypt but accept any certificate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migrations.&lt;/strong&gt; Call &lt;code&gt;db.migrate(&quot;migrations&quot;)&lt;/code&gt; at startup, or apply the folder from CI with &lt;code&gt;sqlx migrate run&lt;/code&gt;. The folder is a path relative to the working directory, so the container holds it beside the executable; the README has a &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql#migrations&quot;&gt;Dockerfile&lt;/a&gt; that builds with &lt;code&gt;varyk build --release&lt;/code&gt; and copies &lt;code&gt;migrations/&lt;/code&gt; into a distroless image.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logging.&lt;/strong&gt; sqlx reports each statement at debug level through &lt;code&gt;tracing&lt;/code&gt;, which a Varyk program that logs already sets up: the SQL text and the time it took, never the values. &lt;code&gt;LOG=debug&lt;/code&gt; turns these lines on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Health.&lt;/strong&gt; &lt;code&gt;db.run(&quot;select 1&quot;)&lt;/code&gt; is the readiness check: it takes a connection from the pool and asks the database for an answer.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-not-in-it&quot;&gt;What is not in it&lt;/h2&gt;
&lt;p&gt;Pool options beyond &lt;code&gt;max_connections&lt;/code&gt; (timeouts, idle, lifetime); &lt;code&gt;rollback&lt;/code&gt; as a call, and savepoints; streaming rows; embedding the migration files in the executable; down migrations; date, uuid, bytes, numeric, JSON, and array columns without a cast; a query spanning two databases&#39; placeholder styles; sqlx&#39;s compile-time checked &lt;code&gt;query!&lt;/code&gt;; Postgres &lt;code&gt;listen&lt;/code&gt; and &lt;code&gt;notify&lt;/code&gt;, and &lt;code&gt;copy&lt;/code&gt;; a &lt;code&gt;Shared&lt;/code&gt; pool for HTTP handlers, which comes with milestone 5b4; and MongoDB and Redis, which are their own packages, after 5b4.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 5b4 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; is &lt;code&gt;varyk-http&lt;/code&gt; and the golden path: an HTTP server with an explicit route table, a handler&#39;s parameters bound by name to the route and by type to shared state, an HTTP client, and the bar for all of milestone 5, a users API on a database that is &lt;code&gt;varyk init&lt;/code&gt;, &lt;code&gt;varyk add http sql&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away. Nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk and varyk-sql are experimental and pre-1.0. Point a small service at your database and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.6.0: facades for packages</title>
        <published>2026-10-04T12:00:00+02:00</published>
        <updated>2026-10-04T12:00:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-6-0/"/>
        <id>https://varyk.com/blog/varyk-0-6-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-6-0/">&lt;p&gt;Varyk 0.6.0 is on crates.io. It is milestone 5b3 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, the fourth part of the batteries for services. Milestone 5b2 let a Varyk package use another Varyk package by name, and moved the database and HTTP to packages, &lt;code&gt;varyk-sql&lt;/code&gt; and &lt;code&gt;varyk-http&lt;/code&gt;. Milestone 5b3 is what such a package needs from the compiler: a &lt;code&gt;.rs&lt;/code&gt; facade that can say &quot;read the result into whatever type you name&quot; and &quot;take these values, however many&quot;, so that &lt;code&gt;varyk-sql&lt;/code&gt; can keep its Rust in a facade, and a program that uses it writes no Rust at all. It also gives a facade a parameter that takes only text written in the program, which is what will make a database query built from input a compile error.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;varyk-sql&lt;/code&gt; itself lives in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk-sql&quot;&gt;its own repository&lt;/a&gt; and is released on its own; its first release, &lt;a href=&quot;/blog/varyk-sql-0-1-0/&quot;&gt;varyk-sql 0.1.0&lt;/a&gt;, ships with this one. This release is the compiler side.&lt;/p&gt;
&lt;h2 id=&quot;why-facades&quot;&gt;Why facades&lt;/h2&gt;
&lt;p&gt;A facade is the &lt;code&gt;.rs&lt;/code&gt; file in a package through which Varyk code reaches a Rust crate. Until now it could name only concrete types, so a package could not offer &quot;read this row into whatever struct you name&quot;, or &quot;take these values, however many&quot;: the two things a database package is made of. Milestone 5b3 adds four shapes a facade can declare, one thing a &lt;code&gt;.vr&lt;/code&gt; file can say, and one convenience for adding a package. Apart from &lt;code&gt;pub use&lt;/code&gt;, none of it is new Varyk syntax: a Varyk function still has no type parameters, no variadic parameter, and no literal-only parameter. These are shapes the compiler accepts in a &lt;code&gt;.rs&lt;/code&gt; signature, and rules for calling them.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;A type taken from where the result goes.&lt;/strong&gt; A &lt;code&gt;pub fn&lt;/code&gt; or method of a &lt;code&gt;.rs&lt;/code&gt; module may have one type parameter, &lt;code&gt;T: serde::de::DeserializeOwned&lt;/code&gt;, or &lt;code&gt;varyk_std::serde::de::DeserializeOwned&lt;/code&gt;, which needs no &lt;code&gt;serde&lt;/code&gt; dependency, and return &lt;code&gt;Result&amp;lt;T, varyk_std::Error&amp;gt;&lt;/code&gt;, &lt;code&gt;Result&amp;lt;Option&amp;lt;T&amp;gt;, varyk_std::Error&amp;gt;&lt;/code&gt;, or &lt;code&gt;Result&amp;lt;Vec&amp;lt;T&amp;gt;, varyk_std::Error&amp;gt;&lt;/code&gt;. At a call, &lt;code&gt;T&lt;/code&gt; is the type the result is used as, found as for &lt;code&gt;json::parse&lt;/code&gt;: a &lt;code&gt;let&lt;/code&gt; with a written type, an argument, a return value, or a field, through &lt;code&gt;?&lt;/code&gt; and &lt;code&gt;.await&lt;/code&gt;. &lt;code&gt;T&lt;/code&gt; is any type &lt;code&gt;json::parse&lt;/code&gt; reads, with the same attribute checks (V0209), so the facade reads into a struct it has never seen. With nothing to say the type, or for a started call, which has no &lt;code&gt;.await&lt;/code&gt;, it is V0207, and a Rust type from a &lt;code&gt;.rs&lt;/code&gt; module or a type of another package is V0210. The generated Rust writes &lt;code&gt;T&lt;/code&gt; after the name.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Any number of values.&lt;/strong&gt; The last parameter of a facade function may be &lt;code&gt;Vec&amp;lt;varyk_std::Value&amp;gt;&lt;/code&gt;, which Varyk code writes as zero or more arguments after the others. Each is a &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;f32&lt;/code&gt;, &lt;code&gt;f64&lt;/code&gt;, &lt;code&gt;i8&lt;/code&gt; to &lt;code&gt;i64&lt;/code&gt;, &lt;code&gt;u8&lt;/code&gt; to &lt;code&gt;u32&lt;/code&gt;, or an &lt;code&gt;Option&lt;/code&gt; of one of those; anything else is V0218, and for a &lt;code&gt;u64&lt;/code&gt; or &lt;code&gt;usize&lt;/code&gt; the help writes &lt;code&gt;as i64&lt;/code&gt;. &lt;code&gt;Value&lt;/code&gt; holds scalars only, built by the compiler without serde, so no conversion can fail: a design that sent any data type through serde was considered and dropped, because its only ways to handle a failed conversion were a crash, an error on every call, or a silent &lt;code&gt;Null&lt;/code&gt;, which in a database query is wrong data with no error. Each value is read, not given away, so a name passed stays usable after the call.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Text written in the program.&lt;/strong&gt; A parameter of type &lt;code&gt;&amp;amp;&#39;static str&lt;/code&gt; takes only a string literal, escapes included, and nothing else. A name, a parameter, or a &lt;code&gt;format!&lt;/code&gt; there is V0217, &quot;this argument must be text written in the program&quot;, and for a &lt;code&gt;format!&lt;/code&gt; a note says to pass the values after the text instead. The compiler knows nothing about SQL; it knows that this parameter takes only a literal. The check happens at the program&#39;s call site, where its input is visible to the compiler, so in &lt;code&gt;varyk-sql&lt;/code&gt; no input can become part of a query: the values go after the text, and the database binds them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Varyk&#39;s own &lt;code&gt;Error&lt;/code&gt;.&lt;/strong&gt; A facade may return &lt;code&gt;varyk_std::Error&lt;/code&gt;, by that full path, as the error of a returned &lt;code&gt;Result&lt;/code&gt;. Varyk sees it as its own &lt;code&gt;Error&lt;/code&gt;, so &lt;code&gt;?&lt;/code&gt; opens it in a function returning &lt;code&gt;Result&amp;lt;_, Error&amp;gt;&lt;/code&gt;, and &lt;code&gt;match&lt;/code&gt; reads &lt;code&gt;e.message()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;pub use&lt;/code&gt;.&lt;/strong&gt; A &lt;code&gt;.vr&lt;/code&gt; file may re-export a function, struct, or enum of its own package, so a library&#39;s root can gather what its users need:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// src/lib.vr of a package `shelf`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub mod&lt;/span&gt;&lt;span&gt; store;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub use&lt;/span&gt;&lt;span&gt; store::item;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub use&lt;/span&gt;&lt;span&gt; store::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Book&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A program that uses &lt;code&gt;shelf&lt;/code&gt; writes &lt;code&gt;shelf::item(3)&lt;/code&gt; and &lt;code&gt;shelf::Book&lt;/code&gt;, and may still write &lt;code&gt;shelf::store::item(3)&lt;/code&gt;. The item must be &lt;code&gt;pub&lt;/code&gt;, and so must every module on its own path from the root, so the types it names stay visible to its users.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;varyk add sql&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;varyk add&lt;/code&gt; gains a shorthand for the official database package: &lt;code&gt;varyk add sql&lt;/code&gt; runs &lt;code&gt;cargo add varyk-sql --rename sql&lt;/code&gt;, so code writes &lt;code&gt;sql::connect&lt;/code&gt;, and any later arguments go to cargo as written (&lt;code&gt;varyk add sql --features postgres&lt;/code&gt;). One shorthand per call. A call whose first argument is not a shorthand is passed through unchanged, as before. &lt;code&gt;varyk add sql&lt;/code&gt; works with varyk-sql 0.1.0, released with it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A second allocation, named.&lt;/strong&gt; Until now the compiler inserted exactly one kind of allocation: a string literal placed into an owned slot. A string passed as a trailing value is the second: the function receiving the values owns them, so &lt;code&gt;Value::from&lt;/code&gt; copies the text as it hands the value over, the cost of sending it out. &lt;code&gt;--emit-rust&lt;/code&gt; shows both, and nothing else copies a string&#39;s text behind your back.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New diagnostic codes.&lt;/strong&gt; V0217 is an argument to a literal-text parameter that is not a string literal. V0218 is a trailing value of a type that cannot be passed as a value. The &lt;a href=&quot;/learn/reference/#a-facade-for-a-package&quot;&gt;language reference&lt;/a&gt; has the new section, and the &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;error codes&lt;/a&gt; the full table.&lt;/p&gt;
&lt;p&gt;There is no new example program this time. The compiler&#39;s own test suite proves the facade shapes with a package whose facade is an in-memory store shaped like &lt;code&gt;varyk-sql&lt;/code&gt;&#39;s, and a program that uses it.&lt;/p&gt;
&lt;h2 id=&quot;a-facade-worked-through&quot;&gt;A facade, worked through&lt;/h2&gt;
&lt;p&gt;This is the reference&#39;s example: a facade shaped like &lt;code&gt;varyk-sql&lt;/code&gt;&#39;s, with a map in memory in place of a database. The facade is Rust; the reference leaves out the bodies of its two methods, as here:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// src/kv.rs of a package `store`, with `serde_json` and `varyk-std` in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// its [dependencies]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Store&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    entries&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collections&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;BTreeMap&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;String&lt;/span&gt;&lt;span&gt;, serde_json&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Value&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; open&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Store&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Store&lt;/span&gt;&lt;span&gt; { entries&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collections&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;BTreeMap&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;() }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Store&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; put&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        &amp;amp;mut&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        key&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;static str&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        values&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;&amp;lt;varyk_std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Value&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;u64&lt;/span&gt;&lt;span&gt;, varyk_std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Error&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;        // turns `values` into JSON and stores it under `key`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; one&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; varyk_std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;serde&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;de&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;DeserializeOwned&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        key&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;static str&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        values&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;&amp;lt;varyk_std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Value&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;T&lt;/span&gt;&lt;span&gt;, varyk_std&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Error&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;        // reads the JSON under `key` with `serde_json::from_value`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The package&#39;s root gives the program short names:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// src/lib.vr of `store`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub mod&lt;/span&gt;&lt;span&gt; kv;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub use&lt;/span&gt;&lt;span&gt; kv::open;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub use&lt;/span&gt;&lt;span&gt; kv::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Store&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the program writes no Rust:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// in a program with `store = { path = &amp;quot;../store&amp;quot; }` and `varyk-std` in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// its [dependencies]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; add_ada&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; store::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;open&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; name &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;Ada&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;put&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;user/1&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;, name)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    db.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;user/1&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;add_ada&lt;/code&gt; stores &lt;code&gt;[1, &quot;Ada&quot;]&lt;/code&gt; and reads it back as a &lt;code&gt;User&lt;/code&gt;. &lt;code&gt;&quot;user/1&quot;&lt;/code&gt; is text written in the program; &lt;code&gt;1, name&lt;/code&gt; are the values after it, read and not given away; &lt;code&gt;User&lt;/code&gt; comes from the return type; and &lt;code&gt;?&lt;/code&gt; works because the facade returns Varyk&#39;s own &lt;code&gt;Error&lt;/code&gt;. For Rust readers, the last call is written &lt;code&gt;::store::kv::Store::one::&amp;lt;User&amp;gt;(&amp;amp;db, &quot;user/1&quot;, vec![])&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-not-yet&quot;&gt;What is not yet&lt;/h2&gt;
&lt;p&gt;A type parameter in a parameter (&lt;code&gt;&amp;amp;T: Serialize&lt;/code&gt;, for sending a Varyk value out, planned for 5b4), two type parameters, a &lt;code&gt;where&lt;/code&gt; clause, or another bound; a &lt;code&gt;u64&lt;/code&gt;, a struct, a &lt;code&gt;Vec&lt;/code&gt;, or a map as a trailing value. Also not yet: &lt;code&gt;varyk_std::Error&lt;/code&gt; anywhere but as the error of a returned &lt;code&gt;Result&lt;/code&gt;; a Varyk function with a literal-only parameter or one taking any number of values, so a &lt;code&gt;.vr&lt;/code&gt; wrapper cannot pass a query through, and &lt;code&gt;varyk-sql&lt;/code&gt; puts every call that takes a query in its &lt;code&gt;.rs&lt;/code&gt; facade; naming &lt;code&gt;varyk_std::Value&lt;/code&gt; from Varyk code; &lt;code&gt;pub use&lt;/code&gt; of a module, with braces, globs, or &lt;code&gt;as&lt;/code&gt;, or of an item of another package; and several shorthands in one &lt;code&gt;varyk add&lt;/code&gt;. The &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/blob/varyk-v0.6.0/docs/language.md#not-in-milestone-5b3&quot;&gt;reference&lt;/a&gt; lists them.&lt;/p&gt;
&lt;h2 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h2&gt;
&lt;p&gt;The three crates, &lt;code&gt;varyk&lt;/code&gt;, &lt;code&gt;varyk-syntax&lt;/code&gt;, and &lt;code&gt;varyk-std&lt;/code&gt;, are released together as 0.6.0; &lt;code&gt;varyk-std&lt;/code&gt; gains &lt;code&gt;Value&lt;/code&gt;. Nothing in 0.6.0 breaks an existing package: before 1.0, a new feature now bumps the minor version, as a breaking change does. After &lt;code&gt;cargo install varyk&lt;/code&gt;, run &lt;code&gt;varyk check&lt;/code&gt; in a package, and it says what to change: the &lt;code&gt;varyk-std&lt;/code&gt; line in &lt;code&gt;Cargo.toml&lt;/code&gt;, or &lt;code&gt;cargo update -p varyk-std&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;First, &lt;code&gt;varyk-sql&lt;/code&gt; 0.1.0, which ships with this release and has &lt;a href=&quot;/blog/varyk-sql-0-1-0/&quot;&gt;its own post&lt;/a&gt;: SQLite, Postgres, and MySQL on sqlx, with the query text a literal, so a query built from input is a compile error.&lt;/p&gt;
&lt;p&gt;Then milestone 5b4, &lt;code&gt;varyk-http&lt;/code&gt; and the golden path: an HTTP server with an explicit route table, an HTTP client, which brings the other half of the type parameter, for sending a Varyk value out, and the bar for all of milestone 5, a users API on a database that is &lt;code&gt;varyk init&lt;/code&gt;, &lt;code&gt;varyk add http sql&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has every item, and nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Try writing a facade for a crate you use, and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.5.0: packages</title>
        <published>2026-10-02T00:00:00+00:00</published>
        <updated>2026-10-02T00:00:00+00:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-5-0/"/>
        <id>https://varyk.com/blog/varyk-0-5-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-5-0/">&lt;p&gt;Varyk 0.5.0 is on crates.io. It is milestone 5b2 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, the third part of the batteries for services. Milestones 5a and 5b1 gave Varyk, a language for backend services that compiles to Rust, the data a service works with and the way it waits: JSON, configuration, logging, tests, and tasks. Milestone 5b2 adds the way Varyk code is shared: a Varyk package uses another Varyk package by name, with no Rust file in between, and every package is built from the Varyk its author wrote. It comes before HTTP and the database because they will be packages too.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;A package is named by its key.&lt;/strong&gt; Until now, Varyk code reached any other package, a Varyk library included, through a &lt;code&gt;.rs&lt;/code&gt; file of its own, a facade. Now a Varyk package listed in &lt;code&gt;[dependencies]&lt;/code&gt; is named in Varyk code like a module, by its key, with each &lt;code&gt;-&lt;/code&gt; read as &lt;code&gt;_&lt;/code&gt;. With &lt;code&gt;units = { path = &quot;../units&quot; }&lt;/code&gt; in &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;use&lt;/span&gt;&lt;span&gt; units::length::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Meters&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; total&lt;/span&gt;&lt;span&gt;(a: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Meters&lt;/span&gt;&lt;span&gt;, b: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Meters&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Meters&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    units::length::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;add&lt;/span&gt;&lt;span&gt;(a, b)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is no new syntax. You choose the key, so &lt;code&gt;sql = { package = &quot;varyk-sql&quot;, version = &quot;0.5&quot; }&lt;/code&gt; would be &lt;code&gt;sql::&lt;/code&gt; in your code, and two packages cannot share a name. A local module of the same name wins over a package. A dependency is a Varyk package when its folder has &lt;code&gt;src/lib.vr&lt;/code&gt;, whether it comes from a path, a registry, or git. A Rust crate is still never named from Varyk code: it is called from a &lt;code&gt;.rs&lt;/code&gt; facade, as before, and naming one is V0110.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Packages that use packages.&lt;/strong&gt; A package may use packages, to any depth: in the new examples, &lt;code&gt;trip&lt;/code&gt; uses &lt;code&gt;route&lt;/code&gt;, and &lt;code&gt;route&lt;/code&gt; uses &lt;code&gt;units&lt;/code&gt;. Each package sees only the packages its own &lt;code&gt;Cargo.toml&lt;/code&gt; lists. If &lt;code&gt;route&lt;/code&gt; gives you a &lt;code&gt;Meters&lt;/code&gt; of &lt;code&gt;units&lt;/code&gt; and your package lists &lt;code&gt;route&lt;/code&gt; but not &lt;code&gt;units&lt;/code&gt;, holding that value is V0115, and the help is the line to add. When cargo picks two versions of one package, they are two packages, and V0115 names both.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What a package gives you.&lt;/strong&gt; Everything it marks &lt;code&gt;pub&lt;/code&gt; that its users can reach: functions, structs with their &lt;code&gt;pub&lt;/code&gt; fields, enums, methods, and the &lt;code&gt;pub&lt;/code&gt; items of its &lt;code&gt;.rs&lt;/code&gt; modules. They behave like your own: parameters borrow, &lt;code&gt;mut&lt;/code&gt; parameters change the caller&#39;s value, an async function is awaited or started, and a &lt;code&gt;match&lt;/code&gt; on its enum is checked for every case. A library cannot hand out a type its users could not name, so a &lt;code&gt;pub&lt;/code&gt; function that returns a type of a private module is V0105 in the library itself. Two things stay inside a package: JSON and configuration conversions, so a &lt;code&gt;json&lt;/code&gt; or &lt;code&gt;env&lt;/code&gt; call on another package&#39;s type is V0210 (convert it in its own package), and its &lt;code&gt;#[test]&lt;/code&gt; functions. And when any package in a build writes log lines, the program sets up logging, so they are not lost.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What runs when you build.&lt;/strong&gt; Varyk is for services that face the network, so this release makes one promise about what runs on your machine. When &lt;code&gt;varyk build&lt;/code&gt;, &lt;code&gt;varyk run&lt;/code&gt;, or &lt;code&gt;varyk test&lt;/code&gt; builds your program, the Rust of every Varyk package in it is exactly that package&#39;s own &lt;code&gt;.rs&lt;/code&gt; files plus what your compiler generates from its &lt;code&gt;.vr&lt;/code&gt; files. Nothing else in the package is compiled or run: not its &lt;code&gt;build.rs&lt;/code&gt;, and not generated Rust its publisher shipped. &lt;code&gt;varyk&lt;/code&gt; asks cargo which packages the build uses, checks every Varyk package from its &lt;code&gt;.vr&lt;/code&gt; sources, and builds each as a crate of its own under &lt;code&gt;target/varyk/packages/&lt;/code&gt;. What runs is what a reader can review. The package&#39;s own &lt;code&gt;.rs&lt;/code&gt; files, the Rust crates it depends on, and their build scripts are Rust, visible as files and lines of &lt;code&gt;Cargo.toml&lt;/code&gt;, and rustc&#39;s to judge, as for your own code.&lt;/p&gt;
&lt;p&gt;The promise covers &lt;code&gt;build&lt;/code&gt;, &lt;code&gt;run&lt;/code&gt;, and &lt;code&gt;test&lt;/code&gt;, and the reference names the one command it does not: &lt;code&gt;varyk publish&lt;/code&gt;. &lt;code&gt;cargo publish&lt;/code&gt; verifies a crate by building it as a plain cargo user would, so publishing compiles a Varyk dependency&#39;s shipped Rust, and any &lt;code&gt;build.rs&lt;/code&gt; it was published with, on the publisher&#39;s machine. &lt;code&gt;--no-verify&lt;/code&gt; after &lt;code&gt;--&lt;/code&gt; skips that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is refused.&lt;/strong&gt; Cargo would build a Varyk package on its own, outside that promise, if it were reached any other way, so V0401 refuses a Varyk package under &lt;code&gt;[dev-dependencies]&lt;/code&gt;, one marked &lt;code&gt;optional&lt;/code&gt; that a feature turns on, and one reached through a Rust crate, even when it is also used the supported way. It also refuses a Varyk package with the same name and version as another Varyk package of the build, or as a package that comes from a &lt;code&gt;path&lt;/code&gt;. Naming a dependency marked &lt;code&gt;optional&lt;/code&gt; in Varyk code is V0401 too, because cargo may leave it out of the build.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Varyk builds Varyk.&lt;/strong&gt; A package&#39;s &lt;code&gt;Cargo.toml&lt;/code&gt; now names its &lt;code&gt;.vr&lt;/code&gt; root as cargo&#39;s target:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;bin&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;trip&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;path =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;src/main.vr&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or &lt;code&gt;[lib]&lt;/code&gt; with &lt;code&gt;path = &quot;src/lib.vr&quot;&lt;/code&gt; for a library. That is what lets cargo&#39;s own tools, such as &lt;code&gt;cargo add&lt;/code&gt;, &lt;code&gt;cargo update&lt;/code&gt;, and &lt;code&gt;cargo tree&lt;/code&gt;, read the package. &lt;code&gt;varyk init&lt;/code&gt; writes three files, &lt;code&gt;Cargo.toml&lt;/code&gt;, &lt;code&gt;.gitignore&lt;/code&gt;, and &lt;code&gt;src/main.vr&lt;/code&gt;, and no &lt;code&gt;build.rs&lt;/code&gt; and no stub, and &lt;code&gt;varyk emit&lt;/code&gt;, which the build script ran, is gone. A source package is built with &lt;code&gt;varyk build&lt;/code&gt;, not with plain &lt;code&gt;cargo build&lt;/code&gt;, since its root is Varyk, not Rust. A Varyk crate published with &lt;code&gt;varyk publish&lt;/code&gt; still carries its generated Rust, so a Rust project uses it with plain cargo, as any crate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New diagnostic codes.&lt;/strong&gt; V0115 is a value of a package your package does not list, or of another version of one it does. V0405 is cargo failing to work out which packages the build uses, for example a &lt;code&gt;path&lt;/code&gt; dependency whose folder is missing, with cargo&#39;s own message in the note. V0406 is a &lt;code&gt;Cargo.toml&lt;/code&gt; that does not name its &lt;code&gt;.vr&lt;/code&gt; root, with the lines to add. The &lt;a href=&quot;/learn/reference/#packages&quot;&gt;language reference&lt;/a&gt; has the new section, and the &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;error codes&lt;/a&gt; the full table.&lt;/p&gt;
&lt;p&gt;Two new example packages show it, and the &lt;a href=&quot;/learn/examples/#route&quot;&gt;examples&lt;/a&gt; page has them with their output: &lt;code&gt;route&lt;/code&gt;, a library whose legs have a length in &lt;code&gt;Meters&lt;/code&gt; of the package &lt;code&gt;units&lt;/code&gt;, and &lt;code&gt;trip&lt;/code&gt;, a program that uses both. This is &lt;code&gt;trip&lt;/code&gt;&#39;s &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;package&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;trip&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;version =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;0.1.0&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edition =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;2024&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;bin&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;trip&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;path =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;src/main.vr&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;route = { path =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;../route&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;units = { path =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;../units&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk-std =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;0.5.0&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and its &lt;code&gt;src/main.vr&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; legs &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        route::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;leg&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Mill&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;800&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        route::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;leg&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Mill&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Lake&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;900&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; sum &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; units::length::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;add&lt;/span&gt;&lt;span&gt;(route::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;total&lt;/span&gt;&lt;span&gt;(legs), units::length::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Meters&lt;/span&gt;&lt;span&gt; { value: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;0&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;total &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; meters&amp;quot;&lt;/span&gt;&lt;span&gt;, sum.value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; best &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; route::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;longest&lt;/span&gt;&lt;span&gt;(legs);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;longest &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; meters&amp;quot;&lt;/span&gt;&lt;span&gt;, best.from, best.to, best.length.value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    for&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;{&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;Lake&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: 12}&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Lake at noon&amp;quot;&lt;/span&gt;&lt;span&gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        match&lt;/span&gt;&lt;span&gt; route::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse_stop&lt;/span&gt;&lt;span&gt;(text) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;            Ok&lt;/span&gt;&lt;span&gt;(stop) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;stop &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; minutes&amp;quot;&lt;/span&gt;&lt;span&gt;, stop.name, stop.minutes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;            Err&lt;/span&gt;&lt;span&gt;(_) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;no stop&amp;quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; minutes &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; route::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;walking_minutes&lt;/span&gt;&lt;span&gt;(sum.value).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;about &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; minutes on foot&amp;quot;&lt;/span&gt;&lt;span&gt;, minutes);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It prints:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;total 1700 meters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;longest Mill to Lake, 900 meters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stop Lake, 12 minutes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;no stop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;about 21 minutes on foot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;route::longest&lt;/code&gt; gives back one of the legs it was given, not a copy, as a function of your own would, and &lt;code&gt;route::walking_minutes&lt;/code&gt; is an async function awaited across the package line. &lt;code&gt;trip&lt;/code&gt; writes no log line itself, but &lt;code&gt;route&lt;/code&gt; warns on stderr when it cannot read a stop, so the program sets up logging for it.&lt;/p&gt;
&lt;h2 id=&quot;the-breaking-changes&quot;&gt;The breaking changes&lt;/h2&gt;
&lt;p&gt;A package&#39;s &lt;code&gt;Cargo.toml&lt;/code&gt; must name its &lt;code&gt;.vr&lt;/code&gt; root, &lt;code&gt;[[bin]]&lt;/code&gt; with &lt;code&gt;path = &quot;src/main.vr&quot;&lt;/code&gt; or &lt;code&gt;[lib]&lt;/code&gt; with &lt;code&gt;path = &quot;src/lib.vr&quot;&lt;/code&gt;; without it, &lt;code&gt;varyk check&lt;/code&gt; reports V0406, and its help gives the lines. &lt;code&gt;varyk emit&lt;/code&gt; is removed. &lt;code&gt;varyk init&lt;/code&gt; no longer writes &lt;code&gt;build.rs&lt;/code&gt; or a stub, and a source package is built with &lt;code&gt;varyk build&lt;/code&gt;, not plain &lt;code&gt;cargo build&lt;/code&gt;. A &lt;code&gt;build.rs&lt;/code&gt; or &lt;code&gt;src/main.rs&lt;/code&gt; left by an earlier &lt;code&gt;varyk init&lt;/code&gt; is never read, so you can delete them. &lt;code&gt;build&lt;/code&gt; in &lt;code&gt;[package]&lt;/code&gt; may only be left out or &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The three crates, &lt;code&gt;varyk&lt;/code&gt;, &lt;code&gt;varyk-syntax&lt;/code&gt;, and &lt;code&gt;varyk-std&lt;/code&gt;, are released together as 0.5.0. After &lt;code&gt;cargo install varyk&lt;/code&gt;, run &lt;code&gt;varyk check&lt;/code&gt; in a package, and it says what to change.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 5b2 also redraws the rest of milestone 5. &lt;code&gt;varyk-std&lt;/code&gt; stays the small runtime every program has: &lt;code&gt;Error&lt;/code&gt;, tasks, &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;, and &lt;code&gt;log&lt;/code&gt;. Anything heavy, the HTTP server and client, SQL, MongoDB, Redis, is a package the writer adds, so a program that prints a line never compiles a web server or a database driver. Official packages are named &lt;code&gt;varyk-*&lt;/code&gt;, such as &lt;code&gt;varyk-sql&lt;/code&gt; and &lt;code&gt;varyk-http&lt;/code&gt;, and packages from the community &lt;code&gt;*-varyk&lt;/code&gt;. With packages in place, a battery is written once as a package, by this project or by anyone, and needs no work in the compiler.&lt;/p&gt;
&lt;p&gt;Milestone 5b3 is facades and &lt;code&gt;varyk-sql&lt;/code&gt;: what a &lt;code&gt;.rs&lt;/code&gt; facade can say, such as a function that takes or returns any Varyk data type, &lt;code&gt;pub use&lt;/code&gt;, and &lt;code&gt;varyk add&lt;/code&gt; shorthands for official packages; then &lt;code&gt;varyk-sql&lt;/code&gt; on sqlx, for SQLite, Postgres, and MySQL, where the query text is written in the program, so a query built from input is a compile error. Milestone 5b4 is &lt;code&gt;varyk-http&lt;/code&gt; and the golden path: an HTTP server with an explicit route table, an HTTP client, and the bar for all of milestone 5, a users API on a database that is &lt;code&gt;varyk init&lt;/code&gt;, &lt;code&gt;varyk add http sql&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has every item, and nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Try splitting a small service into packages and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.4.0: async functions and tasks</title>
        <published>2026-10-01T19:00:00+02:00</published>
        <updated>2026-10-01T19:00:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-4-0/"/>
        <id>https://varyk.com/blog/varyk-0-4-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-4-0/">&lt;p&gt;Varyk 0.4.0 is on crates.io. It is milestone 5b1 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, the second part of the batteries for services. Milestone 5a gave Varyk, a language for backend services that compiles to Rust, the data a service works with: JSON, configuration, logging, and tests. Milestone 5b1 adds the way a service waits: &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;.await&lt;/code&gt; on a built-in runtime, and tasks that run alongside each other, so that a handler can fetch three things at once instead of one after another.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;async fn&lt;/code&gt; and &lt;code&gt;.await&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;async&lt;/code&gt; before &lt;code&gt;fn&lt;/code&gt;, on a top-level function or a method, makes a function that can wait, and &lt;code&gt;.await&lt;/code&gt; after a call runs it and gives its result. Parameters still borrow by default, exactly as in any other function. &lt;code&gt;async fn main()&lt;/code&gt; runs on a built-in runtime, multi-threaded with one worker per core, and &lt;code&gt;#[test] async fn&lt;/code&gt; is a test that runs on a runtime of its own. Calling an async function from an ordinary one is an error, with a fix-it that adds &lt;code&gt;async&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Calls that start tasks.&lt;/strong&gt; There is no &lt;code&gt;spawn&lt;/code&gt;. A call to an async function followed by &lt;code&gt;.await&lt;/code&gt; runs in place; the same call without &lt;code&gt;.await&lt;/code&gt; starts the function at once and gives a task, a &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt; whose type is worked out from the call and never written, as calling an async function does in JavaScript. Two calls started one after the other really do overlap, and each is waited on later with &lt;code&gt;.await&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; late &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; slow&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;2&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; early &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Counter&lt;/span&gt;&lt;span&gt; { step: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt; }.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;next&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;6&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;fast then slow: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, early.&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;, late.&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It prints &lt;code&gt;fast then slow: 7 and 2&lt;/code&gt;: the call started second finishes first.&lt;/p&gt;
&lt;p&gt;A task that is dropped is cancelled, so no work outlives the code that started it unless you ask: a &lt;code&gt;?&lt;/code&gt; that returns early stops the tasks the function had started. &lt;code&gt;.detach()&lt;/code&gt; lets a task run on with nobody waiting for it. A started call whose task is thrown away, such as a bare &lt;code&gt;fetch_user(7);&lt;/code&gt;, is an error, so a forgotten &lt;code&gt;.await&lt;/code&gt; is caught by the compiler instead of turning into background work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Waiting on many.&lt;/strong&gt; &lt;code&gt;Task::all&lt;/code&gt; waits for a list of tasks and gives their results in order. When the tasks can fail, it gives the first error to arrive, as JavaScript&#39;s &lt;code&gt;Promise.all&lt;/code&gt; does, and, unlike it, cancels the tasks still running; &lt;code&gt;Task::all_settled&lt;/code&gt; waits for every task and keeps each outcome, as &lt;code&gt;Promise.allSettled&lt;/code&gt; does. A list of tasks comes from &lt;code&gt;vec!&lt;/code&gt; or from a chain: &lt;code&gt;ids.iter().map(|id| fetch(id)).collect()&lt;/code&gt; starts one task per id.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ownership without new syntax.&lt;/strong&gt; A started call may outlive the function that made it, so its arguments are given to the task: a number is copied, a value the function owns moves in, and a parameter, which belongs to the caller, needs &lt;code&gt;.clone()&lt;/code&gt;. That is the one place a value is handed over, so Varyk still has no ownership-transfer syntax, and the function itself still borrows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Shared&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;Shared::new(config)&lt;/code&gt; puts one struct where many tasks can read it, and &lt;code&gt;s.clone()&lt;/code&gt; gives each task a handle, not a copy. Fields and methods are reached straight through it, and nothing reached through it can be changed. Underneath it is Rust&#39;s &lt;code&gt;Arc&lt;/code&gt;; ten thousand tasks reading one configuration take ten thousand handles and one value.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;time::sleep&lt;/code&gt; and async Rust.&lt;/strong&gt; &lt;code&gt;time::sleep(ms)&lt;/code&gt; waits without holding up other tasks. &lt;code&gt;pub async fn&lt;/code&gt; and async methods in &lt;code&gt;.rs&lt;/code&gt; modules are imported like any other, and are awaited or started the same way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No &lt;code&gt;Send&lt;/code&gt; or &lt;code&gt;Pin&lt;/code&gt; to write.&lt;/strong&gt; Every type Varyk declares can move between threads, so the bounds Rust needs for a multi-threaded runtime never appear in Varyk code. A value from a &lt;code&gt;.rs&lt;/code&gt; module that cannot move to or be shared with another thread, such as one holding an &lt;code&gt;Rc&lt;/code&gt; or a &lt;code&gt;RefCell&lt;/code&gt;, is reported at the Varyk line that starts the task, as V0901, naming the Rust type.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New diagnostic codes.&lt;/strong&gt; V0211 is &lt;code&gt;.await&lt;/code&gt; or an async call outside an &lt;code&gt;async fn&lt;/code&gt;, V0212 an &lt;code&gt;.await&lt;/code&gt; on something that cannot wait, V0213 a task that would be thrown away, V0214 async functions that call each other in a cycle, V0215 a task used anywhere but where it is made, and V0216 a &lt;code&gt;Shared&lt;/code&gt; that is not a struct or is written where it cannot go. V0309 is a started call that would change a value the caller can never see, V0310 a change through a &lt;code&gt;Shared&lt;/code&gt;, V0311 an async function that returns part of a parameter, and V0901 the thread rule above. The &lt;a href=&quot;/learn/reference/#async-functions-and-tasks&quot;&gt;language reference&lt;/a&gt; has the section, and the &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;error codes&lt;/a&gt; the full table.&lt;/p&gt;
&lt;p&gt;Three new example programs show it in use, and the &lt;a href=&quot;/learn/examples/#tasks&quot;&gt;examples&lt;/a&gt; page has them with their output: &lt;code&gt;tasks&lt;/code&gt;, with calls that overlap, an async method, a detached task, and async tests; &lt;code&gt;fanout&lt;/code&gt;, which waits on calls that can fail with &lt;code&gt;Task::all&lt;/code&gt; and &lt;code&gt;Task::all_settled&lt;/code&gt;; and &lt;code&gt;shared&lt;/code&gt;, which gives one &lt;code&gt;Shared&lt;/code&gt; value to ten thousand tasks. This is &lt;code&gt;fanout.vr&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; price&lt;/span&gt;&lt;span&gt;(item: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    time::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;sleep&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; *&lt;/span&gt;&lt;span&gt; item &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; u64&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span&gt; item &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 3&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        return&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;no price for item &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, item)));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(item &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 12&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; prices&lt;/span&gt;&lt;span&gt;(items: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; found &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Task&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;all&lt;/span&gt;&lt;span&gt;(items.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;iter&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; price&lt;/span&gt;&lt;span&gt;(item)).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collect&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(found)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; good: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;4&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; bad: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;3&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; prices&lt;/span&gt;&lt;span&gt;(good).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(found) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;prices: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; + &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; + &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, found[&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;0&lt;/span&gt;&lt;span&gt;], found[&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;], found[&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;2&lt;/span&gt;&lt;span&gt;]),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;failed: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, e.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;message&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; prices&lt;/span&gt;&lt;span&gt;(bad).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(found) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;prices: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, found.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;len&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;failed: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, e.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;message&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; items: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;4&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; outcomes &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Task&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;all_settled&lt;/span&gt;&lt;span&gt;(items.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;iter&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; price&lt;/span&gt;&lt;span&gt;(item)).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collect&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; n: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    for&lt;/span&gt;&lt;span&gt; outcome &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span&gt; outcomes.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;iter&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        match&lt;/span&gt;&lt;span&gt; outcome {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;            Ok&lt;/span&gt;&lt;span&gt;(value) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;item &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, n, value),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;            Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;item &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; failed: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, n, e.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;message&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        n &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It prints:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prices: 12 + 24 + 48&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;failed: no price for item 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;item 1: 12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;item 2: 24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;item 3 failed: no price for item 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;item 4: 48&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;the-breaking-changes&quot;&gt;The breaking changes&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; were already reserved words, and now they are keywords. &lt;code&gt;Task&lt;/code&gt; and &lt;code&gt;Shared&lt;/code&gt; are reserved as &lt;code&gt;Error&lt;/code&gt; is: they cannot name a struct, an enum, a module, or a &lt;code&gt;use&lt;/code&gt;, nor a &lt;code&gt;pub&lt;/code&gt; struct or enum of a &lt;code&gt;.rs&lt;/code&gt; module. &lt;code&gt;time&lt;/code&gt; is reserved as &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;, and &lt;code&gt;log&lt;/code&gt; are: it cannot name a module, a struct, or an enum, or be brought in with &lt;code&gt;use&lt;/code&gt;. A program with its own struct named &lt;code&gt;Task&lt;/code&gt; renames it; the compiler&#39;s own &lt;code&gt;todo&lt;/code&gt; example now calls its struct &lt;code&gt;Item&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The three crates, &lt;code&gt;varyk&lt;/code&gt;, &lt;code&gt;varyk-syntax&lt;/code&gt;, and &lt;code&gt;varyk-std&lt;/code&gt;, are released together as 0.4.0. &lt;code&gt;varyk-std&lt;/code&gt; now holds the runtime too, so a program with an async &lt;code&gt;main&lt;/code&gt; needs it at the compiler&#39;s version: after &lt;code&gt;cargo install varyk&lt;/code&gt;, run &lt;code&gt;varyk check&lt;/code&gt;, and it says what to change.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 5b2 is HTTP and the database: an HTTP server on a proven Rust crate, with the application state every handler shares held in a &lt;code&gt;Shared&lt;/code&gt;, an HTTP client on the same stack, and databases through one API. It meets the bar for all of milestone 5: a users API on a database is &lt;code&gt;varyk init&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away, within fifteen minutes of &lt;code&gt;cargo install varyk&lt;/code&gt;. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has every item, and nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Try starting a few tasks in a small service and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.3.0: data, config, logging, and tests</title>
        <published>2026-10-01T10:00:00+02:00</published>
        <updated>2026-10-01T10:00:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-3-0/"/>
        <id>https://varyk.com/blog/varyk-0-3-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-3-0/">&lt;p&gt;Varyk 0.3.0 is on crates.io. It is milestone 5a of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, the first part of the batteries for services. Milestone 4 made the everyday code of a service easy to write in Varyk, a language for backend services that compiles to Rust. Milestone 5a adds what a service does with data before it talks to the network: read and write JSON, take its settings from the environment, write logs, and test itself.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;varyk-std&lt;/code&gt; and &lt;code&gt;Error&lt;/code&gt;.&lt;/strong&gt; A new crate, &lt;code&gt;varyk-std&lt;/code&gt;, is the one crate Varyk code reaches without a facade; every other crate is still reached through a &lt;code&gt;.rs&lt;/code&gt; file. It is behind &lt;code&gt;Error&lt;/code&gt;, a built-in error type with a message: &lt;code&gt;Error::new(&quot;...&quot;)&lt;/code&gt; makes one, &lt;code&gt;e.message()&lt;/code&gt; reads it, and it prints with &lt;code&gt;{}&lt;/code&gt;. Every standard call that can fail returns &lt;code&gt;Result&amp;lt;T, Error&amp;gt;&lt;/code&gt;, so &lt;code&gt;?&lt;/code&gt; works across all of them with no conversions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JSON, with attributes.&lt;/strong&gt; &lt;code&gt;json::parse&lt;/code&gt; reads a struct from JSON text and &lt;code&gt;json::stringify&lt;/code&gt; writes one. Structs, &lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;Vec&lt;/code&gt;, &lt;code&gt;HashMap&lt;/code&gt; with &lt;code&gt;string&lt;/code&gt; keys, and enums whose variants carry no data all go through. Three attributes adjust the keys: &lt;code&gt;#[rename(&quot;userName&quot;)]&lt;/code&gt; on a field or a variant, &lt;code&gt;#[default(18)]&lt;/code&gt; for a field the text leaves out, and &lt;code&gt;#[skip]&lt;/code&gt; for a field that is neither read nor written, such as a password hash. Varyk derives serde&#39;s traits only for the types a &lt;code&gt;json&lt;/code&gt; or &lt;code&gt;env&lt;/code&gt; call reaches, so a program that never calls &lt;code&gt;json&lt;/code&gt; or &lt;code&gt;env&lt;/code&gt; has no serde in it, and a type that cannot go through JSON is an error at the call.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configuration from the environment.&lt;/strong&gt; &lt;code&gt;let c: Config = env::parse()?;&lt;/code&gt; fills a struct from environment variables, then from a &lt;code&gt;.env&lt;/code&gt; file in the current directory, then from &lt;code&gt;#[default]&lt;/code&gt;. A field &lt;code&gt;database_url&lt;/code&gt; is read from &lt;code&gt;DATABASE_URL&lt;/code&gt;, and &lt;code&gt;#[rename]&lt;/code&gt; changes that. A variable that is not set, or does not read as its type, is an &lt;code&gt;Error&lt;/code&gt; that names it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Logging.&lt;/strong&gt; &lt;code&gt;log::debug&lt;/code&gt;, &lt;code&gt;log::info&lt;/code&gt;, &lt;code&gt;log::warn&lt;/code&gt;, and &lt;code&gt;log::error&lt;/code&gt; take a format string and arguments exactly as &lt;code&gt;println!&lt;/code&gt; does, and write a line to stderr. &lt;code&gt;LOG&lt;/code&gt; sets the level, &lt;code&gt;info&lt;/code&gt; when unset, and &lt;code&gt;LOG_FORMAT=json&lt;/code&gt; writes one JSON object per line instead of text, with no change to the code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tests.&lt;/strong&gt; A function marked &lt;code&gt;#[test]&lt;/code&gt; is a test, in any module, and &lt;code&gt;assert&lt;/code&gt; and &lt;code&gt;assert_eq&lt;/code&gt; check results inside one. &lt;code&gt;varyk test&lt;/code&gt; builds the program with its tests and runs them; &lt;code&gt;varyk build&lt;/code&gt; and &lt;code&gt;varyk run&lt;/code&gt; leave them out. A failing check names the Varyk file and line.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;varyk init&lt;/code&gt;, &lt;code&gt;varyk add&lt;/code&gt;, and the version check.&lt;/strong&gt; &lt;code&gt;varyk init&lt;/code&gt; now writes &lt;code&gt;varyk-std&lt;/code&gt; into &lt;code&gt;Cargo.toml&lt;/code&gt; at the compiler&#39;s own version, and &lt;code&gt;.env&lt;/code&gt; into &lt;code&gt;.gitignore&lt;/code&gt;, so a local secrets file is never committed. &lt;code&gt;varyk add&lt;/code&gt; runs &lt;code&gt;cargo add&lt;/code&gt; in the package with the arguments you give. &lt;code&gt;varyk check&lt;/code&gt; reads the &lt;code&gt;varyk-std&lt;/code&gt; line and &lt;code&gt;Cargo.lock&lt;/code&gt;, and when they do not match the compiler it says so as V0404, with the line to write or &lt;code&gt;cargo update -p varyk-std&lt;/code&gt; to run.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New diagnostic codes.&lt;/strong&gt; V0112 is an attribute Varyk does not have, or one in a place it cannot go. V0113 is a reserved name. V0114 is a test with parameters or a return type, a call to a test, or &lt;code&gt;assert&lt;/code&gt; outside a test. V0209 is an attribute value that does not fit, and V0210 a type that cannot go through JSON or the environment. V0404 is the &lt;code&gt;varyk-std&lt;/code&gt; version check. The &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;language reference&lt;/a&gt; has the full table.&lt;/p&gt;
&lt;p&gt;Three new example programs and a new package show it in use, and the &lt;a href=&quot;/learn/examples/&quot;&gt;examples&lt;/a&gt; page has them with their output. The &lt;code&gt;users&lt;/code&gt; package puts them together: a store of users read from JSON, configuration from a &lt;code&gt;.env&lt;/code&gt; file, logging, and three tests. This is &lt;code&gt;json.vr&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;enum&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Role&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Admin&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[rename(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;member&amp;quot;&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Member&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u32&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[rename(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;userName&amp;quot;&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user_name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    role: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Role&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    nickname: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tags: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[default(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;18&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    age: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;u8&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    #[skip]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    password_hash: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; role_name&lt;/span&gt;&lt;span&gt;(role: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Role&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; role {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Role&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Admin&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;admin&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Role&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;member&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; load&lt;/span&gt;&lt;span&gt;(body: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; u: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; json::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;(body)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(u)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;{&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: 7, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;userName&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;ann&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;], &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;password_hash&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;}&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; load&lt;/span&gt;&lt;span&gt;(text) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(u) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;            println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{} {} {}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, u.id, u.user_name, &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;role_name&lt;/span&gt;&lt;span&gt;(u.role));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;            println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; tags, age &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, nickname: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, u.tags.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;len&lt;/span&gt;&lt;span&gt;(), u.age, u.nickname.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_some&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;            println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, json::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;stringify&lt;/span&gt;&lt;span&gt;(u));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;error: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, e),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; bad &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;{&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: 1, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;userName&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;bo&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;Admin&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: [], &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: 300}&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; load&lt;/span&gt;&lt;span&gt;(bad) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(u) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, u.id),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(e) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;error: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, e),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It prints:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7 ann member&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2 tags, age 18, nickname: false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&amp;quot;id&amp;quot;:7,&amp;quot;userName&amp;quot;:&amp;quot;ann&amp;quot;,&amp;quot;role&amp;quot;:&amp;quot;member&amp;quot;,&amp;quot;nickname&amp;quot;:null,&amp;quot;tags&amp;quot;:[&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;],&amp;quot;age&amp;quot;:18}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error: invalid value: integer `300`, expected u8 at line 1 column 67&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;the-breaking-changes&quot;&gt;The breaking changes&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;s.parse()&lt;/code&gt; returns &lt;code&gt;Result&amp;lt;T, Error&amp;gt;&lt;/code&gt; instead of &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt;, so &lt;code&gt;?&lt;/code&gt; works on it in a function that returns &lt;code&gt;Result&amp;lt;_, Error&amp;gt;&lt;/code&gt;, and the error names the text. Code that wanted the old &lt;code&gt;Option&lt;/code&gt; writes two statements, since the expected type does not reach a method&#39;s receiver:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; r: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i32&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; text.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; r.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;ok&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The new names are reserved: &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;, and &lt;code&gt;log&lt;/code&gt; cannot name a module, a struct, an enum, or a &lt;code&gt;use&lt;/code&gt;; &lt;code&gt;Error&lt;/code&gt; cannot name a struct, an enum, a module, or a &lt;code&gt;use&lt;/code&gt;; &lt;code&gt;assert&lt;/code&gt; and &lt;code&gt;assert_eq&lt;/code&gt; cannot name a function; and no function, method, struct, enum, module, or &lt;code&gt;use&lt;/code&gt; name may start with &lt;code&gt;varyk_&lt;/code&gt;, which is kept for what the compiler adds to the Rust it writes. Local variables and fields may still use any of these names.&lt;/p&gt;
&lt;p&gt;The three crates, &lt;code&gt;varyk&lt;/code&gt;, &lt;code&gt;varyk-syntax&lt;/code&gt;, and &lt;code&gt;varyk-std&lt;/code&gt;, are released together as 0.3.0. A package that uses &lt;code&gt;varyk-std&lt;/code&gt; needs it in &lt;code&gt;[dependencies]&lt;/code&gt; at the compiler&#39;s version: after &lt;code&gt;cargo install varyk&lt;/code&gt;, run &lt;code&gt;varyk check&lt;/code&gt;, and it says what to change.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 5 is now three milestones. Milestone 5b1 is &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; on a built-in runtime and &lt;code&gt;spawn&lt;/code&gt;, gated on two open questions, the runtime shape and ownership-transfer syntax. Milestone 5b2 is HTTP and the database: an HTTP server and client on one stack, and databases through one API. The bar for all three is one golden path: a users API on a database is &lt;code&gt;varyk init&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away, within fifteen minutes of &lt;code&gt;cargo install varyk&lt;/code&gt;. It is met at the end of 5b2. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has every item, and nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Try writing one small service and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.2.0: closures, iterators, and patterns</title>
        <published>2026-09-29T00:00:00+00:00</published>
        <updated>2026-09-29T00:00:00+00:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-2-0/"/>
        <id>https://varyk.com/blog/varyk-0-2-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-2-0/">&lt;p&gt;Varyk 0.2.0 is on crates.io. It is milestone 4 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, and it is about the language: the everyday code of a service that milestone 3 made awkward. Milestone 3 connected Varyk, a language for backend services that compiles to Rust, to Cargo and the Rust ecosystem. Milestone 4 adds closures, chains over collections, richer patterns, &lt;code&gt;HashMap&lt;/code&gt;, and functions that return part of what they are given without a copy.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Closures, as the argument of a call.&lt;/strong&gt; &lt;code&gt;|n| n * 2&lt;/code&gt; works as the argument of &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;map_err&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;any&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt;, and &lt;code&gt;find&lt;/code&gt;. A closure has one parameter with no type written, reads the names around it, and never changes them. It is never a value of its own: a closure in a &lt;code&gt;let&lt;/code&gt;, passed to a Varyk function, or returned is an error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chains.&lt;/strong&gt; A chain starts at &lt;code&gt;v.iter()&lt;/code&gt;, &lt;code&gt;s.split(sep)&lt;/code&gt;, &lt;code&gt;m.keys()&lt;/code&gt;, or &lt;code&gt;m.values()&lt;/code&gt;, passes through any number of &lt;code&gt;map&lt;/code&gt;s and &lt;code&gt;filter&lt;/code&gt;s, and ends at &lt;code&gt;collect&lt;/code&gt;, &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;sum&lt;/code&gt;, &lt;code&gt;any&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt;, or &lt;code&gt;find&lt;/code&gt;, or as the head of a &lt;code&gt;for&lt;/code&gt;. In the generated Rust it is written as it is.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; evens &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; numbers.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;iter&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;filter&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 2&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; ==&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 0&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;count&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;let&lt;/span&gt;&lt;span&gt; names: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; users.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;iter&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt;u&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt; u.name.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collect&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Patterns.&lt;/strong&gt; &lt;code&gt;if let&lt;/code&gt; and &lt;code&gt;while let&lt;/code&gt;; variants with named fields, &lt;code&gt;Event::Click { x: 0, y }&lt;/code&gt;; nested patterns, &lt;code&gt;Some(Shape::Circle(r))&lt;/code&gt;; literals and &lt;code&gt;..=&lt;/code&gt; ranges, &lt;code&gt;90..=100&lt;/code&gt;; and &lt;code&gt;match&lt;/code&gt; on numbers, &lt;code&gt;bool&lt;/code&gt;, and strings. Varyk checks that every value fits an arm (V0204) and that every arm can run (V0205), and the error names a value no arm fits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;HashMap&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt; on &lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;as&lt;/code&gt;, and &lt;code&gt;parse&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;HashMap&lt;/code&gt; has &lt;code&gt;insert&lt;/code&gt;, &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;contains_key&lt;/code&gt;, &lt;code&gt;len&lt;/code&gt;, &lt;code&gt;keys&lt;/code&gt;, and &lt;code&gt;values&lt;/code&gt;. &lt;code&gt;?&lt;/code&gt; now works on an &lt;code&gt;Option&lt;/code&gt; in a function returning one. &lt;code&gt;as&lt;/code&gt; converts between number types with Rust&#39;s rules, &lt;code&gt;s.parse()&lt;/code&gt; gives an &lt;code&gt;Option&lt;/code&gt;, and &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt; get their first methods: &lt;code&gt;is_some&lt;/code&gt;, &lt;code&gt;is_ok&lt;/code&gt;, &lt;code&gt;is_err&lt;/code&gt;, &lt;code&gt;unwrap_or&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;ok_or&lt;/code&gt;, &lt;code&gt;ok&lt;/code&gt;, and &lt;code&gt;map_err&lt;/code&gt;. There is still no &lt;code&gt;unwrap&lt;/code&gt; or &lt;code&gt;expect&lt;/code&gt;: a value that is absent is something to handle, not a reason to stop the program.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;.clone()&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt; on your own types.&lt;/strong&gt; A struct or enum whose fields allow it gets &lt;code&gt;Clone&lt;/code&gt; and &lt;code&gt;PartialEq&lt;/code&gt; derived, so &lt;code&gt;.clone()&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt; work on it, and derives read from an imported Rust type count too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Getters without copies.&lt;/strong&gt; A function may return part of one of its parameters, and nothing is written for it: Varyk sees from the body that every return is part of the same parameter. &lt;code&gt;display_name&lt;/code&gt; needed a &lt;code&gt;.clone()&lt;/code&gt; in milestone 3; now the generated Rust returns a reference into &lt;code&gt;self&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; display_name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; self&lt;/span&gt;&lt;span&gt;.nickname.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_empty&lt;/span&gt;&lt;span&gt;() { &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span&gt;.name } &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;else&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span&gt;.nickname }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; display_name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt; &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;str&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    if&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; self&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span&gt;nickname&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_empty&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span&gt;nickname&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result is another name for part of the value passed in, like a field, so that value cannot change while the result is used. A Rust function in a &lt;code&gt;.rs&lt;/code&gt; file whose elided lifetime ties its result to one parameter, such as &lt;code&gt;fn first_word(s: &amp;amp;str) -&amp;gt; &amp;amp;str&lt;/code&gt;, imports the same way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New diagnostic codes.&lt;/strong&gt; V0208 is a value that must be used where it is made: the &lt;code&gt;Option&lt;/code&gt; of &lt;code&gt;get&lt;/code&gt; on a stored value, which is looked into right there with &lt;code&gt;match&lt;/code&gt; or &lt;code&gt;if let&lt;/code&gt;, or a chain left unfinished. V0308 is a function returning part of one parameter in one place and part of another in another. The &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;language reference&lt;/a&gt; has the full table.&lt;/p&gt;
&lt;p&gt;Six new example programs show it in use, and the &lt;a href=&quot;/learn/examples/&quot;&gt;examples&lt;/a&gt; page has them with their output. This is &lt;code&gt;words.vr&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; text &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;the cat saw the dog and the cat ran&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; counts: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; HashMap&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    for&lt;/span&gt;&lt;span&gt; word &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span&gt; text.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        let&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; counts.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;get&lt;/span&gt;&lt;span&gt;(word).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;unwrap_or&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;0&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        counts.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;insert&lt;/span&gt;&lt;span&gt;(word.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;(), n);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; words: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span&gt; counts.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;keys&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt;w&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;|&lt;/span&gt;&lt;span&gt; w.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;clone&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;collect&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    words.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;sort&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    for&lt;/span&gt;&lt;span&gt; word &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span&gt; words {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        if let&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Some&lt;/span&gt;&lt;span&gt;(n) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; counts.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;get&lt;/span&gt;&lt;span&gt;(word) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;            println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{} {}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, word, n);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; distinct words&amp;quot;&lt;/span&gt;&lt;span&gt;, counts.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;len&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;the-breaking-change&quot;&gt;The breaking change&lt;/h2&gt;
&lt;p&gt;The breaking change is in the &lt;code&gt;varyk-syntax&lt;/code&gt; crate, not in Varyk: its syntax tree gained new expressions, statements, and patterns, and Rust code that matches on that tree must handle them. Every program in the compiler&#39;s examples and tests that 0.1.0 accepted is still accepted.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 5 is the batteries for services: HTTP, JSON, databases, configuration, logging, &lt;code&gt;varyk test&lt;/code&gt;, and &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; on a built-in runtime, with one golden path as the bar, a users API on a database that is &lt;code&gt;varyk init&lt;/code&gt;, one file, and &lt;code&gt;varyk run&lt;/code&gt; away. &lt;code&gt;varyk fmt&lt;/code&gt; and the interop items once planned for milestone 4 moved to milestones 5 and 6. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has every item, and nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Try writing one small service and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.1.0: packages and interop</title>
        <published>2026-09-27T14:00:00+02:00</published>
        <updated>2026-09-27T14:00:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-1-0/"/>
        <id>https://varyk.com/blog/varyk-0-1-0/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-1-0/">&lt;p&gt;Varyk 0.1.0 is on crates.io. It is milestone 3 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, and it connects Varyk, a language for backend services that compiles to Rust, to the Rust ecosystem. Milestones 1 and 2 made a single &lt;code&gt;.vr&lt;/code&gt; file, with the modules it declares, into a running program. Milestone 3 makes Varyk code a Cargo package, with a &lt;code&gt;Cargo.toml&lt;/code&gt;, crates from crates.io called through a &lt;code&gt;.rs&lt;/code&gt; facade, modules at any depth, &lt;code&gt;use&lt;/code&gt;, private fields, Rust structs and enums imported from &lt;code&gt;.rs&lt;/code&gt; modules, plain &lt;code&gt;cargo build&lt;/code&gt; through a &lt;code&gt;build.rs&lt;/code&gt;, and publishing to crates.io as a crate whose consumers need only cargo.&lt;/p&gt;
&lt;p&gt;The minor version moved because one rule changed. Until 1.0, a breaking change bumps the minor version, and this release has one, described below.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;A Varyk package is a Cargo package.&lt;/strong&gt; Its crate root is &lt;code&gt;src/main.vr&lt;/code&gt; for a binary or &lt;code&gt;src/lib.vr&lt;/code&gt; for a library, &lt;code&gt;Cargo.toml&lt;/code&gt; is the only manifest, and it must say &lt;code&gt;edition = &quot;2024&quot;&lt;/code&gt; (V0400 otherwise). &lt;code&gt;varyk check&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;, and &lt;code&gt;run&lt;/code&gt; with no file argument find the package from the current directory. &lt;code&gt;varyk init&lt;/code&gt; writes the package and a &lt;code&gt;build.rs&lt;/code&gt;, so plain &lt;code&gt;cargo build&lt;/code&gt; and &lt;code&gt;cargo run&lt;/code&gt; work too, with &lt;code&gt;varyk&lt;/code&gt; on the &lt;code&gt;PATH&lt;/code&gt; (or &lt;code&gt;$VARYK&lt;/code&gt; naming it), and CI for the compiler asserts that both give the same output. &lt;code&gt;build.rs&lt;/code&gt; calls the new &lt;code&gt;varyk emit&lt;/code&gt;, which writes the generated Rust tree to a directory without running cargo. Single-file mode, &lt;code&gt;varyk run hello.vr&lt;/code&gt;, is unchanged.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Modules at any depth.&lt;/strong&gt; A module may declare modules; children live in a directory named after their parent, as &lt;code&gt;shop.vr&lt;/code&gt; and &lt;code&gt;shop/mod.vr&lt;/code&gt; alike, and paths with &lt;code&gt;crate::&lt;/code&gt;, &lt;code&gt;self::&lt;/code&gt;, or &lt;code&gt;super::&lt;/code&gt; resolve everywhere a path can appear. Visibility is Rust&#39;s: a module or item without &lt;code&gt;pub&lt;/code&gt; is visible in its declaring module and that module&#39;s descendants, and a &lt;code&gt;pub&lt;/code&gt; item may not name a type its users cannot see.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;use&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;use crate::shop::cart::Cart;&lt;/code&gt; and &lt;code&gt;use shop::cart as c;&lt;/code&gt; alias modules, structs, enums, and functions inside the package. A &lt;code&gt;use&lt;/code&gt; cannot start with the name of a crate, &lt;code&gt;std&lt;/code&gt; included, which brings us to dependencies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cargo dependencies.&lt;/strong&gt; &lt;code&gt;cargo add&lt;/code&gt; works unchanged. A crate is called from a Rust file in the same package, which exposes the plain functions and types your Varyk uses, imported the way Rust functions have been since milestone 1. The docs call that file a &lt;em&gt;facade&lt;/em&gt;. Most crate APIs are generic, and Varyk has no generics in its surface, so the facade is where the concrete API gets written, and a package with its facade publishes as a plain crate. Whether Varyk code should ever &lt;code&gt;use&lt;/code&gt; a crate directly, with no facade, is an experiment for after traits exist; it is recorded as an open question in the specification and as unscheduled on the roadmap.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rust structs, methods, and enums import.&lt;/strong&gt; A non-generic &lt;code&gt;pub struct&lt;/code&gt; with named fields in a &lt;code&gt;.rs&lt;/code&gt; module becomes a Varyk struct, its inherent &lt;code&gt;pub fn&lt;/code&gt;s become methods, and &lt;code&gt;&amp;amp;self&lt;/code&gt; and &lt;code&gt;&amp;amp;mut self&lt;/code&gt; map to &lt;code&gt;self&lt;/code&gt; and &lt;code&gt;mut self&lt;/code&gt;. A field whose Rust type Varyk cannot map is present but unusable, with an error that names the type. Enums with unit and tuple variants import too (their methods not yet), and Varyk checks that a &lt;code&gt;match&lt;/code&gt; on one covers every variant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Errors from rustc point at the right file.&lt;/strong&gt; An error or warning rustc reports in one of your own &lt;code&gt;.rs&lt;/code&gt; files is shown at your file and line, unchanged, as rustc worded it. The Rust Varyk generates should never be rejected; if it is, the backend&#39;s line-level source map reports it as V0900 at the Varyk line that produced it, carrying rustc&#39;s message and asking you to report it as a bug. Warnings are allowed per generated item, so your own &lt;code&gt;.rs&lt;/code&gt; files warn normally, and &lt;code&gt;--message-format=json&lt;/code&gt; carries those warnings too; under &lt;code&gt;varyk run&lt;/code&gt;, whose standard output is the program&#39;s own, the JSON goes to standard error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Publishing.&lt;/strong&gt; &lt;code&gt;varyk publish&lt;/code&gt; runs the full check, assembles a plain Rust crate with the generated &lt;code&gt;.rs&lt;/code&gt; files, the &lt;code&gt;.vr&lt;/code&gt; sources beside them, and no &lt;code&gt;build.rs&lt;/code&gt;, and runs &lt;code&gt;cargo publish&lt;/code&gt; there, passing on anything after &lt;code&gt;--&lt;/code&gt;. Binaries and libraries both publish. A consumer that only has cargo adds a published Varyk library like any crate, and &lt;code&gt;cargo install&lt;/code&gt; of a published Varyk binary works like any other. &lt;code&gt;varyk publish --assemble-only&lt;/code&gt; stops after the assembly and publishes nothing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New diagnostic codes.&lt;/strong&gt; V0110 is a &lt;code&gt;use&lt;/code&gt; naming a crate; call it from a &lt;code&gt;.rs&lt;/code&gt; module instead. V0111 is a path Varyk cannot follow, such as &lt;code&gt;super&lt;/code&gt; in the entry file or a &lt;code&gt;use&lt;/code&gt; ending at an enum variant. V0400 to V0403 are about &lt;code&gt;Cargo.toml&lt;/code&gt;: an edition other than 2024, a workspace setting or platform-only dependencies, a &lt;code&gt;path&lt;/code&gt; in a target table, and a manifest that cannot be used. V0900 is the generated-Rust error above. The &lt;a href=&quot;/learn/reference/#error-codes&quot;&gt;language reference&lt;/a&gt; has the full table.&lt;/p&gt;
&lt;p&gt;The three milestone-3 example packages are in the compiler&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/tree/main/examples/packages&quot;&gt;examples&lt;/a&gt;: &lt;code&gt;greeting&lt;/code&gt;, a binary built by &lt;code&gt;varyk run&lt;/code&gt; and by &lt;code&gt;cargo run&lt;/code&gt;; &lt;code&gt;matcher&lt;/code&gt;, a facade over a registry crate with a struct, methods, and an enum imported into Varyk; and &lt;code&gt;units&lt;/code&gt;, a library assembled by &lt;code&gt;varyk publish --assemble-only&lt;/code&gt; and used by a cargo-only consumer.&lt;/p&gt;
&lt;p&gt;This is &lt;code&gt;matcher&lt;/code&gt;. &lt;code&gt;Cargo.toml&lt;/code&gt; names the crate:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;package&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;matcher&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;version =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;0.1.0&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edition =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;2024&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;regex-lite =&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;0.1&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;src/text.rs&lt;/code&gt; is the facade:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// A facade: Varyk code never names a crate, so this file wraps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// `regex_lite` in a struct, methods, and an enum Varyk can import.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Matcher&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    re&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; regex_lite&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Regex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Matcher&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; new&lt;/span&gt;&lt;span&gt;(pattern&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;str&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Matcher&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        let&lt;/span&gt;&lt;span&gt; re&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; regex_lite&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Regex&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(pattern)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;the pattern should be a valid regex&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Matcher&lt;/span&gt;&lt;span&gt; { re }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; is_match&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span&gt;, s&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;str&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; bool&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        self&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span&gt;re&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_match&lt;/span&gt;&lt;span&gt;(s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; count&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;self&lt;/span&gt;&lt;span&gt;, s&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;str&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; usize&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1&quot;&gt;        self&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span&gt;re&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;find_iter&lt;/span&gt;&lt;span&gt;(s)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;count&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub enum&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Kind&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Word&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Number&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;i32&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; classify&lt;/span&gt;&lt;span&gt;(s&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;str&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Kind&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;    // Deliberately unused: rustc&amp;#39;s warning about it shows through&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;    // `varyk build` at this file and line, as Rust warnings do.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; trimmed&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span&gt; s&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;trim&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; s&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;i32&lt;/span&gt;&lt;span&gt;&amp;gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(n)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Kind&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Number&lt;/span&gt;&lt;span&gt;(n),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Err&lt;/span&gt;&lt;span&gt;(_)&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Kind&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Word&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;code&gt;src/main.vr&lt;/code&gt; uses it like any Varyk module:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// expected output:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// apple: word, 0 digit runs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// 42: the number 42, 1 digit runs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// route 66 or 101: word, 2 digit runs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-5&quot;&gt;// 2 of 3 contain digits&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;mod&lt;/span&gt;&lt;span&gt; text;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; describe&lt;/span&gt;&lt;span&gt;(kind: text::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Kind&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; string&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; kind {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        text::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Kind&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Word&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;word&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        text::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Kind&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Number&lt;/span&gt;&lt;span&gt;(n) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;the number &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, n),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; digits &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; text::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Matcher&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;[0-9]+&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; inputs: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;gt; =&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inputs.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;apple&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inputs.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;42&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inputs.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;route 66 or 101&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; with_digits: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    for&lt;/span&gt;&lt;span&gt; s &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span&gt; inputs {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        if&lt;/span&gt;&lt;span&gt; digits.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;is_match&lt;/span&gt;&lt;span&gt;(s) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            with_digits &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span&gt; with_digits &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; digit runs&amp;quot;&lt;/span&gt;&lt;span&gt;, s, &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;describe&lt;/span&gt;&lt;span&gt;(text::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;classify&lt;/span&gt;&lt;span&gt;(s)), digits.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;count&lt;/span&gt;&lt;span&gt;(s));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; of &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; contain digits&amp;quot;&lt;/span&gt;&lt;span&gt;, with_digits, inputs.&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;len&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;varyk run&lt;/code&gt; in the package prints rustc&#39;s warning that &lt;code&gt;trimmed&lt;/code&gt; is unused, at &lt;code&gt;src/text.rs&lt;/code&gt; line 31, which the example keeps on purpose to show a warning in your own Rust, and then the four lines of output.&lt;/p&gt;
&lt;h2 id=&quot;the-breaking-change-fields-are-private-unless-pub&quot;&gt;The breaking change: fields are private unless &lt;code&gt;pub&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In milestone 2 every field of a &lt;code&gt;pub struct&lt;/code&gt; was public. From 0.1.0 a field follows the same rule as everything else: private unless &lt;code&gt;pub&lt;/code&gt;, visible in the struct&#39;s own module and its descendants, which includes the struct&#39;s own methods.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;pub struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    pub&lt;/span&gt;&lt;span&gt; name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    age: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;i32&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reading, assigning, or naming a private field from another module is an error with a note offering both ways out, &lt;code&gt;pub&lt;/code&gt; on the field or a &lt;code&gt;pub fn&lt;/code&gt;, because making every field public is often the wrong fix. The milestone-2 examples needed no source changes when the rule landed, because none of their fields crossed a module boundary; if yours do, add &lt;code&gt;pub&lt;/code&gt; to the fields other modules read.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk init hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cd hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there, and the &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Milestone 4 is closures, iterators, &lt;code&gt;if let&lt;/code&gt;, &lt;code&gt;HashMap&lt;/code&gt;, borrowed return values, and &lt;code&gt;varyk fmt&lt;/code&gt;, and more interop: nested modules in &lt;code&gt;.rs&lt;/code&gt; files, Rust tuple and unit structs, derives on imported Rust structs usable from Varyk, &lt;code&gt;.rs&lt;/code&gt; signatures naming Varyk types, and importing a published Varyk library straight into Varyk code. Milestone 5 is the batteries for services: HTTP, JSON, databases, configuration, logging, tests, and &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; on a built-in runtime. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has every item, and nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0. Try building one small package and tell us where it hurts: the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Varyk 0.0.2: enums, matching, methods, and collections</title>
        <published>2026-09-26T00:00:00+00:00</published>
        <updated>2026-09-26T00:00:00+00:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/varyk-0-0-2/"/>
        <id>https://varyk.com/blog/varyk-0-0-2/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/varyk-0-0-2/">&lt;p&gt;Varyk 0.0.2 is on crates.io. Varyk is a language for backend services that compiles to Rust, and this release, milestone 2 of the &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt;, brings the language core a small program needs. Milestone 1 proved borrow-by-default on six programs; this release adds enums and &lt;code&gt;match&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, methods, &lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;Result&lt;/code&gt;, &lt;code&gt;Vec&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;format!&lt;/code&gt;, and a deliberate string copy, and it keeps every milestone-1 rule. Calls never write &lt;code&gt;&amp;amp;&lt;/code&gt;, mutation is declared with &lt;code&gt;mut&lt;/code&gt;, and the compiler adds no allocation except a string literal stored into a value you own and the copy you ask for with &lt;code&gt;.clone()&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;enum&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; Shape&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Circle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;f64&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Rect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;f64&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;f64&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    Point&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; area&lt;/span&gt;&lt;span&gt;(shape: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Shape&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; f64&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    match&lt;/span&gt;&lt;span&gt; shape {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Shape&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Circle&lt;/span&gt;&lt;span&gt;(radius) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 3.14&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; *&lt;/span&gt;&lt;span&gt; radius &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;*&lt;/span&gt;&lt;span&gt; radius,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Shape&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Rect&lt;/span&gt;&lt;span&gt;(w, h) &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; w &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;*&lt;/span&gt;&lt;span&gt; h,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        Shape&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt; 0.0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let&lt;/span&gt;&lt;span&gt; shapes &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; vec!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Shape&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Circle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;1.0&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Shape&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Rect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;2.0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;3.0&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Shape&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;Point&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    for&lt;/span&gt;&lt;span&gt; shape &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;in&lt;/span&gt;&lt;span&gt; shapes {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;        println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;area&lt;/span&gt;&lt;span&gt;(shape));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It prints &lt;code&gt;3.14&lt;/code&gt;, &lt;code&gt;6&lt;/code&gt;, and &lt;code&gt;0&lt;/code&gt;. Every new construct follows the same idea as the old ones: you write what the program does, and the compiler decides how the value is passed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enums&lt;/strong&gt; with unit and tuple variants, and &lt;code&gt;match&lt;/code&gt; on enums, &lt;code&gt;Option&lt;/code&gt;, and &lt;code&gt;Result&lt;/code&gt; with one-level patterns. Varyk checks the arms itself, so a &lt;code&gt;match&lt;/code&gt; that forgets a variant is a plain-word error before cargo runs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;for&lt;/code&gt;&lt;/strong&gt; over integer ranges and over a &lt;code&gt;Vec&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;impl&lt;/code&gt; blocks&lt;/strong&gt; with &lt;code&gt;self&lt;/code&gt; and &lt;code&gt;mut self&lt;/code&gt; methods and associated functions. A method that reads &lt;code&gt;self&lt;/code&gt; borrows it; one that writes &lt;code&gt;mut self&lt;/code&gt; borrows it mutably, and the caller sees the change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;Result&lt;/code&gt;, and &lt;code&gt;Vec&lt;/code&gt;&lt;/strong&gt; in types, written as in Rust, with &lt;code&gt;Some&lt;/code&gt;, &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;Ok&lt;/code&gt;, &lt;code&gt;Err&lt;/code&gt;, &lt;code&gt;Vec::new()&lt;/code&gt;, &lt;code&gt;vec!&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt;, &lt;code&gt;len&lt;/code&gt;, and indexing. &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;Vec::new()&lt;/code&gt;, &lt;code&gt;Ok&lt;/code&gt;, and &lt;code&gt;Err&lt;/code&gt; take their type from where they go, the way an integer literal does.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;?&lt;/code&gt;&lt;/strong&gt; on a &lt;code&gt;Result&lt;/code&gt; whose error type is the function&#39;s own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;format!&lt;/code&gt;&lt;/strong&gt; for building strings. &lt;code&gt;+&lt;/code&gt; on strings is rejected with a fix-it that says to use it, so every allocation is visible at the call.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;usize&lt;/code&gt;&lt;/strong&gt; for lengths and indexes, matching rustc&#39;s types.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;s.clone()&lt;/code&gt;&lt;/strong&gt; on a string: the one explicit copy, Rust&#39;s own spelling, with the cost visible where it happens. It answers an open question from milestone 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Matching and iterating borrow, like everything else. A &lt;code&gt;match&lt;/code&gt; on a place never moves it; a name bound by a pattern, or the loop variable of a &lt;code&gt;for&lt;/code&gt; over a &lt;code&gt;Vec&lt;/code&gt;, is an &lt;em&gt;alias&lt;/em&gt; of part of the value, and changing or giving away the whole while an alias is still in use is an error. Milestone 1 had this rule implicitly and one bug around it; milestone 2 states it and applies it everywhere.&lt;/p&gt;
&lt;p&gt;The six milestone-2 programs are in the compiler&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/tree/main/examples&quot;&gt;examples&lt;/a&gt;, including a small &lt;code&gt;todo&lt;/code&gt; program with a &lt;code&gt;Task&lt;/code&gt; struct, a &lt;code&gt;Status&lt;/code&gt; enum, methods, and &lt;code&gt;format!&lt;/code&gt;, spread over two files. The &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts today; the reference as it stood at this release, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/blob/varyk-v0.0.2/docs/language.md#not-in-milestone-2&quot;&gt;&lt;code&gt;docs/language.md&lt;/code&gt; at the &lt;code&gt;varyk-v0.0.2&lt;/code&gt; tag&lt;/a&gt;, has a section &quot;Not in milestone 2&quot; that lists what 0.0.2 rejects and why: enum variants with named fields, nested and literal patterns, methods on &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt;, closures, iterators, &lt;code&gt;if let&lt;/code&gt;, &lt;code&gt;HashMap&lt;/code&gt;, and returning part of a borrowed value, which stays a &lt;code&gt;.clone()&lt;/code&gt; until milestone 4.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run enums.vr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there.&lt;/p&gt;
&lt;h2 id=&quot;the-roadmap-renumbered&quot;&gt;The roadmap, renumbered&lt;/h2&gt;
&lt;p&gt;The old milestone 2 covered four independent areas. This release takes the language core only, and the rest moved down the list: packages, Cargo dependencies, &lt;code&gt;use&lt;/code&gt;, nested modules, field-level &lt;code&gt;pub&lt;/code&gt;, Rust struct import, and publishing are now &lt;a href=&quot;/design/roadmap/&quot;&gt;milestone 3&lt;/a&gt;; closures, iterators, &lt;code&gt;if let&lt;/code&gt;, &lt;code&gt;HashMap&lt;/code&gt;, and &lt;code&gt;varyk fmt&lt;/code&gt; are milestone 4; the batteries for services, HTTP, JSON, logging, and &lt;code&gt;async&lt;/code&gt;, are milestone 5. Nothing there is a date.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0: until 1.0, a breaking change bumps the minor version. Milestone 3 has one, private struct fields, so the release after it is 0.1.0.&lt;/p&gt;
&lt;p&gt;If you think the bet is wrong, or right, the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place to say so.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Announcing Varyk 0.0.1</title>
        <published>2026-09-25T00:00:00+00:00</published>
        <updated>2026-09-25T00:00:00+00:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/announcing-varyk/"/>
        <id>https://varyk.com/blog/announcing-varyk/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/announcing-varyk/">&lt;p&gt;Varyk is an experimental language for APIs, workers, and microservices that compiles to Rust. Rust is what a service should run on: memory safety without a garbage collector, native speed, and an ecosystem that already has everything a service needs. It is also a lot to hold in your head when all you want is to handle a request. Varyk keeps what makes Rust strong and removes the ceremony from application code, and the Rust compiler checks everything it generates. Today the first release, 0.0.1, is on crates.io, and the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk&quot;&gt;compiler repository&lt;/a&gt; is public.&lt;/p&gt;
&lt;p&gt;The story of how I got here, through JavaScript, Python, TypeScript, Go, and Swift, is in &lt;a href=&quot;/blog/why-i-built-varyk/&quot;&gt;Why I built Varyk&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-in-it&quot;&gt;What is in it&lt;/h2&gt;
&lt;p&gt;This release is milestone 1: a small compiler that proves the approach. You write simple Varyk, and it becomes readable Rust that rustc checks like any other Rust code.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;varyk&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;string&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; rename&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;mut&lt;/span&gt;&lt;span&gt; user: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user.name &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt; &amp;quot;Bob&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; print_user&lt;/span&gt;&lt;span&gt;(user: &lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt;User&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-1&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;, user.name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; user &lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-6&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name: &lt;/span&gt;&lt;span class=&quot;z-2&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    print_user&lt;/span&gt;&lt;span&gt;(user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    rename&lt;/span&gt;&lt;span&gt;(user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-6&quot;&gt;    print_user&lt;/span&gt;&lt;span&gt;(user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It prints &lt;code&gt;Alice&lt;/code&gt;, then &lt;code&gt;Bob&lt;/code&gt;. &lt;code&gt;varyk build --emit-rust&lt;/code&gt; shows the generated Rust.&lt;/p&gt;
&lt;p&gt;The milestone-1 surface is deliberately small: functions, structs, &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, one string type, &lt;code&gt;println!&lt;/code&gt;, modules that resolve to &lt;code&gt;.vr&lt;/code&gt; or &lt;code&gt;.rs&lt;/code&gt; files, and calls into plain Rust functions. The &lt;a href=&quot;/learn/reference/&quot;&gt;language reference&lt;/a&gt; describes everything the compiler accepts, and the &lt;a href=&quot;/learn/examples/&quot;&gt;examples&lt;/a&gt; are the six programs it must build and run. Every error has a code, a plain-word message, and, where it can, a fix-it; &lt;code&gt;--message-format=json&lt;/code&gt; prints them as JSON for tools and agents.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;You need a stable Rust toolchain installed through &lt;a rel=&quot;external&quot; href=&quot;https://rustup.rs&quot;&gt;rustup&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install varyk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;varyk run hello.vr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;/learn/getting-started/&quot;&gt;getting started&lt;/a&gt; page goes from there.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next&quot;&gt;What is next&lt;/h2&gt;
&lt;p&gt;Varyk is experimental and pre-1.0: syntax, diagnostic codes, and command-line flags may change, and a breaking change bumps the minor version. The next milestones add enums, &lt;code&gt;match&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, methods, &lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;Result&lt;/code&gt;, and &lt;code&gt;?&lt;/code&gt;, and then packages with &lt;code&gt;Cargo.toml&lt;/code&gt; and Cargo dependencies. The batteries a service needs, HTTP, JSON, databases, and &lt;code&gt;async&lt;/code&gt;, come in milestone 5. The &lt;a href=&quot;/design/roadmap/&quot;&gt;roadmap&lt;/a&gt; has the full list, and the &lt;a href=&quot;/design/&quot;&gt;design page&lt;/a&gt; explains why the language is shaped this way.&lt;/p&gt;
&lt;p&gt;If you think the bet is wrong, or right, the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Varyk-Lang/varyk/issues&quot;&gt;issues&lt;/a&gt; are the place to say so.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why I built Varyk</title>
        <published>2026-09-24T14:31:00+02:00</published>
        <updated>2026-09-24T14:31:00+02:00</updated>
        
        <author>
          <name>Vlad Mickevic</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://varyk.com/blog/why-i-built-varyk/"/>
        <id>https://varyk.com/blog/why-i-built-varyk/</id>
        
        <content type="html" xml:base="https://varyk.com/blog/why-i-built-varyk/">&lt;p&gt;Varyk is an experimental language for backend services: you write simple, Go-like application code, and you ship a native Rust binary. This post is the story of why I started building it.&lt;/p&gt;
&lt;p&gt;I came to Varyk through the languages I built services in before it. JavaScript, then Python, then TypeScript: productive languages, but working with data without real types was harder than it needed to be, and TypeScript&#39;s types are only as strong as the JavaScript underneath them. I also needed performance those languages could not give me. So I went looking for a language that was fast and had a type system I could lean on.&lt;/p&gt;
&lt;p&gt;Go is simple, and I like that. But it has a garbage collector, with the runtime and memory overhead that come with it, and a syntax I never took to. Swift is a good language whose server ecosystem is too small for the microservices I build. Rust has the ideology I believe in: ownership instead of a garbage collector, safety enforced by the compiler, native performance, and an ecosystem that already has everything a service needs. I love it. Day to day, though, it is difficult to work with, and much of the difficulty comes from quirks that have nothing to do with the service being written.&lt;/p&gt;
&lt;p&gt;What I wanted did not exist: Rust&#39;s ecosystem, guarantees, and performance, with application code as simple as Go. Varyk is that language. It is for the application: kernels, database engines, and borrow-heavy libraries stay in Rust, in a &lt;code&gt;.rs&lt;/code&gt; file beside your Varyk, in the same build.&lt;/p&gt;
&lt;h2 id=&quot;what-that-means-in-practice&quot;&gt;What that means in practice&lt;/h2&gt;
&lt;p&gt;Varyk compiles to Rust. Every program becomes ordinary Rust that the Rust compiler checks, so the safety and the speed are Rust&#39;s own, and what you deploy is one native binary with no garbage collector. A Varyk package is a Cargo package: any crate on crates.io is available through a small &lt;code&gt;.rs&lt;/code&gt; file in the package, a facade, with no bindings to generate. What Varyk removes is the part of Rust you have to hold in your head. The &lt;a href=&quot;/why/&quot;&gt;Why page&lt;/a&gt; lays out what that costs in Rust and how Varyk takes it out; the &lt;a href=&quot;/learn/examples/&quot;&gt;examples&lt;/a&gt; show what the code looks like.&lt;/p&gt;
&lt;p&gt;Varyk is experimental and pre-1.0, and the batteries a service needs, HTTP, JSON, databases, and &lt;code&gt;async&lt;/code&gt;, are &lt;a href=&quot;/design/roadmap/&quot;&gt;milestone 5&lt;/a&gt;. If the bet sounds wrong to you, I would like to hear why: &lt;a href=&quot;mailto:hello@varyk.com&quot;&gt;hello@varyk.com&lt;/a&gt;.&lt;/p&gt;
</content>
        
    </entry>
</feed>
