1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2025-10-20 23:24:09 +00:00

added docs for gh pages

This commit is contained in:
Rene Schallner 2024-01-10 15:25:02 +01:00
parent 79aa63f717
commit f4563f2357
28 changed files with 24402 additions and 0 deletions

10270
docs/commonmark.js Normal file

File diff suppressed because it is too large Load diff

1
docs/data-astNodes.js Normal file

File diff suppressed because one or more lines are too long

1
docs/data-calls.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
docs/data-decls.js Normal file

File diff suppressed because one or more lines are too long

1
docs/data-exprs.js Normal file

File diff suppressed because one or more lines are too long

1
docs/data-files.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
var guideSections =[{"name":"","guides":[]}];

1
docs/data-modules.js Normal file
View file

@ -0,0 +1 @@
var modules =[{"name":"zap","file":0,"main":66,"table":{"zap":0}},{"name":"builtin","file":0,"main":454,"table":{}}];

1
docs/data-rootMod.js Normal file
View file

@ -0,0 +1 @@
var rootMod =0;

1
docs/data-typeKinds.js Normal file
View file

@ -0,0 +1 @@
var typeKinds =["Unanalyzed","Type","Void","Bool","NoReturn","Int","Float","Pointer","Array","Struct","ComptimeExpr","ComptimeFloat","ComptimeInt","Undefined","Null","Optional","ErrorUnion","InferredErrorUnion","ErrorSet","Enum","Union","Fn","Opaque","Frame","AnyFrame","Vector","EnumLiteral"];

1
docs/data-types.js Normal file

File diff suppressed because one or more lines are too long

1246
docs/index.html Normal file

File diff suppressed because it is too large Load diff

5242
docs/main.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,241 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>builtin.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-comment">/// Zig version. When writing code that supports multiple versions of Zig, prefer</span></span>
<span class="line" id="L3"><span class="tok-comment">/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.</span></span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> zig_version = std.SemanticVersion.parse(zig_version_string) <span class="tok-kw">catch</span> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> zig_version_string = <span class="tok-str">&quot;0.12.0-dev.2105+60094cc3f&quot;</span>;</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> zig_backend = std.builtin.CompilerBackend.stage2_llvm;</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> output_mode = std.builtin.OutputMode.Obj;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> link_mode = std.builtin.LinkMode.Static;</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> is_test = <span class="tok-null">false</span>;</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> single_threaded = <span class="tok-null">false</span>;</span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> abi = std.Target.Abi.gnu;</span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> cpu: std.Target.Cpu = .{</span>
<span class="line" id="L14"> .arch = .x86_64,</span>
<span class="line" id="L15"> .model = &amp;std.Target.x86.cpu.znver3,</span>
<span class="line" id="L16"> .features = std.Target.x86.featureSet(&amp;[_]std.Target.x86.Feature{</span>
<span class="line" id="L17"> .@&quot;64bit&quot;,</span>
<span class="line" id="L18"> .adx,</span>
<span class="line" id="L19"> .aes,</span>
<span class="line" id="L20"> .allow_light_256_bit,</span>
<span class="line" id="L21"> .avx,</span>
<span class="line" id="L22"> .avx2,</span>
<span class="line" id="L23"> .bmi,</span>
<span class="line" id="L24"> .bmi2,</span>
<span class="line" id="L25"> .branchfusion,</span>
<span class="line" id="L26"> .clflushopt,</span>
<span class="line" id="L27"> .clwb,</span>
<span class="line" id="L28"> .clzero,</span>
<span class="line" id="L29"> .cmov,</span>
<span class="line" id="L30"> .crc32,</span>
<span class="line" id="L31"> .cx16,</span>
<span class="line" id="L32"> .cx8,</span>
<span class="line" id="L33"> .f16c,</span>
<span class="line" id="L34"> .fast_15bytenop,</span>
<span class="line" id="L35"> .fast_bextr,</span>
<span class="line" id="L36"> .fast_lzcnt,</span>
<span class="line" id="L37"> .fast_movbe,</span>
<span class="line" id="L38"> .fast_scalar_fsqrt,</span>
<span class="line" id="L39"> .fast_scalar_shift_masks,</span>
<span class="line" id="L40"> .fast_variable_perlane_shuffle,</span>
<span class="line" id="L41"> .fast_vector_fsqrt,</span>
<span class="line" id="L42"> .fma,</span>
<span class="line" id="L43"> .fsgsbase,</span>
<span class="line" id="L44"> .fsrm,</span>
<span class="line" id="L45"> .fxsr,</span>
<span class="line" id="L46"> .invpcid,</span>
<span class="line" id="L47"> .lzcnt,</span>
<span class="line" id="L48"> .macrofusion,</span>
<span class="line" id="L49"> .mmx,</span>
<span class="line" id="L50"> .movbe,</span>
<span class="line" id="L51"> .mwaitx,</span>
<span class="line" id="L52"> .nopl,</span>
<span class="line" id="L53"> .pclmul,</span>
<span class="line" id="L54"> .pku,</span>
<span class="line" id="L55"> .popcnt,</span>
<span class="line" id="L56"> .prfchw,</span>
<span class="line" id="L57"> .rdpid,</span>
<span class="line" id="L58"> .rdpru,</span>
<span class="line" id="L59"> .rdrnd,</span>
<span class="line" id="L60"> .rdseed,</span>
<span class="line" id="L61"> .sahf,</span>
<span class="line" id="L62"> .sbb_dep_breaking,</span>
<span class="line" id="L63"> .sha,</span>
<span class="line" id="L64"> .shstk,</span>
<span class="line" id="L65"> .slow_shld,</span>
<span class="line" id="L66"> .sse,</span>
<span class="line" id="L67"> .sse2,</span>
<span class="line" id="L68"> .sse3,</span>
<span class="line" id="L69"> .sse4_1,</span>
<span class="line" id="L70"> .sse4_2,</span>
<span class="line" id="L71"> .sse4a,</span>
<span class="line" id="L72"> .ssse3,</span>
<span class="line" id="L73"> .vaes,</span>
<span class="line" id="L74"> .vpclmulqdq,</span>
<span class="line" id="L75"> .vzeroupper,</span>
<span class="line" id="L76"> .wbnoinvd,</span>
<span class="line" id="L77"> .x87,</span>
<span class="line" id="L78"> .xsave,</span>
<span class="line" id="L79"> .xsavec,</span>
<span class="line" id="L80"> .xsaveopt,</span>
<span class="line" id="L81"> .xsaves,</span>
<span class="line" id="L82"> }),</span>
<span class="line" id="L83">};</span>
<span class="line" id="L84"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> os = std.Target.Os{</span>
<span class="line" id="L85"> .tag = .linux,</span>
<span class="line" id="L86"> .version_range = .{ .linux = .{</span>
<span class="line" id="L87"> .range = .{</span>
<span class="line" id="L88"> .min = .{</span>
<span class="line" id="L89"> .major = <span class="tok-number">6</span>,</span>
<span class="line" id="L90"> .minor = <span class="tok-number">6</span>,</span>
<span class="line" id="L91"> .patch = <span class="tok-number">3</span>,</span>
<span class="line" id="L92"> },</span>
<span class="line" id="L93"> .max = .{</span>
<span class="line" id="L94"> .major = <span class="tok-number">6</span>,</span>
<span class="line" id="L95"> .minor = <span class="tok-number">6</span>,</span>
<span class="line" id="L96"> .patch = <span class="tok-number">3</span>,</span>
<span class="line" id="L97"> },</span>
<span class="line" id="L98"> },</span>
<span class="line" id="L99"> .glibc = .{</span>
<span class="line" id="L100"> .major = <span class="tok-number">2</span>,</span>
<span class="line" id="L101"> .minor = <span class="tok-number">36</span>,</span>
<span class="line" id="L102"> .patch = <span class="tok-number">0</span>,</span>
<span class="line" id="L103"> },</span>
<span class="line" id="L104"> }},</span>
<span class="line" id="L105">};</span>
<span class="line" id="L106"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> target: std.Target = .{</span>
<span class="line" id="L107"> .cpu = cpu,</span>
<span class="line" id="L108"> .os = os,</span>
<span class="line" id="L109"> .abi = abi,</span>
<span class="line" id="L110"> .ofmt = object_format,</span>
<span class="line" id="L111"> .dynamic_linker = std.Target.DynamicLinker.init(<span class="tok-str">&quot;/nix/store/whypqfa83z4bsn43n4byvmw80n4mg3r8-glibc-2.37-45/lib/ld-linux-x86-64.so.2&quot;</span>),</span>
<span class="line" id="L112">};</span>
<span class="line" id="L113"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> object_format = std.Target.ObjectFormat.elf;</span>
<span class="line" id="L114"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mode = std.builtin.OptimizeMode.Debug;</span>
<span class="line" id="L115"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> link_libc = <span class="tok-null">false</span>;</span>
<span class="line" id="L116"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> link_libcpp = <span class="tok-null">false</span>;</span>
<span class="line" id="L117"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> have_error_return_tracing = <span class="tok-null">true</span>;</span>
<span class="line" id="L118"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> valgrind_support = <span class="tok-null">true</span>;</span>
<span class="line" id="L119"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sanitize_thread = <span class="tok-null">false</span>;</span>
<span class="line" id="L120"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> position_independent_code = <span class="tok-null">false</span>;</span>
<span class="line" id="L121"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> position_independent_executable = <span class="tok-null">false</span>;</span>
<span class="line" id="L122"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> strip_debug_info = <span class="tok-null">false</span>;</span>
<span class="line" id="L123"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> code_model = std.builtin.CodeModel.default;</span>
<span class="line" id="L124"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> omit_frame_pointer = <span class="tok-null">false</span>;</span>
<span class="line" id="L125"></span>
</code></pre></body>
</html>

View file

@ -0,0 +1,461 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>endpoint.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> zap = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zap.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> auth = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;http_auth.zig&quot;</span>);</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">const</span> Endpoint = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-comment">// zap types</span>
</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Request = zap.Request;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> ListenerSettings = zap.HttpListenerSettings;</span>
<span class="line" id="L10"><span class="tok-kw">const</span> HttpListener = zap.HttpListener;</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-comment">/// Type of the request function callbacks.</span></span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> RequestFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (self: *Endpoint, r: Request) <span class="tok-type">void</span>;</span>
<span class="line" id="L14"></span>
<span class="line" id="L15"><span class="tok-comment">/// Settings to initialize an Endpoint</span></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Settings = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L17"> <span class="tok-comment">/// path / slug of the endpoint</span></span>
<span class="line" id="L18"> path: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L19"> <span class="tok-comment">/// callback to GET request handler</span></span>
<span class="line" id="L20"> get: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L21"> <span class="tok-comment">/// callback to POST request handler</span></span>
<span class="line" id="L22"> post: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L23"> <span class="tok-comment">/// callback to PUT request handler</span></span>
<span class="line" id="L24"> put: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L25"> <span class="tok-comment">/// callback to DELETE request handler</span></span>
<span class="line" id="L26"> delete: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L27"> <span class="tok-comment">/// callback to PATCH request handler</span></span>
<span class="line" id="L28"> patch: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L29"> <span class="tok-comment">/// callback to OPTIONS request handler</span></span>
<span class="line" id="L30"> options: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L31"> <span class="tok-comment">/// Only applicable to Authenticating Endpoint: handler for unauthorized requests</span></span>
<span class="line" id="L32"> unauthorized: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L33">};</span>
<span class="line" id="L34"></span>
<span class="line" id="L35">settings: Settings,</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"><span class="tok-comment">/// Initialize the endpoint.</span></span>
<span class="line" id="L38"><span class="tok-comment">/// Set only the callbacks you need. Requests of HTTP methods without a</span></span>
<span class="line" id="L39"><span class="tok-comment">/// provided callback will be ignored.</span></span>
<span class="line" id="L40"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(s: Settings) Endpoint {</span>
<span class="line" id="L41"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L42"> .settings = .{</span>
<span class="line" id="L43"> .path = s.path,</span>
<span class="line" id="L44"> .get = s.get <span class="tok-kw">orelse</span> &amp;nop,</span>
<span class="line" id="L45"> .post = s.post <span class="tok-kw">orelse</span> &amp;nop,</span>
<span class="line" id="L46"> .put = s.put <span class="tok-kw">orelse</span> &amp;nop,</span>
<span class="line" id="L47"> .delete = s.delete <span class="tok-kw">orelse</span> &amp;nop,</span>
<span class="line" id="L48"> .patch = s.patch <span class="tok-kw">orelse</span> &amp;nop,</span>
<span class="line" id="L49"> .options = s.options <span class="tok-kw">orelse</span> &amp;nop,</span>
<span class="line" id="L50"> .unauthorized = s.unauthorized <span class="tok-kw">orelse</span> &amp;nop,</span>
<span class="line" id="L51"> },</span>
<span class="line" id="L52"> };</span>
<span class="line" id="L53">}</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-comment">// no operation. Dummy handler function for ignoring unset request types.</span>
</span>
<span class="line" id="L56"><span class="tok-kw">fn</span> <span class="tok-fn">nop</span>(self: *Endpoint, r: Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L57"> _ = self;</span>
<span class="line" id="L58"> _ = r;</span>
<span class="line" id="L59">}</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"><span class="tok-comment">/// The global request handler for this Endpoint, called by the listener.</span></span>
<span class="line" id="L62"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">onRequest</span>(self: *Endpoint, r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L63"> <span class="tok-kw">if</span> (r.method) |m| {</span>
<span class="line" id="L64"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, m, <span class="tok-str">&quot;GET&quot;</span>))</span>
<span class="line" id="L65"> <span class="tok-kw">return</span> self.settings.get.?(self, r);</span>
<span class="line" id="L66"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, m, <span class="tok-str">&quot;POST&quot;</span>))</span>
<span class="line" id="L67"> <span class="tok-kw">return</span> self.settings.post.?(self, r);</span>
<span class="line" id="L68"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, m, <span class="tok-str">&quot;PUT&quot;</span>))</span>
<span class="line" id="L69"> <span class="tok-kw">return</span> self.settings.put.?(self, r);</span>
<span class="line" id="L70"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, m, <span class="tok-str">&quot;DELETE&quot;</span>))</span>
<span class="line" id="L71"> <span class="tok-kw">return</span> self.settings.delete.?(self, r);</span>
<span class="line" id="L72"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, m, <span class="tok-str">&quot;PATCH&quot;</span>))</span>
<span class="line" id="L73"> <span class="tok-kw">return</span> self.settings.patch.?(self, r);</span>
<span class="line" id="L74"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, m, <span class="tok-str">&quot;OPTIONS&quot;</span>))</span>
<span class="line" id="L75"> <span class="tok-kw">return</span> self.settings.options.?(self, r);</span>
<span class="line" id="L76"> }</span>
<span class="line" id="L77">}</span>
<span class="line" id="L78"></span>
<span class="line" id="L79"><span class="tok-comment">/// Wrap an endpoint with an Authenticator -&gt; new Endpoint of type Endpoint</span></span>
<span class="line" id="L80"><span class="tok-comment">/// is available via the `endpoint()` function.</span></span>
<span class="line" id="L81"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Authenticating</span>(<span class="tok-kw">comptime</span> Authenticator: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L83"> authenticator: *Authenticator,</span>
<span class="line" id="L84"> ep: *Endpoint,</span>
<span class="line" id="L85"> auth_endpoint: Endpoint,</span>
<span class="line" id="L86"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L87"></span>
<span class="line" id="L88"> <span class="tok-comment">/// Init the authenticating endpoint. Pass in a pointer to the endpoint</span></span>
<span class="line" id="L89"> <span class="tok-comment">/// you want to wrap, and the Authenticator that takes care of authenticating</span></span>
<span class="line" id="L90"> <span class="tok-comment">/// requests.</span></span>
<span class="line" id="L91"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(e: *Endpoint, authenticator: *Authenticator) Self {</span>
<span class="line" id="L92"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L93"> .authenticator = authenticator,</span>
<span class="line" id="L94"> .ep = e,</span>
<span class="line" id="L95"> .auth_endpoint = Endpoint.init(.{</span>
<span class="line" id="L96"> .path = e.settings.path,</span>
<span class="line" id="L97"> <span class="tok-comment">// we override only the set ones. the other ones</span>
</span>
<span class="line" id="L98"> <span class="tok-comment">// are set to null anyway -&gt; will be nopped out</span>
</span>
<span class="line" id="L99"> .get = <span class="tok-kw">if</span> (e.settings.get != <span class="tok-null">null</span>) get <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L100"> .post = <span class="tok-kw">if</span> (e.settings.post != <span class="tok-null">null</span>) post <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L101"> .put = <span class="tok-kw">if</span> (e.settings.put != <span class="tok-null">null</span>) put <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L102"> .delete = <span class="tok-kw">if</span> (e.settings.delete != <span class="tok-null">null</span>) delete <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L103"> .patch = <span class="tok-kw">if</span> (e.settings.patch != <span class="tok-null">null</span>) patch <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L104"> .options = <span class="tok-kw">if</span> (e.settings.options != <span class="tok-null">null</span>) options <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L105"> .unauthorized = e.settings.unauthorized,</span>
<span class="line" id="L106"> }),</span>
<span class="line" id="L107"> };</span>
<span class="line" id="L108"> }</span>
<span class="line" id="L109"></span>
<span class="line" id="L110"> <span class="tok-comment">/// Get the auth endpoint struct of type Endpoint so it can be stored in the listener.</span></span>
<span class="line" id="L111"> <span class="tok-comment">/// When the listener calls the auth_endpoint, onRequest will have</span></span>
<span class="line" id="L112"> <span class="tok-comment">/// access to all of this via fieldParentPtr</span></span>
<span class="line" id="L113"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">endpoint</span>(self: *Self) *Endpoint {</span>
<span class="line" id="L114"> <span class="tok-kw">return</span> &amp;self.auth_endpoint;</span>
<span class="line" id="L115"> }</span>
<span class="line" id="L116"></span>
<span class="line" id="L117"> <span class="tok-comment">/// GET: here, the auth_endpoint will be passed in as endpoint.</span></span>
<span class="line" id="L118"> <span class="tok-comment">/// Authenticates GET requests using the Authenticator.</span></span>
<span class="line" id="L119"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">get</span>(e: *Endpoint, r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L120"> <span class="tok-kw">const</span> authEp: *Self = <span class="tok-builtin">@fieldParentPtr</span>(Self, <span class="tok-str">&quot;auth_endpoint&quot;</span>, e);</span>
<span class="line" id="L121"> <span class="tok-kw">switch</span> (authEp.authenticator.authenticateRequest(&amp;r)) {</span>
<span class="line" id="L122"> .AuthFailed =&gt; {</span>
<span class="line" id="L123"> <span class="tok-kw">if</span> (e.settings.unauthorized) |unauthorized| {</span>
<span class="line" id="L124"> unauthorized(authEp.ep, r);</span>
<span class="line" id="L125"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L126"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L127"> r.setStatus(.unauthorized);</span>
<span class="line" id="L128"> r.sendBody(<span class="tok-str">&quot;UNAUTHORIZED&quot;</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L129"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L130"> }</span>
<span class="line" id="L131"> },</span>
<span class="line" id="L132"> .AuthOK =&gt; authEp.ep.settings.get.?(authEp.ep, r),</span>
<span class="line" id="L133"> .Handled =&gt; {},</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"> }</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"> <span class="tok-comment">/// POST: here, the auth_endpoint will be passed in as endpoint.</span></span>
<span class="line" id="L138"> <span class="tok-comment">/// Authenticates POST requests using the Authenticator.</span></span>
<span class="line" id="L139"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">post</span>(e: *Endpoint, r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L140"> <span class="tok-kw">const</span> authEp: *Self = <span class="tok-builtin">@fieldParentPtr</span>(Self, <span class="tok-str">&quot;auth_endpoint&quot;</span>, e);</span>
<span class="line" id="L141"> <span class="tok-kw">switch</span> (authEp.authenticator.authenticateRequest(&amp;r)) {</span>
<span class="line" id="L142"> .AuthFailed =&gt; {</span>
<span class="line" id="L143"> <span class="tok-kw">if</span> (e.settings.unauthorized) |unauthorized| {</span>
<span class="line" id="L144"> unauthorized(authEp.ep, r);</span>
<span class="line" id="L145"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L146"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L147"> r.setStatus(.unauthorized);</span>
<span class="line" id="L148"> r.sendBody(<span class="tok-str">&quot;UNAUTHORIZED&quot;</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L149"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L150"> }</span>
<span class="line" id="L151"> },</span>
<span class="line" id="L152"> .AuthOK =&gt; authEp.ep.settings.post.?(authEp.ep, r),</span>
<span class="line" id="L153"> .Handled =&gt; {},</span>
<span class="line" id="L154"> }</span>
<span class="line" id="L155"> }</span>
<span class="line" id="L156"></span>
<span class="line" id="L157"> <span class="tok-comment">/// PUT: here, the auth_endpoint will be passed in as endpoint.</span></span>
<span class="line" id="L158"> <span class="tok-comment">/// Authenticates PUT requests using the Authenticator.</span></span>
<span class="line" id="L159"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">put</span>(e: *Endpoint, r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L160"> <span class="tok-kw">const</span> authEp: *Self = <span class="tok-builtin">@fieldParentPtr</span>(Self, <span class="tok-str">&quot;auth_endpoint&quot;</span>, e);</span>
<span class="line" id="L161"> <span class="tok-kw">switch</span> (authEp.authenticator.authenticateRequest(&amp;r)) {</span>
<span class="line" id="L162"> .AuthFailed =&gt; {</span>
<span class="line" id="L163"> <span class="tok-kw">if</span> (e.settings.unauthorized) |unauthorized| {</span>
<span class="line" id="L164"> unauthorized(authEp.ep, r);</span>
<span class="line" id="L165"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L166"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L167"> r.setStatus(.unauthorized);</span>
<span class="line" id="L168"> r.sendBody(<span class="tok-str">&quot;UNAUTHORIZED&quot;</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L169"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L170"> }</span>
<span class="line" id="L171"> },</span>
<span class="line" id="L172"> .AuthOK =&gt; authEp.ep.settings.put.?(authEp.ep, r),</span>
<span class="line" id="L173"> .Handled =&gt; {},</span>
<span class="line" id="L174"> }</span>
<span class="line" id="L175"> }</span>
<span class="line" id="L176"></span>
<span class="line" id="L177"> <span class="tok-comment">/// DELETE: here, the auth_endpoint will be passed in as endpoint.</span></span>
<span class="line" id="L178"> <span class="tok-comment">/// Authenticates DELETE requests using the Authenticator.</span></span>
<span class="line" id="L179"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">delete</span>(e: *Endpoint, r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L180"> <span class="tok-kw">const</span> authEp: *Self = <span class="tok-builtin">@fieldParentPtr</span>(Self, <span class="tok-str">&quot;auth_endpoint&quot;</span>, e);</span>
<span class="line" id="L181"> <span class="tok-kw">switch</span> (authEp.authenticator.authenticateRequest(&amp;r)) {</span>
<span class="line" id="L182"> .AuthFailed =&gt; {</span>
<span class="line" id="L183"> <span class="tok-kw">if</span> (e.settings.unauthorized) |unauthorized| {</span>
<span class="line" id="L184"> unauthorized(authEp.ep, r);</span>
<span class="line" id="L185"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L186"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L187"> r.setStatus(.unauthorized);</span>
<span class="line" id="L188"> r.sendBody(<span class="tok-str">&quot;UNAUTHORIZED&quot;</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L189"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L190"> }</span>
<span class="line" id="L191"> },</span>
<span class="line" id="L192"> .AuthOK =&gt; authEp.ep.settings.delete.?(authEp.ep, r),</span>
<span class="line" id="L193"> .Handled =&gt; {},</span>
<span class="line" id="L194"> }</span>
<span class="line" id="L195"> }</span>
<span class="line" id="L196"></span>
<span class="line" id="L197"> <span class="tok-comment">/// PATCH: here, the auth_endpoint will be passed in as endpoint.</span></span>
<span class="line" id="L198"> <span class="tok-comment">/// Authenticates PATCH requests using the Authenticator.</span></span>
<span class="line" id="L199"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">patch</span>(e: *Endpoint, r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L200"> <span class="tok-kw">const</span> authEp: *Self = <span class="tok-builtin">@fieldParentPtr</span>(Self, <span class="tok-str">&quot;auth_endpoint&quot;</span>, e);</span>
<span class="line" id="L201"> <span class="tok-kw">switch</span> (authEp.authenticator.authenticateRequest(&amp;r)) {</span>
<span class="line" id="L202"> .AuthFailed =&gt; {</span>
<span class="line" id="L203"> <span class="tok-kw">if</span> (e.settings.unauthorized) |unauthorized| {</span>
<span class="line" id="L204"> unauthorized(authEp.ep, r);</span>
<span class="line" id="L205"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L206"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L207"> r.setStatus(.unauthorized);</span>
<span class="line" id="L208"> r.sendBody(<span class="tok-str">&quot;UNAUTHORIZED&quot;</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L209"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L210"> }</span>
<span class="line" id="L211"> },</span>
<span class="line" id="L212"> .AuthOK =&gt; authEp.ep.settings.patch.?(authEp.ep, r),</span>
<span class="line" id="L213"> .Handled =&gt; {},</span>
<span class="line" id="L214"> }</span>
<span class="line" id="L215"> }</span>
<span class="line" id="L216"></span>
<span class="line" id="L217"> <span class="tok-comment">/// OPTIONS: here, the auth_endpoint will be passed in as endpoint.</span></span>
<span class="line" id="L218"> <span class="tok-comment">/// Authenticates OPTIONS requests using the Authenticator.</span></span>
<span class="line" id="L219"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">options</span>(e: *Endpoint, r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L220"> <span class="tok-kw">const</span> authEp: *Self = <span class="tok-builtin">@fieldParentPtr</span>(Self, <span class="tok-str">&quot;auth_endpoint&quot;</span>, e);</span>
<span class="line" id="L221"> <span class="tok-kw">switch</span> (authEp.authenticator.authenticateRequest(&amp;r)) {</span>
<span class="line" id="L222"> .AuthFailed =&gt; {</span>
<span class="line" id="L223"> <span class="tok-kw">if</span> (e.settings.unauthorized) |unauthorized| {</span>
<span class="line" id="L224"> unauthorized(authEp.ep, r);</span>
<span class="line" id="L225"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L226"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L227"> r.setStatus(.unauthorized);</span>
<span class="line" id="L228"> r.sendBody(<span class="tok-str">&quot;UNAUTHORIZED&quot;</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L229"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L230"> }</span>
<span class="line" id="L231"> },</span>
<span class="line" id="L232"> .AuthOK =&gt; authEp.ep.settings.put.?(authEp.ep, r),</span>
<span class="line" id="L233"> .Handled =&gt; {},</span>
<span class="line" id="L234"> }</span>
<span class="line" id="L235"> }</span>
<span class="line" id="L236"> };</span>
<span class="line" id="L237">}</span>
<span class="line" id="L238"></span>
<span class="line" id="L239"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> EndpointListenerError = <span class="tok-kw">error</span>{</span>
<span class="line" id="L240"> <span class="tok-comment">/// Since we use .startsWith to check for matching paths, you cannot use</span></span>
<span class="line" id="L241"> <span class="tok-comment">/// endpoint paths that overlap at the beginning. --&gt; When trying to register</span></span>
<span class="line" id="L242"> <span class="tok-comment">/// an endpoint whose path would shadow an already registered one, you will</span></span>
<span class="line" id="L243"> <span class="tok-comment">/// receive this error.</span></span>
<span class="line" id="L244"> EndpointPathShadowError,</span>
<span class="line" id="L245">};</span>
<span class="line" id="L246"></span>
<span class="line" id="L247"><span class="tok-comment">/// The listener with ednpoint support</span></span>
<span class="line" id="L248"><span class="tok-comment">///</span></span>
<span class="line" id="L249"><span class="tok-comment">/// NOTE: It switches on path.startsWith -&gt; so use endpoints with distinctly starting names!!</span></span>
<span class="line" id="L250"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Listener = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L251"> listener: HttpListener,</span>
<span class="line" id="L252"> allocator: std.mem.Allocator,</span>
<span class="line" id="L253"></span>
<span class="line" id="L254"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L255"></span>
<span class="line" id="L256"> <span class="tok-comment">/// Internal static struct of member endpoints</span></span>
<span class="line" id="L257"> <span class="tok-kw">var</span> endpoints: std.ArrayList(*Endpoint) = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L258"></span>
<span class="line" id="L259"> <span class="tok-comment">/// Internal, static request handler callback. Will be set to the optional,</span></span>
<span class="line" id="L260"> <span class="tok-comment">/// user-defined request callback that only gets called if no endpoints match</span></span>
<span class="line" id="L261"> <span class="tok-comment">/// a request.</span></span>
<span class="line" id="L262"> <span class="tok-kw">var</span> on_request: ?zap.HttpRequestFn = <span class="tok-null">null</span>;</span>
<span class="line" id="L263"></span>
<span class="line" id="L264"> <span class="tok-comment">/// Initialize a new endpoint listener. Note, if you pass an `on_request`</span></span>
<span class="line" id="L265"> <span class="tok-comment">/// callback in the provided ListenerSettings, this request callback will be</span></span>
<span class="line" id="L266"> <span class="tok-comment">/// called every time a request arrives that no endpoint matches.</span></span>
<span class="line" id="L267"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(a: std.mem.Allocator, l: ListenerSettings) Self {</span>
<span class="line" id="L268"> endpoints = std.ArrayList(*Endpoint).init(a);</span>
<span class="line" id="L269"></span>
<span class="line" id="L270"> <span class="tok-comment">// take copy of listener settings before modifying the callback field</span>
</span>
<span class="line" id="L271"> <span class="tok-kw">var</span> ls = l;</span>
<span class="line" id="L272"></span>
<span class="line" id="L273"> <span class="tok-comment">// override the settings with our internal, actul callback function</span>
</span>
<span class="line" id="L274"> <span class="tok-comment">// so that &quot;we&quot; will be called on request</span>
</span>
<span class="line" id="L275"> ls.on_request = Listener.onRequest;</span>
<span class="line" id="L276"></span>
<span class="line" id="L277"> <span class="tok-comment">// store the settings-provided request callback for later use</span>
</span>
<span class="line" id="L278"> on_request = l.on_request;</span>
<span class="line" id="L279"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L280"> .listener = HttpListener.init(ls),</span>
<span class="line" id="L281"> .allocator = a,</span>
<span class="line" id="L282"> };</span>
<span class="line" id="L283"> }</span>
<span class="line" id="L284"></span>
<span class="line" id="L285"> <span class="tok-comment">/// De-init the listener and free its resources.</span></span>
<span class="line" id="L286"> <span class="tok-comment">/// Registered endpoints will not be de-initialized automatically; just removed</span></span>
<span class="line" id="L287"> <span class="tok-comment">/// from the internal map.</span></span>
<span class="line" id="L288"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L289"> _ = self;</span>
<span class="line" id="L290"> endpoints.deinit();</span>
<span class="line" id="L291"> }</span>
<span class="line" id="L292"></span>
<span class="line" id="L293"> <span class="tok-comment">/// Call this to start listening. After this, no more endpoints can be</span></span>
<span class="line" id="L294"> <span class="tok-comment">/// registered.</span></span>
<span class="line" id="L295"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">listen</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L296"> <span class="tok-kw">try</span> self.listener.listen();</span>
<span class="line" id="L297"> }</span>
<span class="line" id="L298"></span>
<span class="line" id="L299"> <span class="tok-comment">/// Register an endpoint with this listener.</span></span>
<span class="line" id="L300"> <span class="tok-comment">/// NOTE: endpoint paths are matched with startsWith -&gt; so use endpoints with distinctly starting names!!</span></span>
<span class="line" id="L301"> <span class="tok-comment">/// If you try to register an endpoint whose path would shadow an already registered one, you will</span></span>
<span class="line" id="L302"> <span class="tok-comment">/// receive an EndpointPathShadowError.</span></span>
<span class="line" id="L303"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">register</span>(self: *Self, e: *Endpoint) !<span class="tok-type">void</span> {</span>
<span class="line" id="L304"> _ = self;</span>
<span class="line" id="L305"> <span class="tok-kw">for</span> (endpoints.items) |other| {</span>
<span class="line" id="L306"> <span class="tok-kw">if</span> (std.mem.startsWith(</span>
<span class="line" id="L307"> <span class="tok-type">u8</span>,</span>
<span class="line" id="L308"> other.settings.path,</span>
<span class="line" id="L309"> e.settings.path,</span>
<span class="line" id="L310"> ) <span class="tok-kw">or</span> std.mem.startsWith(</span>
<span class="line" id="L311"> <span class="tok-type">u8</span>,</span>
<span class="line" id="L312"> e.settings.path,</span>
<span class="line" id="L313"> other.settings.path,</span>
<span class="line" id="L314"> )) {</span>
<span class="line" id="L315"> <span class="tok-kw">return</span> EndpointListenerError.EndpointPathShadowError;</span>
<span class="line" id="L316"> }</span>
<span class="line" id="L317"> }</span>
<span class="line" id="L318"> <span class="tok-kw">try</span> endpoints.append(e);</span>
<span class="line" id="L319"> }</span>
<span class="line" id="L320"></span>
<span class="line" id="L321"> <span class="tok-kw">fn</span> <span class="tok-fn">onRequest</span>(r: Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L322"> <span class="tok-kw">if</span> (r.path) |p| {</span>
<span class="line" id="L323"> <span class="tok-kw">for</span> (endpoints.items) |e| {</span>
<span class="line" id="L324"> <span class="tok-kw">if</span> (std.mem.startsWith(<span class="tok-type">u8</span>, p, e.settings.path)) {</span>
<span class="line" id="L325"> e.onRequest(r);</span>
<span class="line" id="L326"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L327"> }</span>
<span class="line" id="L328"> }</span>
<span class="line" id="L329"> }</span>
<span class="line" id="L330"> <span class="tok-comment">// if set, call the user-provided default callback</span>
</span>
<span class="line" id="L331"> <span class="tok-kw">if</span> (on_request) |foo| {</span>
<span class="line" id="L332"> foo(r);</span>
<span class="line" id="L333"> }</span>
<span class="line" id="L334"> }</span>
<span class="line" id="L335">};</span>
<span class="line" id="L336"></span>
</code></pre></body>
</html>

740
docs/src/zap/fio.zig.html Normal file
View file

@ -0,0 +1,740 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>fio.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ = <span class="tok-type">usize</span>;</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">is_invalid</span>(o: FIOBJ) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fio_url_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L4"> scheme: fio_str_info_s,</span>
<span class="line" id="L5"> user: fio_str_info_s,</span>
<span class="line" id="L6"> password: fio_str_info_s,</span>
<span class="line" id="L7"> host: fio_str_info_s,</span>
<span class="line" id="L8"> port: fio_str_info_s,</span>
<span class="line" id="L9"> path: fio_str_info_s,</span>
<span class="line" id="L10"> query: fio_str_info_s,</span>
<span class="line" id="L11"> target: fio_str_info_s,</span>
<span class="line" id="L12">};</span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_url_parse</span>(url: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, length: <span class="tok-type">usize</span>) fio_url_s;</span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_fio_start_args = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L15"> threads: <span class="tok-type">i16</span>,</span>
<span class="line" id="L16"> workers: <span class="tok-type">i16</span>,</span>
<span class="line" id="L17">};</span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fio_start_args = struct_fio_start_args;</span>
<span class="line" id="L19"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_start</span>(args: struct_fio_start_args) <span class="tok-type">void</span>;</span>
<span class="line" id="L20"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_stop</span>() <span class="tok-type">void</span>;</span>
<span class="line" id="L21"><span class="tok-kw">const</span> struct_unnamed_37 = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L22"> vtbl: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L23"> flag: <span class="tok-type">usize</span>,</span>
<span class="line" id="L24"> out_headers: FIOBJ,</span>
<span class="line" id="L25">};</span>
<span class="line" id="L26"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> __time_t = <span class="tok-type">c_long</span>;</span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> time_t = __time_t;</span>
<span class="line" id="L28"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> __syscall_slong_t = <span class="tok-type">c_long</span>;</span>
<span class="line" id="L29"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_timespec = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L30"> tv_sec: __time_t,</span>
<span class="line" id="L31"> tv_nsec: __syscall_slong_t,</span>
<span class="line" id="L32">};</span>
<span class="line" id="L33"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_http_settings_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L34"> on_request: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L35"> on_upgrade: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_s, [*c]<span class="tok-type">u8</span>, <span class="tok-type">usize</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L36"> on_response: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L37"> on_finish: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]struct_http_settings_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L38"> udata: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L39"> public_folder: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L40"> public_folder_length: <span class="tok-type">usize</span>,</span>
<span class="line" id="L41"> max_header_size: <span class="tok-type">usize</span>,</span>
<span class="line" id="L42"> max_body_size: <span class="tok-type">usize</span>,</span>
<span class="line" id="L43"> max_clients: <span class="tok-type">isize</span>,</span>
<span class="line" id="L44"> tls: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L45"> reserved1: <span class="tok-type">isize</span>,</span>
<span class="line" id="L46"> reserved2: <span class="tok-type">isize</span>,</span>
<span class="line" id="L47"> reserved3: <span class="tok-type">isize</span>,</span>
<span class="line" id="L48"> ws_max_msg_size: <span class="tok-type">usize</span>,</span>
<span class="line" id="L49"> timeout: <span class="tok-type">u8</span>,</span>
<span class="line" id="L50"> ws_timeout: <span class="tok-type">u8</span>,</span>
<span class="line" id="L51"> log: <span class="tok-type">u8</span>,</span>
<span class="line" id="L52"> is_client: <span class="tok-type">u8</span>,</span>
<span class="line" id="L53">};</span>
<span class="line" id="L54"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> http_settings_s = struct_http_settings_s;</span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> http_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L56"> private_data: struct_unnamed_37,</span>
<span class="line" id="L57"> received_at: struct_timespec,</span>
<span class="line" id="L58"> method: FIOBJ,</span>
<span class="line" id="L59"> status_str: FIOBJ,</span>
<span class="line" id="L60"> version: FIOBJ,</span>
<span class="line" id="L61"> status: <span class="tok-type">usize</span>,</span>
<span class="line" id="L62"> path: FIOBJ,</span>
<span class="line" id="L63"> query: FIOBJ,</span>
<span class="line" id="L64"> headers: FIOBJ,</span>
<span class="line" id="L65"> cookies: FIOBJ,</span>
<span class="line" id="L66"> params: FIOBJ,</span>
<span class="line" id="L67"> body: FIOBJ,</span>
<span class="line" id="L68"> udata: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L69">};</span>
<span class="line" id="L70"></span>
<span class="line" id="L71"><span class="tok-comment">// zig-cache/i/e0c8a6e617497ade13de512cbe191f23/include/http.h:153:12: warning: struct demoted to opaque type - has bitfield</span>
</span>
<span class="line" id="L72"></span>
<span class="line" id="L73"><span class="tok-comment">// typedef struct {</span>
</span>
<span class="line" id="L74"><span class="tok-comment">// /** The cookie's name (Symbol). */</span>
</span>
<span class="line" id="L75"><span class="tok-comment">// const char *name;</span>
</span>
<span class="line" id="L76"><span class="tok-comment">// /** The cookie's value (leave blank to delete cookie). */</span>
</span>
<span class="line" id="L77"><span class="tok-comment">// const char *value;</span>
</span>
<span class="line" id="L78"><span class="tok-comment">// /** The cookie's domain (optional). */</span>
</span>
<span class="line" id="L79"><span class="tok-comment">// const char *domain;</span>
</span>
<span class="line" id="L80"><span class="tok-comment">// /** The cookie's path (optional). */</span>
</span>
<span class="line" id="L81"><span class="tok-comment">// const char *path;</span>
</span>
<span class="line" id="L82"><span class="tok-comment">// /** The cookie name's size in bytes or a terminating NUL will be assumed.*/</span>
</span>
<span class="line" id="L83"><span class="tok-comment">// size_t name_len;</span>
</span>
<span class="line" id="L84"><span class="tok-comment">// /** The cookie value's size in bytes or a terminating NUL will be assumed.*/</span>
</span>
<span class="line" id="L85"><span class="tok-comment">// size_t value_len;</span>
</span>
<span class="line" id="L86"><span class="tok-comment">// /** The cookie domain's size in bytes or a terminating NUL will be assumed.*/</span>
</span>
<span class="line" id="L87"><span class="tok-comment">// size_t domain_len;</span>
</span>
<span class="line" id="L88"><span class="tok-comment">// /** The cookie path's size in bytes or a terminating NULL will be assumed.*/</span>
</span>
<span class="line" id="L89"><span class="tok-comment">// size_t path_len;</span>
</span>
<span class="line" id="L90"><span class="tok-comment">// /** Max Age (how long should the cookie persist), in seconds (0 == session).*/</span>
</span>
<span class="line" id="L91"><span class="tok-comment">// int max_age;</span>
</span>
<span class="line" id="L92"><span class="tok-comment">// /** Limit cookie to secure connections.*/</span>
</span>
<span class="line" id="L93"><span class="tok-comment">// unsigned secure : 1;</span>
</span>
<span class="line" id="L94"><span class="tok-comment">// /** Limit cookie to HTTP (intended to prevent javascript access/hijacking).*/</span>
</span>
<span class="line" id="L95"><span class="tok-comment">// unsigned http_only : 1;</span>
</span>
<span class="line" id="L96"><span class="tok-comment">// } http_cookie_args_s;</span>
</span>
<span class="line" id="L97"></span>
<span class="line" id="L98"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> http_cookie_args_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L99"> name: [*c]<span class="tok-type">u8</span>,</span>
<span class="line" id="L100"> value: [*c]<span class="tok-type">u8</span>,</span>
<span class="line" id="L101"> domain: [*c]<span class="tok-type">u8</span>,</span>
<span class="line" id="L102"> path: [*c]<span class="tok-type">u8</span>,</span>
<span class="line" id="L103"> name_len: <span class="tok-type">isize</span>,</span>
<span class="line" id="L104"> value_len: <span class="tok-type">isize</span>,</span>
<span class="line" id="L105"> domain_len: <span class="tok-type">isize</span>,</span>
<span class="line" id="L106"> path_len: <span class="tok-type">isize</span>,</span>
<span class="line" id="L107"> <span class="tok-comment">/// in seconds</span></span>
<span class="line" id="L108"> max_age: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L109"> secure: <span class="tok-type">c_uint</span>,</span>
<span class="line" id="L110"> http_only: <span class="tok-type">c_uint</span>,</span>
<span class="line" id="L111">};</span>
<span class="line" id="L112"></span>
<span class="line" id="L113"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_fio_str_info_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L114"> capa: <span class="tok-type">usize</span>,</span>
<span class="line" id="L115"> len: <span class="tok-type">usize</span>,</span>
<span class="line" id="L116"> data: [*c]<span class="tok-type">u8</span>,</span>
<span class="line" id="L117">};</span>
<span class="line" id="L118"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fio_str_info_s = struct_fio_str_info_s;</span>
<span class="line" id="L119"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_send_body</span>(h: [*c]http_s, data: ?*<span class="tok-type">anyopaque</span>, length: <span class="tok-type">usize</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L120"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_each1</span>(arg_o: FIOBJ, arg_start_at: <span class="tok-type">usize</span>, arg_task: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">c_int</span>, arg_arg: ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span> {</span>
<span class="line" id="L121"> <span class="tok-kw">const</span> o = arg_o;</span>
<span class="line" id="L122"> <span class="tok-kw">const</span> start_at = arg_start_at;</span>
<span class="line" id="L123"> <span class="tok-kw">const</span> task = arg_task;</span>
<span class="line" id="L124"> <span class="tok-kw">const</span> arg = arg_arg;</span>
<span class="line" id="L125"> <span class="tok-kw">if</span> ((((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) != <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>)))))) <span class="tok-kw">and</span> (fiobj_type_vtable(o).*.each != <span class="tok-null">null</span>)) <span class="tok-kw">return</span> fiobj_type_vtable(o).*.each.?(o, start_at, task, arg);</span>
<span class="line" id="L126"> <span class="tok-kw">return</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L127">}</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_hash_new</span>() FIOBJ;</span>
<span class="line" id="L130"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_hash_set</span>(hash: FIOBJ, key: FIOBJ, obj: FIOBJ) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L131"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_hash_get</span>(hash: FIOBJ, key: FIOBJ) FIOBJ;</span>
<span class="line" id="L132"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_hash_pop</span>(hash: FIOBJ, key: [*c]FIOBJ) FIOBJ;</span>
<span class="line" id="L133"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_hash_count</span>(hash: FIOBJ) <span class="tok-type">usize</span>;</span>
<span class="line" id="L134"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_hash_key_in_loop</span>() FIOBJ;</span>
<span class="line" id="L135"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_hash_haskey</span>(hash: FIOBJ, key: FIOBJ) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L136"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_new</span>() FIOBJ;</span>
<span class="line" id="L137"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_new2</span>(capa: <span class="tok-type">usize</span>) FIOBJ;</span>
<span class="line" id="L138"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_count</span>(ary: FIOBJ) <span class="tok-type">usize</span>;</span>
<span class="line" id="L139"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_capa</span>(ary: FIOBJ) <span class="tok-type">usize</span>;</span>
<span class="line" id="L140"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary2ptr</span>(ary: FIOBJ) [*c]FIOBJ;</span>
<span class="line" id="L141"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_index</span>(ary: FIOBJ, pos: <span class="tok-type">i64</span>) FIOBJ;</span>
<span class="line" id="L142"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_set</span>(ary: FIOBJ, obj: FIOBJ, pos: <span class="tok-type">i64</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L143"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_push</span>(ary: FIOBJ, obj: FIOBJ) <span class="tok-type">void</span>;</span>
<span class="line" id="L144"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_pop</span>(ary: FIOBJ) FIOBJ;</span>
<span class="line" id="L145"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_unshift</span>(ary: FIOBJ, obj: FIOBJ) <span class="tok-type">void</span>;</span>
<span class="line" id="L146"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_shift</span>(ary: FIOBJ) FIOBJ;</span>
<span class="line" id="L147"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_replace</span>(ary: FIOBJ, obj: FIOBJ, pos: <span class="tok-type">i64</span>) FIOBJ;</span>
<span class="line" id="L148"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_find</span>(ary: FIOBJ, data: FIOBJ) <span class="tok-type">i64</span>;</span>
<span class="line" id="L149"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_remove</span>(ary: FIOBJ, pos: <span class="tok-type">i64</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L150"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_remove2</span>(ary: FIOBJ, data: FIOBJ) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L151"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_compact</span>(ary: FIOBJ) <span class="tok-type">void</span>;</span>
<span class="line" id="L152"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_float_new</span>(num: <span class="tok-type">f64</span>) FIOBJ;</span>
<span class="line" id="L153"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_num_new_bignum</span>(num: <span class="tok-type">isize</span>) FIOBJ;</span>
<span class="line" id="L154"></span>
<span class="line" id="L155"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_newstr</span>() FIOBJ;</span>
<span class="line" id="L156"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_newstr2</span>(buffer: ?*<span class="tok-type">anyopaque</span>, length: <span class="tok-type">usize</span>, dealloc: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>) FIOBJ;</span>
<span class="line" id="L157"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_newtmpfile</span>() FIOBJ;</span>
<span class="line" id="L158"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_newfd</span>(fd: <span class="tok-type">c_int</span>) FIOBJ;</span>
<span class="line" id="L159"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_slice</span>(parent: FIOBJ, offset: <span class="tok-type">isize</span>, length: <span class="tok-type">usize</span>) FIOBJ;</span>
<span class="line" id="L160"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_save</span>(io: FIOBJ, filename: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L161"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_read</span>(io: FIOBJ, length: <span class="tok-type">isize</span>) fio_str_info_s;</span>
<span class="line" id="L162"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_read2ch</span>(io: FIOBJ, token: <span class="tok-type">u8</span>) fio_str_info_s;</span>
<span class="line" id="L163"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_pos</span>(io: FIOBJ) <span class="tok-type">isize</span>;</span>
<span class="line" id="L164"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_len</span>(io: FIOBJ) <span class="tok-type">isize</span>;</span>
<span class="line" id="L165"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_seek</span>(io: FIOBJ, position: <span class="tok-type">isize</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L166"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_pread</span>(io: FIOBJ, start_at: <span class="tok-type">isize</span>, length: <span class="tok-type">usize</span>) fio_str_info_s;</span>
<span class="line" id="L167"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_write</span>(io: FIOBJ, buffer: ?*<span class="tok-type">anyopaque</span>, length: <span class="tok-type">usize</span>) <span class="tok-type">isize</span>;</span>
<span class="line" id="L168"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_puts</span>(io: FIOBJ, buffer: ?*<span class="tok-type">anyopaque</span>, length: <span class="tok-type">usize</span>) <span class="tok-type">isize</span>;</span>
<span class="line" id="L169"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_data_assert_dynamic</span>(io: FIOBJ) <span class="tok-type">void</span>;</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"><span class="tok-comment">/// Creates a new SSL/TLS context / settings object with a default certificate (if any).</span></span>
<span class="line" id="L172"><span class="tok-comment">/// If a server name is provided, than NULL values can be used to create an anonymous (unverified)</span></span>
<span class="line" id="L173"><span class="tok-comment">/// context / settings object. If all values are NULL, a TLS object will be created without a</span></span>
<span class="line" id="L174"><span class="tok-comment">/// certificate. This could be used for clients together with fio_tls_trust. fio_tls_s * is an</span></span>
<span class="line" id="L175"><span class="tok-comment">/// opaque type used as a handle for the SSL/TLS functions. It shouldn't be directly accessed.</span></span>
<span class="line" id="L176"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_tls_new</span>(</span>
<span class="line" id="L177"> server_name: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L178"> public_certificate_file: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L179"> private_key_file: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L180"> private_key_password: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L181">) ?*<span class="tok-type">anyopaque</span>;</span>
<span class="line" id="L182"></span>
<span class="line" id="L183"><span class="tok-comment">/// Increase the reference count for the TLS object.</span></span>
<span class="line" id="L184"><span class="tok-comment">/// Decrease / free with fio_tls_destroy.</span></span>
<span class="line" id="L185"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_tls_dup</span>(tls: ?*<span class="tok-type">anyopaque</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L186"></span>
<span class="line" id="L187"><span class="tok-comment">/// Destroys the SSL/TLS context / settings object and frees any related resources / memory.</span></span>
<span class="line" id="L188"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_tls_destroy</span>(tls: ?*<span class="tok-type">anyopaque</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L189"></span>
<span class="line" id="L190"><span class="tok-comment">/// Adds a certificate a new SSL/TLS context / settings object (SNI support).</span></span>
<span class="line" id="L191"><span class="tok-comment">/// The private_key_password can be NULL if the private key PEM file isn't password protected.</span></span>
<span class="line" id="L192"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_tls_cert_add</span>(</span>
<span class="line" id="L193"> tls: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L194"> server_name: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L195"> public_certificate_file: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L196"> private_key_file: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L197"> private_key_password: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L198">) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L199"></span>
<span class="line" id="L200"><span class="tok-comment">/// Adds a certificate to the &quot;trust&quot; list, which automatically adds a peer verification requirement.</span></span>
<span class="line" id="L201"><span class="tok-comment">/// Note: when the fio_tls_s object is used for server connections, this will limit connections to</span></span>
<span class="line" id="L202"><span class="tok-comment">/// clients that connect using a trusted certificate.</span></span>
<span class="line" id="L203"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_tls_trust</span>(tls: ?*<span class="tok-type">anyopaque</span>, public_cert_file: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L204"></span>
<span class="line" id="L205"><span class="tok-comment">/// Establishes an SSL/TLS connection as an SSL/TLS Server, using the specified context / settings object.</span></span>
<span class="line" id="L206"><span class="tok-comment">/// The uuid should be a socket UUID that is already connected to a peer (i.e., the result of fio_accept).</span></span>
<span class="line" id="L207"><span class="tok-comment">/// The udata is an opaque user data pointer that is passed along to the protocol selected (if any protocols</span></span>
<span class="line" id="L208"><span class="tok-comment">/// were added using fio_tls_alpn_add).</span></span>
<span class="line" id="L209"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_tls_accept</span>(uuid: *<span class="tok-type">u32</span>, tls: ?*<span class="tok-type">anyopaque</span>, udata: ?*<span class="tok-type">anyopaque</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L210"></span>
<span class="line" id="L211"><span class="tok-comment">/// Establishes an SSL/TLS connection as an SSL/TLS Client, using the specified context / settings object.</span></span>
<span class="line" id="L212"><span class="tok-comment">/// The uuid should be a socket UUID that is already connected to a peer (i.e., one received by a fio_connect</span></span>
<span class="line" id="L213"><span class="tok-comment">/// specified callback on_connect).</span></span>
<span class="line" id="L214"><span class="tok-comment">/// The udata is an opaque user data pointer that is passed along to the protocol selected (if any protocols</span></span>
<span class="line" id="L215"><span class="tok-comment">/// were added using fio_tls_alpn_add).</span></span>
<span class="line" id="L216"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_tls_connect</span>(uuid: *<span class="tok-type">u32</span>, tls: ?*<span class="tok-type">anyopaque</span>, udata: ?*<span class="tok-type">anyopaque</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L217"></span>
<span class="line" id="L218"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_free_wrapped</span>(o: FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>;</span>
<span class="line" id="L219"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_null</span>() <span class="tok-kw">callconv</span>(.C) FIOBJ {</span>
<span class="line" id="L220"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(FIOBJ, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, FIOBJ_T_NULL)));</span>
<span class="line" id="L221">}</span>
<span class="line" id="L222"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_true</span>() <span class="tok-kw">callconv</span>(.C) FIOBJ {</span>
<span class="line" id="L223"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(FIOBJ, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, FIOBJ_T_TRUE)));</span>
<span class="line" id="L224">}</span>
<span class="line" id="L225"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_false</span>() <span class="tok-kw">callconv</span>(.C) FIOBJ {</span>
<span class="line" id="L226"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(FIOBJ, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, FIOBJ_T_FALSE)));</span>
<span class="line" id="L227">}</span>
<span class="line" id="L228"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_str_new</span>(str: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, len: <span class="tok-type">usize</span>) FIOBJ;</span>
<span class="line" id="L229"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_str_buf</span>(capa: <span class="tok-type">usize</span>) FIOBJ;</span>
<span class="line" id="L230"></span>
<span class="line" id="L231"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">FIOBJ_TYPE</span>(obj: <span class="tok-kw">anytype</span>) <span class="tok-builtin">@TypeOf</span>(fiobj_type(obj)) {</span>
<span class="line" id="L232"> <span class="tok-kw">return</span> fiobj_type(obj);</span>
<span class="line" id="L233">}</span>
<span class="line" id="L234"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">FIOBJ_TYPE_IS</span>(obj: <span class="tok-kw">anytype</span>, @&quot;type&quot;: <span class="tok-kw">anytype</span>) <span class="tok-builtin">@TypeOf</span>(fiobj_type_is(obj, @&quot;type&quot;)) {</span>
<span class="line" id="L235"> <span class="tok-kw">return</span> fiobj_type_is(obj, @&quot;type&quot;);</span>
<span class="line" id="L236">}</span>
<span class="line" id="L237"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">FIOBJ_IS_NULL</span>(obj: <span class="tok-kw">anytype</span>) <span class="tok-builtin">@TypeOf</span>(!(obj != <span class="tok-number">0</span>) <span class="tok-kw">or</span> (obj == <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).zig.c_translation.cast(FIOBJ, FIOBJ_T_NULL))) {</span>
<span class="line" id="L238"> <span class="tok-kw">return</span> !(obj != <span class="tok-number">0</span>) <span class="tok-kw">or</span> (obj == <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).zig.c_translation.cast(FIOBJ, FIOBJ_T_NULL));</span>
<span class="line" id="L239">}</span>
<span class="line" id="L240"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_INVALID = <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>);</span>
<span class="line" id="L241"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJECT_NUMBER_FLAG = <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>);</span>
<span class="line" id="L242"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJECT_PRIMITIVE_FLAG = <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>);</span>
<span class="line" id="L243"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJECT_STRING_FLAG = <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">2</span>);</span>
<span class="line" id="L244"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJECT_HASH_FLAG = <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">4</span>);</span>
<span class="line" id="L245"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJECT_TYPE_MASK = ~<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).zig.c_translation.cast(<span class="tok-type">usize</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">7</span>));</span>
<span class="line" id="L246"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_NUMBER_SIGN_MASK = ~<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).zig.c_translation.cast(<span class="tok-type">usize</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>);</span>
<span class="line" id="L247"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_NUMBER_SIGN_BIT = ~FIOBJ_NUMBER_SIGN_MASK;</span>
<span class="line" id="L248"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_NUMBER_SIGN_EXCLUDE_BIT = FIOBJ_NUMBER_SIGN_BIT &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>);</span>
<span class="line" id="L249"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">FIOBJ_IS_ALLOCATED</span>(o: <span class="tok-kw">anytype</span>) <span class="tok-builtin">@TypeOf</span>(((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; FIOBJECT_NUMBER_FLAG) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>))) <span class="tok-kw">and</span> ((o &amp; FIOBJECT_PRIMITIVE_FLAG) != FIOBJECT_PRIMITIVE_FLAG)) {</span>
<span class="line" id="L250"> <span class="tok-kw">return</span> ((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; FIOBJECT_NUMBER_FLAG) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>))) <span class="tok-kw">and</span> ((o &amp; FIOBJECT_PRIMITIVE_FLAG) != FIOBJECT_PRIMITIVE_FLAG);</span>
<span class="line" id="L251">}</span>
<span class="line" id="L252"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">FIOBJ2PTR</span>(o: <span class="tok-kw">anytype</span>) ?*<span class="tok-type">anyopaque</span> {</span>
<span class="line" id="L253"> <span class="tok-kw">return</span> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).zig.c_translation.cast(?*<span class="tok-type">anyopaque</span>, o &amp; FIOBJECT_TYPE_MASK);</span>
<span class="line" id="L254">}</span>
<span class="line" id="L255"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">FIOBJECT2VTBL</span>(o: <span class="tok-kw">anytype</span>) <span class="tok-builtin">@TypeOf</span>(fiobj_type_vtable(o)) {</span>
<span class="line" id="L256"> <span class="tok-kw">return</span> fiobj_type_vtable(o);</span>
<span class="line" id="L257">}</span>
<span class="line" id="L258"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">FIOBJECT2HEAD</span>(o: <span class="tok-kw">anytype</span>) [*c]fiobj_object_header_s {</span>
<span class="line" id="L259"> <span class="tok-kw">return</span> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).zig.c_translation.cast([*c]fiobj_object_header_s, FIOBJ2PTR(o));</span>
<span class="line" id="L260">}</span>
<span class="line" id="L261"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_ary_entry</span>(a: <span class="tok-kw">anytype</span>, p: <span class="tok-kw">anytype</span>) <span class="tok-builtin">@TypeOf</span>(fiobj_ary_index(a, p)) {</span>
<span class="line" id="L262"> <span class="tok-kw">return</span> fiobj_ary_index(a, p);</span>
<span class="line" id="L263">}</span>
<span class="line" id="L264"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_NUMBER: <span class="tok-type">c_int</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L265"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_NULL: <span class="tok-type">c_int</span> = <span class="tok-number">6</span>;</span>
<span class="line" id="L266"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_TRUE: <span class="tok-type">c_int</span> = <span class="tok-number">22</span>;</span>
<span class="line" id="L267"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_FALSE: <span class="tok-type">c_int</span> = <span class="tok-number">38</span>;</span>
<span class="line" id="L268"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_FLOAT: <span class="tok-type">c_int</span> = <span class="tok-number">39</span>;</span>
<span class="line" id="L269"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_STRING: <span class="tok-type">c_int</span> = <span class="tok-number">40</span>;</span>
<span class="line" id="L270"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_ARRAY: <span class="tok-type">c_int</span> = <span class="tok-number">41</span>;</span>
<span class="line" id="L271"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_HASH: <span class="tok-type">c_int</span> = <span class="tok-number">42</span>;</span>
<span class="line" id="L272"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_DATA: <span class="tok-type">c_int</span> = <span class="tok-number">43</span>;</span>
<span class="line" id="L273"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FIOBJ_T_UNKNOWN: <span class="tok-type">c_int</span> = <span class="tok-number">44</span>;</span>
<span class="line" id="L274"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fiobj_type_enum = <span class="tok-type">u8</span>;</span>
<span class="line" id="L275"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fiobj_object_vtable_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L276"> class_name: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L277"> dealloc: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ, ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L278"> count: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span>,</span>
<span class="line" id="L279"> is_true: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span>,</span>
<span class="line" id="L280"> is_eq: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ, FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span>,</span>
<span class="line" id="L281"> each: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ, <span class="tok-type">usize</span>, ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">c_int</span>, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span>,</span>
<span class="line" id="L282"> to_str: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ) <span class="tok-kw">callconv</span>(.C) fio_str_info_s,</span>
<span class="line" id="L283"> to_i: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">isize</span>,</span>
<span class="line" id="L284"> to_f: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">f64</span>,</span>
<span class="line" id="L285">};</span>
<span class="line" id="L286"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fiobj_object_header_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L287"> <span class="tok-type">type</span>: fiobj_type_enum,</span>
<span class="line" id="L288"> ref: <span class="tok-type">u32</span>,</span>
<span class="line" id="L289">};</span>
<span class="line" id="L290"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_type_is</span>(arg_o: FIOBJ, arg_type: fiobj_type_enum) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span> {</span>
<span class="line" id="L291"> <span class="tok-kw">const</span> o = arg_o;</span>
<span class="line" id="L292"> <span class="tok-kw">const</span> @&quot;type&quot; = arg_type;</span>
<span class="line" id="L293"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L294"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, @&quot;type&quot;)))) {</span>
<span class="line" id="L295"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>) =&gt; <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>(((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) != <span class="tok-number">0</span>) <span class="tok-kw">or</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@as</span>([*c]fiobj_type_enum, <span class="tok-builtin">@ptrFromInt</span>(o))[<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))]))) == FIOBJ_T_NUMBER))))),</span>
<span class="line" id="L296"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>) =&gt; <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>(!(o != <span class="tok-number">0</span>) <span class="tok-kw">or</span> (o == fiobj_null()))))),</span>
<span class="line" id="L297"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">22</span>) =&gt; <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>(o == fiobj_true())))),</span>
<span class="line" id="L298"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">38</span>) =&gt; <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>(o == fiobj_false())))),</span>
<span class="line" id="L299"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">40</span>) =&gt; <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>(((<span class="tok-null">true</span> <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">2</span>)))))) <span class="tok-kw">or</span> (((<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">2</span>) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)) <span class="tok-kw">and</span> (((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) != <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))))) <span class="tok-kw">and</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@as</span>([*c]fiobj_type_enum, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(<span class="tok-builtin">@as</span>(?*<span class="tok-type">anyopaque</span>, <span class="tok-builtin">@ptrFromInt</span>(o &amp; ~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">7</span>)))))))))[<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))]))) == FIOBJ_T_STRING)))))),</span>
<span class="line" id="L300"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">42</span>) =&gt; {</span>
<span class="line" id="L301"> <span class="tok-kw">if</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L302"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>(((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">4</span>)))))))));</span>
<span class="line" id="L303"> }</span>
<span class="line" id="L304"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>((((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) != <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>)))))) <span class="tok-kw">and</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@as</span>([*c]fiobj_type_enum, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(<span class="tok-builtin">@as</span>(?*<span class="tok-type">anyopaque</span>, <span class="tok-builtin">@ptrFromInt</span>(o &amp; ~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">7</span>)))))))))[<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))]))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, @&quot;type&quot;))))))));</span>
<span class="line" id="L305"> },</span>
<span class="line" id="L306"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">39</span>), <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">41</span>), <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">43</span>), <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">44</span>) =&gt; <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>((((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) != <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>)))))) <span class="tok-kw">and</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@as</span>([*c]fiobj_type_enum, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(<span class="tok-builtin">@as</span>(?*<span class="tok-type">anyopaque</span>, <span class="tok-builtin">@ptrFromInt</span>(o &amp; ~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">7</span>)))))))))[<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))]))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, @&quot;type&quot;)))))))),</span>
<span class="line" id="L307"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L308"> }</span>
<span class="line" id="L309"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L310"> }</span>
<span class="line" id="L311"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>((((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) != <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>)))))) <span class="tok-kw">and</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@as</span>([*c]fiobj_type_enum, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(<span class="tok-builtin">@as</span>(?*<span class="tok-type">anyopaque</span>, <span class="tok-builtin">@ptrFromInt</span>(o &amp; ~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">7</span>)))))))))[<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))]))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, @&quot;type&quot;))))))));</span>
<span class="line" id="L312">}</span>
<span class="line" id="L313"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_type</span>(arg_o: FIOBJ) <span class="tok-kw">callconv</span>(.C) fiobj_type_enum {</span>
<span class="line" id="L314"> <span class="tok-kw">const</span> o = arg_o;</span>
<span class="line" id="L315"> <span class="tok-kw">if</span> (!(o != <span class="tok-number">0</span>)) <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, <span class="tok-builtin">@truncate</span>(FIOBJ_T_NULL))));</span>
<span class="line" id="L316"> <span class="tok-kw">if</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) != <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, <span class="tok-builtin">@truncate</span>(FIOBJ_T_NUMBER))));</span>
<span class="line" id="L317"> <span class="tok-kw">if</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@truncate</span>(o))));</span>
<span class="line" id="L318"> <span class="tok-kw">if</span> (<span class="tok-null">true</span> <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">2</span>)))))) <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, <span class="tok-builtin">@truncate</span>(FIOBJ_T_STRING))));</span>
<span class="line" id="L319"> <span class="tok-kw">if</span> (<span class="tok-null">true</span> <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">4</span>)))))) <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, <span class="tok-builtin">@truncate</span>(FIOBJ_T_HASH))));</span>
<span class="line" id="L320"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>([*c]fiobj_type_enum, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(<span class="tok-builtin">@as</span>(?*<span class="tok-type">anyopaque</span>, <span class="tok-builtin">@ptrFromInt</span>(o &amp; ~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">7</span>)))))))))[<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))];</span>
<span class="line" id="L321">}</span>
<span class="line" id="L322"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> FIOBJECT_VTABLE_NUMBER: fiobj_object_vtable_s;</span>
<span class="line" id="L323"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> FIOBJECT_VTABLE_FLOAT: fiobj_object_vtable_s;</span>
<span class="line" id="L324"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> FIOBJECT_VTABLE_STRING: fiobj_object_vtable_s;</span>
<span class="line" id="L325"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> FIOBJECT_VTABLE_ARRAY: fiobj_object_vtable_s;</span>
<span class="line" id="L326"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> FIOBJECT_VTABLE_HASH: fiobj_object_vtable_s;</span>
<span class="line" id="L327"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> FIOBJECT_VTABLE_DATA: fiobj_object_vtable_s;</span>
<span class="line" id="L328"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_type_vtable</span>(arg_o: FIOBJ) <span class="tok-kw">callconv</span>(.C) [*c]<span class="tok-kw">const</span> fiobj_object_vtable_s {</span>
<span class="line" id="L329"> <span class="tok-kw">const</span> o = arg_o;</span>
<span class="line" id="L330"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L331"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, fiobj_type(o))))) {</span>
<span class="line" id="L332"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>) =&gt; <span class="tok-kw">return</span> &amp;FIOBJECT_VTABLE_NUMBER,</span>
<span class="line" id="L333"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">39</span>) =&gt; <span class="tok-kw">return</span> &amp;FIOBJECT_VTABLE_FLOAT,</span>
<span class="line" id="L334"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">40</span>) =&gt; <span class="tok-kw">return</span> &amp;FIOBJECT_VTABLE_STRING,</span>
<span class="line" id="L335"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">41</span>) =&gt; <span class="tok-kw">return</span> &amp;FIOBJECT_VTABLE_ARRAY,</span>
<span class="line" id="L336"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">42</span>) =&gt; <span class="tok-kw">return</span> &amp;FIOBJECT_VTABLE_HASH,</span>
<span class="line" id="L337"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">43</span>) =&gt; <span class="tok-kw">return</span> &amp;FIOBJECT_VTABLE_DATA,</span>
<span class="line" id="L338"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>), <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">22</span>), <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">38</span>), <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">44</span>) =&gt; <span class="tok-kw">return</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L339"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L340"> }</span>
<span class="line" id="L341"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L342"> }</span>
<span class="line" id="L343"> <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L344">}</span>
<span class="line" id="L345"></span>
<span class="line" id="L346"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_obj2num</span>(o: FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">isize</span> {</span>
<span class="line" id="L347"> <span class="tok-kw">if</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) != <span class="tok-number">0</span>) {</span>
<span class="line" id="L348"> <span class="tok-kw">const</span> sign: <span class="tok-type">usize</span> = <span class="tok-kw">if</span> ((o &amp; ~(~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).math.Log2Int(<span class="tok-type">usize</span>), <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>)))) != <span class="tok-number">0</span>) ~(~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).math.Log2Int(<span class="tok-type">usize</span>), <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>))) | (~(~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).math.Log2Int(<span class="tok-type">usize</span>), <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>))) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).math.Log2Int(<span class="tok-type">usize</span>), <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>))) <span class="tok-kw">else</span> <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>))));</span>
<span class="line" id="L349"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@bitCast</span>(((o &amp; (~<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).math.Log2Int(<span class="tok-type">usize</span>), <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>)))) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).math.Log2Int(<span class="tok-type">c_ulong</span>), <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>))) | sign));</span>
<span class="line" id="L350"> }</span>
<span class="line" id="L351"> <span class="tok-kw">if</span> (!(o != <span class="tok-number">0</span>) <span class="tok-kw">or</span> !(((o != <span class="tok-number">0</span>) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))))) <span class="tok-kw">and</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) != <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))))) <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@intFromBool</span>(o == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, FIOBJ_T_TRUE)))))));</span>
<span class="line" id="L352"> <span class="tok-kw">return</span> fiobj_type_vtable(o).*.to_i.?(o);</span>
<span class="line" id="L353">}</span>
<span class="line" id="L354"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_obj2float</span>(o: FIOBJ) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">f64</span> {</span>
<span class="line" id="L355"> <span class="tok-kw">if</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) != <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">f64</span>, <span class="tok-builtin">@floatFromInt</span>(fiobj_obj2num(o)));</span>
<span class="line" id="L356"> <span class="tok-comment">// the below doesn't parse and we don't support ints here anyway</span>
</span>
<span class="line" id="L357"> <span class="tok-comment">// if (!(o != 0) or ((o &amp; @bitCast(c_ulong, @as(c_long, @as(c_int, 6)))) == @bitCast(c_ulong, @as(c_long, @as(c_int, 6))))) return @intToFloat(f64, o == @bitCast(c_ulong, @as(c_long, FIOBJ_T_TRUE)));</span>
</span>
<span class="line" id="L358"> <span class="tok-kw">return</span> fiobj_type_vtable(o).*.to_f.?(o);</span>
<span class="line" id="L359">}</span>
<span class="line" id="L360"></span>
<span class="line" id="L361"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_ltocstr</span>(<span class="tok-type">c_long</span>) fio_str_info_s;</span>
<span class="line" id="L362"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_obj2cstr</span>(o: FIOBJ) <span class="tok-kw">callconv</span>(.C) fio_str_info_s {</span>
<span class="line" id="L363"> <span class="tok-kw">if</span> (!(o != <span class="tok-number">0</span>)) {</span>
<span class="line" id="L364"> <span class="tok-kw">const</span> ret: fio_str_info_s = fio_str_info_s{</span>
<span class="line" id="L365"> .capa = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))),</span>
<span class="line" id="L366"> .len = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">4</span>)))),</span>
<span class="line" id="L367"> .data = <span class="tok-builtin">@as</span>([*c]<span class="tok-type">u8</span>, <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(<span class="tok-str">&quot;null&quot;</span>))),</span>
<span class="line" id="L368"> };</span>
<span class="line" id="L369"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L370"> }</span>
<span class="line" id="L371"> <span class="tok-kw">if</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">1</span>))))) != <span class="tok-number">0</span>) <span class="tok-kw">return</span> fio_ltocstr(<span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@bitCast</span>(o)) &gt;&gt; <span class="tok-builtin">@as</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).math.Log2Int(<span class="tok-type">isize</span>), <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>)));</span>
<span class="line" id="L372"> <span class="tok-kw">if</span> ((o &amp; <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) == <span class="tok-builtin">@as</span>(<span class="tok-type">c_ulong</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>))))) {</span>
<span class="line" id="L373"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L374"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_uint</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@truncate</span>(o)))))))) {</span>
<span class="line" id="L375"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">6</span>) =&gt; {</span>
<span class="line" id="L376"> {</span>
<span class="line" id="L377"> <span class="tok-kw">const</span> ret: fio_str_info_s = fio_str_info_s{</span>
<span class="line" id="L378"> .capa = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))),</span>
<span class="line" id="L379"> .len = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">4</span>)))),</span>
<span class="line" id="L380"> .data = <span class="tok-builtin">@as</span>([*c]<span class="tok-type">u8</span>, <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(<span class="tok-str">&quot;null&quot;</span>))),</span>
<span class="line" id="L381"> };</span>
<span class="line" id="L382"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L383"> }</span>
<span class="line" id="L384"> },</span>
<span class="line" id="L385"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">38</span>) =&gt; {</span>
<span class="line" id="L386"> {</span>
<span class="line" id="L387"> <span class="tok-kw">const</span> ret: fio_str_info_s = fio_str_info_s{</span>
<span class="line" id="L388"> .capa = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))),</span>
<span class="line" id="L389"> .len = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">5</span>)))),</span>
<span class="line" id="L390"> .data = <span class="tok-builtin">@as</span>([*c]<span class="tok-type">u8</span>, <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(<span class="tok-str">&quot;false&quot;</span>))),</span>
<span class="line" id="L391"> };</span>
<span class="line" id="L392"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L393"> }</span>
<span class="line" id="L394"> },</span>
<span class="line" id="L395"> <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">22</span>) =&gt; {</span>
<span class="line" id="L396"> {</span>
<span class="line" id="L397"> <span class="tok-kw">const</span> ret: fio_str_info_s = fio_str_info_s{</span>
<span class="line" id="L398"> .capa = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">0</span>)))),</span>
<span class="line" id="L399"> .len = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">c_long</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">c_int</span>, <span class="tok-number">4</span>)))),</span>
<span class="line" id="L400"> .data = <span class="tok-builtin">@as</span>([*c]<span class="tok-type">u8</span>, <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(<span class="tok-str">&quot;true&quot;</span>))),</span>
<span class="line" id="L401"> };</span>
<span class="line" id="L402"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L403"> }</span>
<span class="line" id="L404"> },</span>
<span class="line" id="L405"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">break</span>,</span>
<span class="line" id="L406"> }</span>
<span class="line" id="L407"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L408"> }</span>
<span class="line" id="L409"> }</span>
<span class="line" id="L410"> <span class="tok-kw">return</span> fiobj_type_vtable(o).*.to_str.?(o);</span>
<span class="line" id="L411">}</span>
<span class="line" id="L412"><span class="tok-comment">// pub const http_cookie_args_s = opaque {};</span>
</span>
<span class="line" id="L413"></span>
<span class="line" id="L414"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_set_header</span>(h: [*c]http_s, name: FIOBJ, value: FIOBJ) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L415"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_set_header2</span>(h: [*c]http_s, name: fio_str_info_s, value: fio_str_info_s) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L416"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_set_cookie</span>(h: [*c]http_s, http_cookie_args_s) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L417"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sendfile</span>(h: [*c]http_s, fd: <span class="tok-type">c_int</span>, length: <span class="tok-type">usize</span>, offset: <span class="tok-type">usize</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L418"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sendfile2</span>(h: [*c]http_s, prefix: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, prefix_len: <span class="tok-type">usize</span>, encoded: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, encoded_len: <span class="tok-type">usize</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L419"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_send_error</span>(h: [*c]http_s, error_code: <span class="tok-type">usize</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L420"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_finish</span>(h: [*c]http_s) <span class="tok-type">void</span>;</span>
<span class="line" id="L421"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_push_data</span>(h: [*c]http_s, data: ?*<span class="tok-type">anyopaque</span>, length: <span class="tok-type">usize</span>, mime_type: FIOBJ) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L422"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_push_file</span>(h: [*c]http_s, filename: FIOBJ, mime_type: FIOBJ) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L423"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_http_pause_handle_s = <span class="tok-kw">opaque</span> {};</span>
<span class="line" id="L424"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> http_pause_handle_s = struct_http_pause_handle_s;</span>
<span class="line" id="L425"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_pause</span>(h: [*c]http_s, task: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*http_pause_handle_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L426"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_resume</span>(http: ?*http_pause_handle_s, task: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>, fallback: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L427"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_paused_udata_get</span>(http: ?*http_pause_handle_s) ?*<span class="tok-type">anyopaque</span>;</span>
<span class="line" id="L428"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_paused_udata_set</span>(http: ?*http_pause_handle_s, udata: ?*<span class="tok-type">anyopaque</span>) ?*<span class="tok-type">anyopaque</span>;</span>
<span class="line" id="L429"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_listen</span>(port: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, binding: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, struct_http_settings_s) <span class="tok-type">isize</span>;</span>
<span class="line" id="L430"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_connect</span>(url: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, unix_address: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, struct_http_settings_s) <span class="tok-type">isize</span>;</span>
<span class="line" id="L431"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_settings</span>(h: [*c]http_s) [*c]struct_http_settings_s;</span>
<span class="line" id="L432"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_peer_addr</span>(h: [*c]http_s) fio_str_info_s;</span>
<span class="line" id="L433"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_hijack</span>(h: [*c]http_s, leftover: [*c]fio_str_info_s) <span class="tok-type">isize</span>;</span>
<span class="line" id="L434"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_ws_s = <span class="tok-kw">opaque</span> {};</span>
<span class="line" id="L435"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ws_s = struct_ws_s;</span>
<span class="line" id="L436"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> websocket_settings_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L437"> on_message: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*ws_s, fio_str_info_s, <span class="tok-type">u8</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L438"> on_open: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*ws_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L439"> on_ready: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*ws_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L440"> on_shutdown: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*ws_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L441"> on_close: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (<span class="tok-type">isize</span>, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L442"> udata: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L443">};</span>
<span class="line" id="L444"></span>
<span class="line" id="L445"><span class="tok-comment">// struct websocket_subscribe_s_zigcompat {</span>
</span>
<span class="line" id="L446"><span class="tok-comment">// ws_s *ws;</span>
</span>
<span class="line" id="L447"><span class="tok-comment">// fio_str_info_s channel;</span>
</span>
<span class="line" id="L448"><span class="tok-comment">// void (*on_message)(ws_s *ws, fio_str_info_s channel, fio_str_info_s msg, void *udata);</span>
</span>
<span class="line" id="L449"><span class="tok-comment">// void (*on_unsubscribe)(void *udata);</span>
</span>
<span class="line" id="L450"><span class="tok-comment">// void *udata;</span>
</span>
<span class="line" id="L451"><span class="tok-comment">// fio_match_fn match;</span>
</span>
<span class="line" id="L452"><span class="tok-comment">// unsigned char force_binary;</span>
</span>
<span class="line" id="L453"><span class="tok-comment">// unsigned char force_text;</span>
</span>
<span class="line" id="L454"><span class="tok-comment">// };</span>
</span>
<span class="line" id="L455"></span>
<span class="line" id="L456"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> websocket_subscribe_s_zigcompat = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L457"> ws: ?*ws_s,</span>
<span class="line" id="L458"> channel: fio_str_info_s,</span>
<span class="line" id="L459"> on_message: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*ws_s, fio_str_info_s, fio_str_info_s, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L460"> on_unsubscribe: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L461"> udata: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L462"> match: fio_match_fn,</span>
<span class="line" id="L463"> force_binary: <span class="tok-type">u8</span>,</span>
<span class="line" id="L464"> force_text: <span class="tok-type">u8</span>,</span>
<span class="line" id="L465">};</span>
<span class="line" id="L466"></span>
<span class="line" id="L467"><span class="tok-comment">/// 0 on failure</span></span>
<span class="line" id="L468"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_subscribe_zigcompat</span>(websocket_subscribe_s_zigcompat) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span>;</span>
<span class="line" id="L469"></span>
<span class="line" id="L470"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_upgrade2ws</span>(http: [*c]http_s, websocket_settings_s) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L471"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_connect</span>(url: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, settings: websocket_settings_s) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L472"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_attach</span>(uuid: <span class="tok-type">isize</span>, http_settings: [*c]http_settings_s, args: [*c]websocket_settings_s, data: ?*<span class="tok-type">anyopaque</span>, length: <span class="tok-type">usize</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L473"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_udata_get</span>(ws: ?*ws_s) ?*<span class="tok-type">anyopaque</span>;</span>
<span class="line" id="L474"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_udata_set</span>(ws: ?*ws_s, udata: ?*<span class="tok-type">anyopaque</span>) ?*<span class="tok-type">anyopaque</span>;</span>
<span class="line" id="L475"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_uuid</span>(ws: ?*ws_s) <span class="tok-type">isize</span>;</span>
<span class="line" id="L476"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_is_client</span>(ws: ?*ws_s) <span class="tok-type">u8</span>;</span>
<span class="line" id="L477"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_write</span>(ws: ?*ws_s, msg: fio_str_info_s, is_text: <span class="tok-type">u8</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L478"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_close</span>(ws: ?*ws_s) <span class="tok-type">void</span>; <span class="tok-comment">// zig-cache/i/e0c8a6e617497ade13de512cbe191f23/include/websockets.h:104:12: warning: struct demoted to opaque type - has bitfield</span>
</span>
<span class="line" id="L479"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_websocket_subscribe_s = <span class="tok-kw">opaque</span> {};</span>
<span class="line" id="L480"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_subscribe</span>(args: struct_websocket_subscribe_s) <span class="tok-type">usize</span>;</span>
<span class="line" id="L481"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_unsubscribe</span>(ws: ?*ws_s, subscription_id: <span class="tok-type">usize</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L482"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">websocket_optimize4broadcasts</span>(@&quot;type&quot;: <span class="tok-type">isize</span>, enable: <span class="tok-type">c_int</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L483"></span>
<span class="line" id="L484"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_publish</span>(args: fio_publish_args_s) <span class="tok-type">void</span>;</span>
<span class="line" id="L485"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fio_publish_args_s = struct_fio_publish_args_s;</span>
<span class="line" id="L486"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_fio_publish_args_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L487"> engine: ?*<span class="tok-type">anyopaque</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L488"> <span class="tok-comment">// we don't support engines other than default</span>
</span>
<span class="line" id="L489"> <span class="tok-comment">// engine: [*c]const fio_pubsub_engine_s,</span>
</span>
<span class="line" id="L490"> filter: <span class="tok-type">i32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L491"> channel: fio_str_info_s,</span>
<span class="line" id="L492"> message: fio_str_info_s,</span>
<span class="line" id="L493"> is_json: <span class="tok-type">u8</span>,</span>
<span class="line" id="L494">};</span>
<span class="line" id="L495"></span>
<span class="line" id="L496"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> http_sse_s = struct_http_sse_s;</span>
<span class="line" id="L497"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_http_sse_s = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L498"> on_open: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_sse_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L499"> on_ready: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_sse_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L500"> on_shutdown: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_sse_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L501"> on_close: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_sse_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L502"> udata: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L503">};</span>
<span class="line" id="L504"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_upgrade2sse</span>(h: [*c]http_s, http_sse_s) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L505"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse_set_timout</span>(sse: [*c]http_sse_s, timeout: <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L506"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fio_match_fn = ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (fio_str_info_s, fio_str_info_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L507"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_http_sse_subscribe_args = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L508"> channel: fio_str_info_s,</span>
<span class="line" id="L509"> on_message: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> ([*c]http_sse_s, fio_str_info_s, fio_str_info_s, ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L510"> on_unsubscribe: ?*<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>,</span>
<span class="line" id="L511"> udata: ?*<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L512"> match: fio_match_fn,</span>
<span class="line" id="L513">};</span>
<span class="line" id="L514"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse_subscribe</span>(sse: [*c]http_sse_s, args: struct_http_sse_subscribe_args) <span class="tok-type">usize</span>;</span>
<span class="line" id="L515"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse_unsubscribe</span>(sse: [*c]http_sse_s, subscription: <span class="tok-type">usize</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L516"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_http_sse_write_args = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L517"> id: fio_str_info_s,</span>
<span class="line" id="L518"> event: fio_str_info_s,</span>
<span class="line" id="L519"> data: fio_str_info_s,</span>
<span class="line" id="L520"> retry: <span class="tok-type">isize</span>,</span>
<span class="line" id="L521">};</span>
<span class="line" id="L522"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse_write</span>(sse: [*c]http_sse_s, struct_http_sse_write_args) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L523"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse2uuid</span>(sse: [*c]http_sse_s) <span class="tok-type">isize</span>;</span>
<span class="line" id="L524"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse_close</span>(sse: [*c]http_sse_s) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L525"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse_dup</span>(sse: [*c]http_sse_s) [*c]http_sse_s;</span>
<span class="line" id="L526"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_sse_free</span>(sse: [*c]http_sse_s) <span class="tok-type">void</span>;</span>
<span class="line" id="L527"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_parse_body</span>(h: [*c]http_s) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L528"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_parse_query</span>(h: [*c]http_s) <span class="tok-type">void</span>;</span>
<span class="line" id="L529"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_parse_cookies</span>(h: [*c]http_s, is_url_encoded: <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L530"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_add2hash</span>(dest: FIOBJ, name: [*c]<span class="tok-type">u8</span>, name_len: <span class="tok-type">usize</span>, value: [*c]<span class="tok-type">u8</span>, value_len: <span class="tok-type">usize</span>, encoded: <span class="tok-type">u8</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L531"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_add2hash2</span>(dest: FIOBJ, name: [*c]<span class="tok-type">u8</span>, name_len: <span class="tok-type">usize</span>, value: FIOBJ, encoded: <span class="tok-type">u8</span>) <span class="tok-type">c_int</span>;</span>
<span class="line" id="L532"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_status2str</span>(status: <span class="tok-type">usize</span>) fio_str_info_s;</span>
<span class="line" id="L533"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_mimetype_register</span>(file_ext: [*c]<span class="tok-type">u8</span>, file_ext_len: <span class="tok-type">usize</span>, mime_type_str: FIOBJ) <span class="tok-type">void</span>;</span>
<span class="line" id="L534"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_mimetype_find</span>(file_ext: [*c]<span class="tok-type">u8</span>, file_ext_len: <span class="tok-type">usize</span>) FIOBJ;</span>
<span class="line" id="L535"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_mimetype_find2</span>(url: FIOBJ) FIOBJ;</span>
<span class="line" id="L536"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_mimetype_clear</span>() <span class="tok-type">void</span>;</span>
<span class="line" id="L537"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_ACCEPT: FIOBJ;</span>
<span class="line" id="L538"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_CACHE_CONTROL: FIOBJ;</span>
<span class="line" id="L539"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_CONNECTION: FIOBJ;</span>
<span class="line" id="L540"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_CONTENT_ENCODING: FIOBJ;</span>
<span class="line" id="L541"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_CONTENT_LENGTH: FIOBJ;</span>
<span class="line" id="L542"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_CONTENT_RANGE: FIOBJ;</span>
<span class="line" id="L543"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_CONTENT_TYPE: FIOBJ;</span>
<span class="line" id="L544"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_COOKIE: FIOBJ;</span>
<span class="line" id="L545"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_DATE: FIOBJ;</span>
<span class="line" id="L546"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_ETAG: FIOBJ;</span>
<span class="line" id="L547"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_HOST: FIOBJ;</span>
<span class="line" id="L548"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_LAST_MODIFIED: FIOBJ;</span>
<span class="line" id="L549"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_ORIGIN: FIOBJ;</span>
<span class="line" id="L550"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_SET_COOKIE: FIOBJ;</span>
<span class="line" id="L551"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">var</span> HTTP_HEADER_UPGRADE: FIOBJ;</span>
<span class="line" id="L552"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_req2str</span>(h: [*c]http_s) FIOBJ;</span>
<span class="line" id="L553"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_write_log</span>(h: [*c]http_s) <span class="tok-type">void</span>;</span>
<span class="line" id="L554"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_gmtime</span>(timer: time_t, tmbuf: [*c]struct_tm) [*c]struct_tm;</span>
<span class="line" id="L555"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_date2rfc7231</span>(target: [*c]<span class="tok-type">u8</span>, tmbuf: [*c]struct_tm) <span class="tok-type">usize</span>;</span>
<span class="line" id="L556"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_date2rfc2109</span>(target: [*c]<span class="tok-type">u8</span>, tmbuf: [*c]struct_tm) <span class="tok-type">usize</span>;</span>
<span class="line" id="L557"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_date2rfc2822</span>(target: [*c]<span class="tok-type">u8</span>, tmbuf: [*c]struct_tm) <span class="tok-type">usize</span>;</span>
<span class="line" id="L558"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_date2str</span>(arg_target: [*c]<span class="tok-type">u8</span>, arg_tmbuf: [*c]struct_tm) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">usize</span> {</span>
<span class="line" id="L559"> <span class="tok-kw">const</span> target = arg_target;</span>
<span class="line" id="L560"> <span class="tok-kw">const</span> tmbuf = arg_tmbuf;</span>
<span class="line" id="L561"> <span class="tok-kw">return</span> http_date2rfc7231(target, tmbuf);</span>
<span class="line" id="L562">}</span>
<span class="line" id="L563"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_time2str</span>(target: [*c]<span class="tok-type">u8</span>, t: time_t) <span class="tok-type">usize</span>;</span>
<span class="line" id="L564"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_decode_url_unsafe</span>(dest: [*c]<span class="tok-type">u8</span>, url_data: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">isize</span>;</span>
<span class="line" id="L565"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_decode_url</span>(dest: [*c]<span class="tok-type">u8</span>, url_data: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, length: <span class="tok-type">usize</span>) <span class="tok-type">isize</span>;</span>
<span class="line" id="L566"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_decode_path_unsafe</span>(dest: [*c]<span class="tok-type">u8</span>, url_data: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">isize</span>;</span>
<span class="line" id="L567"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">http_decode_path</span>(dest: [*c]<span class="tok-type">u8</span>, url_data: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, length: <span class="tok-type">usize</span>) <span class="tok-type">isize</span>;</span>
<span class="line" id="L568"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> http_url_s = fio_url_s;</span>
<span class="line" id="L569"></span>
<span class="line" id="L570"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> struct_tm = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L571"> tm_sec: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L572"> tm_min: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L573"> tm_hour: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L574"> tm_mday: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L575"> tm_mon: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L576"> tm_year: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L577"> tm_wday: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L578"> tm_yday: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L579"> tm_isdst: <span class="tok-type">c_int</span>,</span>
<span class="line" id="L580"> tm_gmtoff: <span class="tok-type">c_long</span>,</span>
<span class="line" id="L581"> tm_zone: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L582">};</span>
<span class="line" id="L583"></span>
</code></pre></body>
</html>

229
docs/src/zap/http.zig.html Normal file
View file

@ -0,0 +1,229 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>http.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">/// HTTP Status codes according to `rfc7231`</span></span>
<span class="line" id="L2"><span class="tok-comment">/// https://tools.ietf.org/html/rfc7231#section-6</span></span>
<span class="line" id="L3"><span class="tok-comment">/// (taken from https://github.com/Luukdegram/apple_pie/blob/master/src/response.zig)</span></span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> StatusCode = <span class="tok-kw">enum</span>(<span class="tok-type">u16</span>) {</span>
<span class="line" id="L5"> <span class="tok-comment">// Informational 1xx</span>
</span>
<span class="line" id="L6"> @&quot;continue&quot; = <span class="tok-number">100</span>,</span>
<span class="line" id="L7"> <span class="tok-comment">// Successful 2xx</span>
</span>
<span class="line" id="L8"> switching_protocols = <span class="tok-number">101</span>,</span>
<span class="line" id="L9"> ok = <span class="tok-number">200</span>,</span>
<span class="line" id="L10"> created = <span class="tok-number">201</span>,</span>
<span class="line" id="L11"> accepted = <span class="tok-number">202</span>,</span>
<span class="line" id="L12"> non_authoritative_information = <span class="tok-number">203</span>,</span>
<span class="line" id="L13"> no_content = <span class="tok-number">204</span>,</span>
<span class="line" id="L14"> reset_content = <span class="tok-number">205</span>,</span>
<span class="line" id="L15"> <span class="tok-comment">// redirections 3xx</span>
</span>
<span class="line" id="L16"> partial_content = <span class="tok-number">206</span>,</span>
<span class="line" id="L17"> multiple_choices = <span class="tok-number">300</span>,</span>
<span class="line" id="L18"> moved_permanently = <span class="tok-number">301</span>,</span>
<span class="line" id="L19"> found = <span class="tok-number">302</span>,</span>
<span class="line" id="L20"> see_other = <span class="tok-number">303</span>,</span>
<span class="line" id="L21"> not_modified = <span class="tok-number">304</span>,</span>
<span class="line" id="L22"> use_proxy = <span class="tok-number">305</span>,</span>
<span class="line" id="L23"> temporary_redirect = <span class="tok-number">307</span>,</span>
<span class="line" id="L24"> <span class="tok-comment">// client errors 4xx</span>
</span>
<span class="line" id="L25"> bad_request = <span class="tok-number">400</span>,</span>
<span class="line" id="L26"> unauthorized = <span class="tok-number">401</span>,</span>
<span class="line" id="L27"> payment_required = <span class="tok-number">402</span>,</span>
<span class="line" id="L28"> forbidden = <span class="tok-number">403</span>,</span>
<span class="line" id="L29"> not_found = <span class="tok-number">404</span>,</span>
<span class="line" id="L30"> method_not_allowed = <span class="tok-number">405</span>,</span>
<span class="line" id="L31"> not_acceptable = <span class="tok-number">406</span>,</span>
<span class="line" id="L32"> proxy_authentication_required = <span class="tok-number">407</span>,</span>
<span class="line" id="L33"> request_timeout = <span class="tok-number">408</span>,</span>
<span class="line" id="L34"> conflict = <span class="tok-number">409</span>,</span>
<span class="line" id="L35"> gone = <span class="tok-number">410</span>,</span>
<span class="line" id="L36"> length_required = <span class="tok-number">411</span>,</span>
<span class="line" id="L37"> precondition_failed = <span class="tok-number">412</span>,</span>
<span class="line" id="L38"> request_entity_too_large = <span class="tok-number">413</span>,</span>
<span class="line" id="L39"> request_uri_too_long = <span class="tok-number">414</span>,</span>
<span class="line" id="L40"> unsupported_mediatype = <span class="tok-number">415</span>,</span>
<span class="line" id="L41"> requested_range_not_satisfiable = <span class="tok-number">416</span>,</span>
<span class="line" id="L42"> expectation_failed = <span class="tok-number">417</span>,</span>
<span class="line" id="L43"> <span class="tok-comment">/// teapot is an extension status code and not required for clients to support</span></span>
<span class="line" id="L44"> teapot = <span class="tok-number">418</span>,</span>
<span class="line" id="L45"> upgrade_required = <span class="tok-number">426</span>,</span>
<span class="line" id="L46"> <span class="tok-comment">/// extra status code according to `https://tools.ietf.org/html/rfc6585#section-5`</span></span>
<span class="line" id="L47"> request_header_fields_too_large = <span class="tok-number">431</span>,</span>
<span class="line" id="L48"> <span class="tok-comment">// server errors 5xx</span>
</span>
<span class="line" id="L49"> internal_server_error = <span class="tok-number">500</span>,</span>
<span class="line" id="L50"> not_implemented = <span class="tok-number">501</span>,</span>
<span class="line" id="L51"> bad_gateway = <span class="tok-number">502</span>,</span>
<span class="line" id="L52"> service_unavailable = <span class="tok-number">503</span>,</span>
<span class="line" id="L53"> gateway_timeout = <span class="tok-number">504</span>,</span>
<span class="line" id="L54"> http_version_not_supported = <span class="tok-number">505</span>,</span>
<span class="line" id="L55"> _,</span>
<span class="line" id="L56"></span>
<span class="line" id="L57"> <span class="tok-comment">/// Returns the string value of a `StatusCode`</span></span>
<span class="line" id="L58"> <span class="tok-comment">/// for example: .ResetContent returns &quot;Returns Content&quot;.</span></span>
<span class="line" id="L59"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">toString</span>(self: StatusCode) []<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L60"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L61"> .@&quot;continue&quot; =&gt; <span class="tok-str">&quot;Continue&quot;</span>,</span>
<span class="line" id="L62"> .switching_protocols =&gt; <span class="tok-str">&quot;Switching Protocols&quot;</span>,</span>
<span class="line" id="L63"> .ok =&gt; <span class="tok-str">&quot;Ok&quot;</span>,</span>
<span class="line" id="L64"> .created =&gt; <span class="tok-str">&quot;Created&quot;</span>,</span>
<span class="line" id="L65"> .accepted =&gt; <span class="tok-str">&quot;Accepted&quot;</span>,</span>
<span class="line" id="L66"> .non_authoritative_information =&gt; <span class="tok-str">&quot;Non Authoritative Information&quot;</span>,</span>
<span class="line" id="L67"> .no_content =&gt; <span class="tok-str">&quot;No Content&quot;</span>,</span>
<span class="line" id="L68"> .reset_content =&gt; <span class="tok-str">&quot;Reset Content&quot;</span>,</span>
<span class="line" id="L69"> .partial_content =&gt; <span class="tok-str">&quot;Partial Content&quot;</span>,</span>
<span class="line" id="L70"> .multiple_choices =&gt; <span class="tok-str">&quot;Multiple Choices&quot;</span>,</span>
<span class="line" id="L71"> .moved_permanently =&gt; <span class="tok-str">&quot;Moved Permanently&quot;</span>,</span>
<span class="line" id="L72"> .found =&gt; <span class="tok-str">&quot;Found&quot;</span>,</span>
<span class="line" id="L73"> .see_other =&gt; <span class="tok-str">&quot;See Other&quot;</span>,</span>
<span class="line" id="L74"> .not_modified =&gt; <span class="tok-str">&quot;Not Modified&quot;</span>,</span>
<span class="line" id="L75"> .use_proxy =&gt; <span class="tok-str">&quot;Use Proxy&quot;</span>,</span>
<span class="line" id="L76"> .temporary_redirect =&gt; <span class="tok-str">&quot;Temporary Redirect&quot;</span>,</span>
<span class="line" id="L77"> .bad_request =&gt; <span class="tok-str">&quot;Bad Request&quot;</span>,</span>
<span class="line" id="L78"> .unauthorized =&gt; <span class="tok-str">&quot;Unauthorized&quot;</span>,</span>
<span class="line" id="L79"> .payment_required =&gt; <span class="tok-str">&quot;Payment Required&quot;</span>,</span>
<span class="line" id="L80"> .forbidden =&gt; <span class="tok-str">&quot;Forbidden&quot;</span>,</span>
<span class="line" id="L81"> .not_found =&gt; <span class="tok-str">&quot;Not Found&quot;</span>,</span>
<span class="line" id="L82"> .method_not_allowed =&gt; <span class="tok-str">&quot;Method Not Allowed&quot;</span>,</span>
<span class="line" id="L83"> .not_acceptable =&gt; <span class="tok-str">&quot;Not Acceptable&quot;</span>,</span>
<span class="line" id="L84"> .proxy_authentication_required =&gt; <span class="tok-str">&quot;Proxy Authentication Required&quot;</span>,</span>
<span class="line" id="L85"> .request_timeout =&gt; <span class="tok-str">&quot;Request Timeout&quot;</span>,</span>
<span class="line" id="L86"> .conflict =&gt; <span class="tok-str">&quot;Conflict&quot;</span>,</span>
<span class="line" id="L87"> .gone =&gt; <span class="tok-str">&quot;Gone&quot;</span>,</span>
<span class="line" id="L88"> .length_required =&gt; <span class="tok-str">&quot;Length Required&quot;</span>,</span>
<span class="line" id="L89"> .precondition_failed =&gt; <span class="tok-str">&quot;Precondition Failed&quot;</span>,</span>
<span class="line" id="L90"> .request_entity_too_large =&gt; <span class="tok-str">&quot;Request Entity Too Large&quot;</span>,</span>
<span class="line" id="L91"> .request_uri_too_long =&gt; <span class="tok-str">&quot;Request-URI Too Long&quot;</span>,</span>
<span class="line" id="L92"> .unsupported_mediatype =&gt; <span class="tok-str">&quot;Unsupported Media Type&quot;</span>,</span>
<span class="line" id="L93"> .requested_range_not_satisfiable =&gt; <span class="tok-str">&quot;Requested Range Not Satisfiable&quot;</span>,</span>
<span class="line" id="L94"> .teapot =&gt; <span class="tok-str">&quot;I'm a Teapot&quot;</span>,</span>
<span class="line" id="L95"> .upgrade_required =&gt; <span class="tok-str">&quot;Upgrade Required&quot;</span>,</span>
<span class="line" id="L96"> .request_header_fields_too_large =&gt; <span class="tok-str">&quot;Request Header Fields Too Large&quot;</span>,</span>
<span class="line" id="L97"> .expectation_failed =&gt; <span class="tok-str">&quot;Expectation Failed&quot;</span>,</span>
<span class="line" id="L98"> .internal_server_error =&gt; <span class="tok-str">&quot;Internal Server Error&quot;</span>,</span>
<span class="line" id="L99"> .not_implemented =&gt; <span class="tok-str">&quot;Not Implemented&quot;</span>,</span>
<span class="line" id="L100"> .bad_gateway =&gt; <span class="tok-str">&quot;Bad Gateway&quot;</span>,</span>
<span class="line" id="L101"> .service_unavailable =&gt; <span class="tok-str">&quot;Service Unavailable&quot;</span>,</span>
<span class="line" id="L102"> .gateway_timeout =&gt; <span class="tok-str">&quot;Gateway Timeout&quot;</span>,</span>
<span class="line" id="L103"> .http_version_not_supported =&gt; <span class="tok-str">&quot;HTTP Version Not Supported&quot;</span>,</span>
<span class="line" id="L104"> _ =&gt; <span class="tok-str">&quot;&quot;</span>,</span>
<span class="line" id="L105"> };</span>
<span class="line" id="L106"> }</span>
<span class="line" id="L107">};</span>
<span class="line" id="L108"></span>
</code></pre></body>
</html>

View file

@ -0,0 +1,766 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>http_auth.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> zap = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zap.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-comment">/// Authentication Scheme enum: Basic or Bearer.</span></span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> AuthScheme = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L6"> Basic,</span>
<span class="line" id="L7"> Bearer,</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">str</span>(self: AuthScheme) []<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L10"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L11"> .Basic =&gt; <span class="tok-str">&quot;Basic &quot;</span>,</span>
<span class="line" id="L12"> .Bearer =&gt; <span class="tok-str">&quot;Bearer &quot;</span>,</span>
<span class="line" id="L13"> };</span>
<span class="line" id="L14"> }</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">headerFieldStrFio</span>(self: AuthScheme) []<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L17"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L18"> .Basic =&gt; <span class="tok-str">&quot;authentication&quot;</span>,</span>
<span class="line" id="L19"> .Bearer =&gt; <span class="tok-str">&quot;authorization&quot;</span>,</span>
<span class="line" id="L20"> };</span>
<span class="line" id="L21"> }</span>
<span class="line" id="L22"></span>
<span class="line" id="L23"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">headerFieldStrHeader</span>(self: AuthScheme) [:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L24"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L25"> .Basic =&gt; <span class="tok-str">&quot;Authentication&quot;</span>,</span>
<span class="line" id="L26"> .Bearer =&gt; <span class="tok-str">&quot;Authorization&quot;</span>,</span>
<span class="line" id="L27"> };</span>
<span class="line" id="L28"> }</span>
<span class="line" id="L29">};</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-comment">/// Used internally: check for presence of the requested auth header.</span></span>
<span class="line" id="L32"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">checkAuthHeader</span>(scheme: AuthScheme, auth_header: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L33"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (scheme) {</span>
<span class="line" id="L34"> .Basic =&gt; |b| std.mem.startsWith(<span class="tok-type">u8</span>, auth_header, b.str()) <span class="tok-kw">and</span> auth_header.len &gt; b.str().len,</span>
<span class="line" id="L35"> .Bearer =&gt; |b| std.mem.startsWith(<span class="tok-type">u8</span>, auth_header, b.str()) <span class="tok-kw">and</span> auth_header.len &gt; b.str().len,</span>
<span class="line" id="L36"> };</span>
<span class="line" id="L37">}</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-comment">/// Used internally: return the requested auth header.</span></span>
<span class="line" id="L40"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">extractAuthHeader</span>(scheme: AuthScheme, r: *<span class="tok-kw">const</span> zap.Request) ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L41"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (scheme) {</span>
<span class="line" id="L42"> .Basic =&gt; |b| r.getHeader(b.headerFieldStrFio()),</span>
<span class="line" id="L43"> .Bearer =&gt; |b| r.getHeader(b.headerFieldStrFio()),</span>
<span class="line" id="L44"> };</span>
<span class="line" id="L45">}</span>
<span class="line" id="L46"></span>
<span class="line" id="L47"><span class="tok-comment">/// Decoding Strategy for Basic Authentication</span></span>
<span class="line" id="L48"><span class="tok-kw">const</span> BasicAuthStrategy = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L49"> <span class="tok-comment">/// decode into user and pass, then check pass</span></span>
<span class="line" id="L50"> UserPass,</span>
<span class="line" id="L51"> <span class="tok-comment">/// just look up the encoded user:pass token</span></span>
<span class="line" id="L52"> Token68,</span>
<span class="line" id="L53">};</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-comment">/// Authentication result</span></span>
<span class="line" id="L56"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> AuthResult = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L57"> <span class="tok-comment">/// authentication / authorization was successful</span></span>
<span class="line" id="L58"> AuthOK,</span>
<span class="line" id="L59"> <span class="tok-comment">/// authentication / authorization failed</span></span>
<span class="line" id="L60"> AuthFailed,</span>
<span class="line" id="L61"> <span class="tok-comment">/// The authenticator handled the request that didn't pass authentication /</span></span>
<span class="line" id="L62"> <span class="tok-comment">/// authorization.</span></span>
<span class="line" id="L63"> <span class="tok-comment">/// This is used to implement authenticators that redirect to a login</span></span>
<span class="line" id="L64"> <span class="tok-comment">/// page. An Authenticating endpoint will not do the default, which is trying</span></span>
<span class="line" id="L65"> <span class="tok-comment">/// to call the `unauthorized` callback if one exists orelse ignore the request.</span></span>
<span class="line" id="L66"> Handled,</span>
<span class="line" id="L67">};</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"><span class="tok-comment">/// HTTP Basic Authentication RFC 7617.</span></span>
<span class="line" id="L70"><span class="tok-comment">/// &quot;Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==&quot;</span></span>
<span class="line" id="L71"><span class="tok-comment">/// user-pass strings: &quot;$username:$password&quot; -&gt; base64</span></span>
<span class="line" id="L72"><span class="tok-comment">///</span></span>
<span class="line" id="L73"><span class="tok-comment">/// Notes:</span></span>
<span class="line" id="L74"><span class="tok-comment">/// - we only look at the Authentication header</span></span>
<span class="line" id="L75"><span class="tok-comment">/// - we ignore the required realm parameter</span></span>
<span class="line" id="L76"><span class="tok-comment">/// - we ignore the optional charset parameter</span></span>
<span class="line" id="L77"><span class="tok-comment">///</span></span>
<span class="line" id="L78"><span class="tok-comment">/// Errors:</span></span>
<span class="line" id="L79"><span class="tok-comment">/// WWW-Authenticate: Basic realm=&quot;this&quot;</span></span>
<span class="line" id="L80"><span class="tok-comment">///</span></span>
<span class="line" id="L81"><span class="tok-comment">/// Lookup : any kind of map that implements get([]const u8) -&gt; []const u8</span></span>
<span class="line" id="L82"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Basic</span>(<span class="tok-kw">comptime</span> Lookup: <span class="tok-type">type</span>, <span class="tok-kw">comptime</span> kind: BasicAuthStrategy) <span class="tok-type">type</span> {</span>
<span class="line" id="L83"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L84"> allocator: std.mem.Allocator,</span>
<span class="line" id="L85"> realm: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L86"> lookup: *Lookup,</span>
<span class="line" id="L87"></span>
<span class="line" id="L88"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> <span class="tok-comment">/// Creates a BasicAuth. `lookup` must implement `.get([]const u8) -&gt; []const u8`</span></span>
<span class="line" id="L91"> <span class="tok-comment">/// different implementations can</span></span>
<span class="line" id="L92"> <span class="tok-comment">/// - either decode, lookup and compare passwords</span></span>
<span class="line" id="L93"> <span class="tok-comment">/// - or just check for existence of the base64-encoded user:pass combination</span></span>
<span class="line" id="L94"> <span class="tok-comment">/// if realm is provided (not null), a copy of it is taken -&gt; call deinit() to clean up</span></span>
<span class="line" id="L95"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(allocator: std.mem.Allocator, lookup: *Lookup, realm: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !Self {</span>
<span class="line" id="L96"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L97"> .allocator = allocator,</span>
<span class="line" id="L98"> .lookup = lookup,</span>
<span class="line" id="L99"> .realm = <span class="tok-kw">if</span> (realm) |the_realm| <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, the_realm) <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L100"> };</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"> <span class="tok-comment">/// Deinit the authenticator.</span></span>
<span class="line" id="L104"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L105"> <span class="tok-kw">if</span> (self.realm) |the_realm| {</span>
<span class="line" id="L106"> self.allocator.free(the_realm);</span>
<span class="line" id="L107"> }</span>
<span class="line" id="L108"> }</span>
<span class="line" id="L109"></span>
<span class="line" id="L110"> <span class="tok-comment">/// Use this to decode the auth_header into user:pass, lookup pass in lookup.</span></span>
<span class="line" id="L111"> <span class="tok-comment">/// Note: usually, you don't want to use this; you'd go for `authenticateRequest()`.</span></span>
<span class="line" id="L112"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticateUserPass</span>(self: *Self, auth_header: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) AuthResult {</span>
<span class="line" id="L113"> zap.debug(<span class="tok-str">&quot;AuthenticateUserPass\n&quot;</span>, .{});</span>
<span class="line" id="L114"> <span class="tok-kw">const</span> encoded = auth_header[AuthScheme.Basic.str().len..];</span>
<span class="line" id="L115"> <span class="tok-kw">const</span> decoder = std.base64.standard.Decoder;</span>
<span class="line" id="L116"> <span class="tok-kw">var</span> buffer: [<span class="tok-number">0x100</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L117"> <span class="tok-kw">if</span> (decoder.calcSizeForSlice(encoded)) |decoded_size| {</span>
<span class="line" id="L118"> <span class="tok-kw">if</span> (decoded_size &gt;= buffer.len) {</span>
<span class="line" id="L119"> zap.debug(</span>
<span class="line" id="L120"> <span class="tok-str">&quot;ERROR: UserPassAuth: decoded_size {d} &gt;= buffer.len {d}\n&quot;</span>,</span>
<span class="line" id="L121"> .{ decoded_size, buffer.len },</span>
<span class="line" id="L122"> );</span>
<span class="line" id="L123"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L124"> }</span>
<span class="line" id="L125"> <span class="tok-kw">const</span> decoded = buffer[<span class="tok-number">0</span>..decoded_size];</span>
<span class="line" id="L126"> decoder.decode(decoded, encoded) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L127"> zap.debug(</span>
<span class="line" id="L128"> <span class="tok-str">&quot;ERROR: UserPassAuth: unable to decode `{s}`: {any}\n&quot;</span>,</span>
<span class="line" id="L129"> .{ encoded, err },</span>
<span class="line" id="L130"> );</span>
<span class="line" id="L131"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L132"> };</span>
<span class="line" id="L133"> <span class="tok-comment">// we have decoded</span>
</span>
<span class="line" id="L134"> <span class="tok-comment">// we can split</span>
</span>
<span class="line" id="L135"> <span class="tok-kw">var</span> it = std.mem.split(<span class="tok-type">u8</span>, decoded, <span class="tok-str">&quot;:&quot;</span>);</span>
<span class="line" id="L136"> <span class="tok-kw">const</span> user = it.next();</span>
<span class="line" id="L137"> <span class="tok-kw">const</span> pass = it.next();</span>
<span class="line" id="L138"> <span class="tok-kw">if</span> (user == <span class="tok-null">null</span> <span class="tok-kw">or</span> pass == <span class="tok-null">null</span>) {</span>
<span class="line" id="L139"> zap.debug(</span>
<span class="line" id="L140"> <span class="tok-str">&quot;ERROR: UserPassAuth: user {any} or pass {any} is null\n&quot;</span>,</span>
<span class="line" id="L141"> .{ user, pass },</span>
<span class="line" id="L142"> );</span>
<span class="line" id="L143"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L144"> }</span>
<span class="line" id="L145"> <span class="tok-comment">// now, do the lookup</span>
</span>
<span class="line" id="L146"> <span class="tok-kw">const</span> actual_pw = self.lookup.*.get(user.?);</span>
<span class="line" id="L147"> <span class="tok-kw">if</span> (actual_pw) |pw| {</span>
<span class="line" id="L148"> <span class="tok-kw">const</span> ret = std.mem.eql(<span class="tok-type">u8</span>, pass.?, pw);</span>
<span class="line" id="L149"> zap.debug(</span>
<span class="line" id="L150"> <span class="tok-str">&quot;INFO: UserPassAuth for user `{s}`: `{s}` == pass `{s}` = {}\n&quot;</span>,</span>
<span class="line" id="L151"> .{ user.?, pw, pass.?, ret },</span>
<span class="line" id="L152"> );</span>
<span class="line" id="L153"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (ret) .AuthOK <span class="tok-kw">else</span> .AuthFailed;</span>
<span class="line" id="L154"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L155"> zap.debug(</span>
<span class="line" id="L156"> <span class="tok-str">&quot;ERROR: UserPassAuth: user `{s}` not found in map of size {d}!\n&quot;</span>,</span>
<span class="line" id="L157"> .{ user.?, self.lookup.*.count() },</span>
<span class="line" id="L158"> );</span>
<span class="line" id="L159"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L160"> }</span>
<span class="line" id="L161"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L162"> <span class="tok-comment">// can't calc slice size --&gt; fallthrough to return false</span>
</span>
<span class="line" id="L163"> zap.debug(</span>
<span class="line" id="L164"> <span class="tok-str">&quot;ERROR: UserPassAuth: cannot calc slize size for encoded `{s}`: {any} \n&quot;</span>,</span>
<span class="line" id="L165"> .{ encoded, err },</span>
<span class="line" id="L166"> );</span>
<span class="line" id="L167"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L168"> }</span>
<span class="line" id="L169"> zap.debug(<span class="tok-str">&quot;UNREACHABLE\n&quot;</span>, .{});</span>
<span class="line" id="L170"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L171"> }</span>
<span class="line" id="L172"></span>
<span class="line" id="L173"> <span class="tok-comment">/// Use this to just look up if the base64-encoded auth_header exists in lookup.</span></span>
<span class="line" id="L174"> <span class="tok-comment">/// Note: usually, you don't want to use this; you'd go for `authenticateRequest()`.</span></span>
<span class="line" id="L175"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticateToken68</span>(self: *Self, auth_header: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) AuthResult {</span>
<span class="line" id="L176"> <span class="tok-kw">const</span> token = auth_header[AuthScheme.Basic.str().len..];</span>
<span class="line" id="L177"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (self.lookup.*.contains(token)) .AuthOK <span class="tok-kw">else</span> .AuthFailed;</span>
<span class="line" id="L178"> }</span>
<span class="line" id="L179"></span>
<span class="line" id="L180"> <span class="tok-comment">/// dispatch based on kind (.UserPass / .Token689) and try to authenticate based on the header.</span></span>
<span class="line" id="L181"> <span class="tok-comment">/// Note: usually, you don't want to use this; you'd go for `authenticateRequest()`.</span></span>
<span class="line" id="L182"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticate</span>(self: *Self, auth_header: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) AuthResult {</span>
<span class="line" id="L183"> zap.debug(<span class="tok-str">&quot;AUTHENTICATE\n&quot;</span>, .{});</span>
<span class="line" id="L184"> <span class="tok-kw">switch</span> (kind) {</span>
<span class="line" id="L185"> .UserPass =&gt; <span class="tok-kw">return</span> self.authenticateUserPass(auth_header),</span>
<span class="line" id="L186"> .Token68 =&gt; <span class="tok-kw">return</span> self.authenticateToken68(auth_header),</span>
<span class="line" id="L187"> }</span>
<span class="line" id="L188"> }</span>
<span class="line" id="L189"></span>
<span class="line" id="L190"> <span class="tok-comment">/// The zap authentication request handler.</span></span>
<span class="line" id="L191"> <span class="tok-comment">///</span></span>
<span class="line" id="L192"> <span class="tok-comment">/// Tries to extract the authentication header and perform the authentication.</span></span>
<span class="line" id="L193"> <span class="tok-comment">/// If no authentication header is found, an authorization header is tried.</span></span>
<span class="line" id="L194"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticateRequest</span>(self: *Self, r: *<span class="tok-kw">const</span> zap.Request) AuthResult {</span>
<span class="line" id="L195"> zap.debug(<span class="tok-str">&quot;AUTHENTICATE REQUEST\n&quot;</span>, .{});</span>
<span class="line" id="L196"> <span class="tok-kw">if</span> (extractAuthHeader(.Basic, r)) |auth_header| {</span>
<span class="line" id="L197"> zap.debug(<span class="tok-str">&quot;Authentication Header found!\n&quot;</span>, .{});</span>
<span class="line" id="L198"> <span class="tok-kw">return</span> self.authenticate(auth_header);</span>
<span class="line" id="L199"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L200"> <span class="tok-comment">// try with .Authorization</span>
</span>
<span class="line" id="L201"> <span class="tok-kw">if</span> (extractAuthHeader(.Bearer, r)) |auth_header| {</span>
<span class="line" id="L202"> zap.debug(<span class="tok-str">&quot;Authorization Header found!\n&quot;</span>, .{});</span>
<span class="line" id="L203"> <span class="tok-kw">return</span> self.authenticate(auth_header);</span>
<span class="line" id="L204"> }</span>
<span class="line" id="L205"> }</span>
<span class="line" id="L206"> zap.debug(<span class="tok-str">&quot;NO fitting Auth Header found!\n&quot;</span>, .{});</span>
<span class="line" id="L207"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L208"> }</span>
<span class="line" id="L209"> };</span>
<span class="line" id="L210">}</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"><span class="tok-comment">/// HTTP bearer authentication for a single token</span></span>
<span class="line" id="L213"><span class="tok-comment">/// RFC 6750</span></span>
<span class="line" id="L214"><span class="tok-comment">/// &quot;Authentication: Bearer TOKEN&quot;</span></span>
<span class="line" id="L215"><span class="tok-comment">/// `Bearer` is case-sensitive</span></span>
<span class="line" id="L216"><span class="tok-comment">/// - we don't support form-encoded `access_token` body parameter</span></span>
<span class="line" id="L217"><span class="tok-comment">/// - we don't support URI query parameter `access_token`</span></span>
<span class="line" id="L218"><span class="tok-comment">///</span></span>
<span class="line" id="L219"><span class="tok-comment">/// Errors:</span></span>
<span class="line" id="L220"><span class="tok-comment">/// HTTP/1.1 401 Unauthorized</span></span>
<span class="line" id="L221"><span class="tok-comment">/// WWW-Authenticate: Bearer realm=&quot;example&quot;, error=&quot;invalid_token&quot;, error_description=&quot;...&quot;</span></span>
<span class="line" id="L222"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BearerSingle = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L223"> allocator: std.mem.Allocator,</span>
<span class="line" id="L224"> token: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L225"> realm: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L226"></span>
<span class="line" id="L227"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L228"></span>
<span class="line" id="L229"> <span class="tok-comment">/// Creates a Single-Token Bearer Authenticator.</span></span>
<span class="line" id="L230"> <span class="tok-comment">/// Takes a copy of the token.</span></span>
<span class="line" id="L231"> <span class="tok-comment">/// If realm is provided (not null), a copy is taken call deinit() to clean up.</span></span>
<span class="line" id="L232"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(allocator: std.mem.Allocator, token: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, realm: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !Self {</span>
<span class="line" id="L233"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L234"> .allocator = allocator,</span>
<span class="line" id="L235"> .token = <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, token),</span>
<span class="line" id="L236"> .realm = <span class="tok-kw">if</span> (realm) |the_realm| <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, the_realm) <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L237"> };</span>
<span class="line" id="L238"> }</span>
<span class="line" id="L239"></span>
<span class="line" id="L240"> <span class="tok-comment">/// Try to authenticate based on the header.</span></span>
<span class="line" id="L241"> <span class="tok-comment">/// Note: usually, you don't want to use this; you'd go for `authenticateRequest()`.</span></span>
<span class="line" id="L242"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticate</span>(self: *Self, auth_header: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) AuthResult {</span>
<span class="line" id="L243"> <span class="tok-kw">if</span> (checkAuthHeader(.Bearer, auth_header) == <span class="tok-null">false</span>) {</span>
<span class="line" id="L244"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L245"> }</span>
<span class="line" id="L246"> <span class="tok-kw">const</span> token = auth_header[AuthScheme.Bearer.str().len..];</span>
<span class="line" id="L247"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, token, self.token)) .AuthOK <span class="tok-kw">else</span> .AuthFailed;</span>
<span class="line" id="L248"> }</span>
<span class="line" id="L249"></span>
<span class="line" id="L250"> <span class="tok-comment">/// The zap authentication request handler.</span></span>
<span class="line" id="L251"> <span class="tok-comment">///</span></span>
<span class="line" id="L252"> <span class="tok-comment">/// Tries to extract the authentication header and perform the authentication.</span></span>
<span class="line" id="L253"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticateRequest</span>(self: *Self, r: *<span class="tok-kw">const</span> zap.Request) AuthResult {</span>
<span class="line" id="L254"> <span class="tok-kw">if</span> (extractAuthHeader(.Bearer, r)) |auth_header| {</span>
<span class="line" id="L255"> <span class="tok-kw">return</span> self.authenticate(auth_header);</span>
<span class="line" id="L256"> }</span>
<span class="line" id="L257"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L258"> }</span>
<span class="line" id="L259"></span>
<span class="line" id="L260"> <span class="tok-comment">/// Deinits the authenticator.</span></span>
<span class="line" id="L261"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L262"> <span class="tok-kw">if</span> (self.realm) |the_realm| {</span>
<span class="line" id="L263"> self.allocator.free(the_realm);</span>
<span class="line" id="L264"> }</span>
<span class="line" id="L265"> self.allocator.free(self.token);</span>
<span class="line" id="L266"> }</span>
<span class="line" id="L267">};</span>
<span class="line" id="L268"></span>
<span class="line" id="L269"><span class="tok-comment">/// HTTP bearer authentication for multiple tokens</span></span>
<span class="line" id="L270"><span class="tok-comment">/// RFC 6750</span></span>
<span class="line" id="L271"><span class="tok-comment">/// &quot;Authentication: Bearer TOKEN&quot;</span></span>
<span class="line" id="L272"><span class="tok-comment">/// `Bearer` is case-sensitive</span></span>
<span class="line" id="L273"><span class="tok-comment">/// - we don't support form-encoded `access_token` body parameter</span></span>
<span class="line" id="L274"><span class="tok-comment">/// - we don't support URI query parameter `access_token`</span></span>
<span class="line" id="L275"><span class="tok-comment">///</span></span>
<span class="line" id="L276"><span class="tok-comment">/// Errors:</span></span>
<span class="line" id="L277"><span class="tok-comment">/// HTTP/1.1 401 Unauthorized</span></span>
<span class="line" id="L278"><span class="tok-comment">/// WWW-Authenticate: Bearer realm=&quot;example&quot;, error=&quot;invalid_token&quot;, error_description=&quot;...&quot;</span></span>
<span class="line" id="L279"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">BearerMulti</span>(<span class="tok-kw">comptime</span> Lookup: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L280"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L281"> allocator: std.mem.Allocator,</span>
<span class="line" id="L282"> lookup: *Lookup,</span>
<span class="line" id="L283"> realm: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L284"></span>
<span class="line" id="L285"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L286"></span>
<span class="line" id="L287"> <span class="tok-comment">/// Creates a Multi Token Bearer Authenticator. `lookup` must implement</span></span>
<span class="line" id="L288"> <span class="tok-comment">/// `.get([]const u8) -&gt; []const u8` to look up tokens.</span></span>
<span class="line" id="L289"> <span class="tok-comment">/// If realm is provided (not null), a copy of it is taken -&gt; call deinit() to clean up.</span></span>
<span class="line" id="L290"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(allocator: std.mem.Allocator, lookup: *Lookup, realm: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !Self {</span>
<span class="line" id="L291"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L292"> .allocator = allocator,</span>
<span class="line" id="L293"> .lookup = lookup,</span>
<span class="line" id="L294"> .realm = <span class="tok-kw">if</span> (realm) |the_realm| <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, the_realm) <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L295"> };</span>
<span class="line" id="L296"> }</span>
<span class="line" id="L297"></span>
<span class="line" id="L298"> <span class="tok-comment">/// Deinit the authenticator. Only required if a realm was provided at</span></span>
<span class="line" id="L299"> <span class="tok-comment">/// init() time.</span></span>
<span class="line" id="L300"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L301"> <span class="tok-kw">if</span> (self.realm) |the_realm| {</span>
<span class="line" id="L302"> self.allocator.free(the_realm);</span>
<span class="line" id="L303"> }</span>
<span class="line" id="L304"> }</span>
<span class="line" id="L305"></span>
<span class="line" id="L306"> <span class="tok-comment">/// Try to authenticate based on the header.</span></span>
<span class="line" id="L307"> <span class="tok-comment">/// Note: usually, you don't want to use this; you'd go for `authenticateRequest()`.</span></span>
<span class="line" id="L308"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticate</span>(self: *Self, auth_header: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) AuthResult {</span>
<span class="line" id="L309"> <span class="tok-kw">if</span> (checkAuthHeader(.Bearer, auth_header) == <span class="tok-null">false</span>) {</span>
<span class="line" id="L310"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L311"> }</span>
<span class="line" id="L312"> <span class="tok-kw">const</span> token = auth_header[AuthScheme.Bearer.str().len..];</span>
<span class="line" id="L313"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (self.lookup.*.contains(token)) .AuthOK <span class="tok-kw">else</span> .AuthFailed;</span>
<span class="line" id="L314"> }</span>
<span class="line" id="L315"></span>
<span class="line" id="L316"> <span class="tok-comment">/// The zap authentication request handler.</span></span>
<span class="line" id="L317"> <span class="tok-comment">///</span></span>
<span class="line" id="L318"> <span class="tok-comment">/// Tries to extract the authentication header and perform the authentication.</span></span>
<span class="line" id="L319"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticateRequest</span>(self: *Self, r: *<span class="tok-kw">const</span> zap.Request) AuthResult {</span>
<span class="line" id="L320"> <span class="tok-kw">if</span> (extractAuthHeader(.Bearer, r)) |auth_header| {</span>
<span class="line" id="L321"> <span class="tok-kw">return</span> self.authenticate(auth_header);</span>
<span class="line" id="L322"> }</span>
<span class="line" id="L323"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L324"> }</span>
<span class="line" id="L325"> };</span>
<span class="line" id="L326">}</span>
<span class="line" id="L327"></span>
<span class="line" id="L328"><span class="tok-comment">/// Settings to initialize a UserPassSession authenticator.</span></span>
<span class="line" id="L329"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> UserPassSessionArgs = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L330"> <span class="tok-comment">/// username body parameter</span></span>
<span class="line" id="L331"> usernameParam: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L332"> <span class="tok-comment">/// password body parameter</span></span>
<span class="line" id="L333"> passwordParam: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L334"> <span class="tok-comment">/// redirect to this page if auth fails</span></span>
<span class="line" id="L335"> loginPage: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L336"> <span class="tok-comment">/// name of the auth cookie</span></span>
<span class="line" id="L337"> cookieName: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L338"> <span class="tok-comment">/// cookie max age in seconds; 0 -&gt; session cookie</span></span>
<span class="line" id="L339"> cookieMaxAge: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L340"> <span class="tok-comment">/// redirect status code, defaults to 302 found</span></span>
<span class="line" id="L341"> redirectCode: zap.StatusCode = .found,</span>
<span class="line" id="L342">};</span>
<span class="line" id="L343"></span>
<span class="line" id="L344"><span class="tok-comment">/// UserPassSession supports the following use case:</span></span>
<span class="line" id="L345"><span class="tok-comment">///</span></span>
<span class="line" id="L346"><span class="tok-comment">/// - checks every request: is it going to the login page? -&gt; let the request through.</span></span>
<span class="line" id="L347"><span class="tok-comment">/// - else:</span></span>
<span class="line" id="L348"><span class="tok-comment">/// - checks every request for a session token in a cookie</span></span>
<span class="line" id="L349"><span class="tok-comment">/// - if there is no token, it checks for correct username and password body params</span></span>
<span class="line" id="L350"><span class="tok-comment">/// - if username and password are present and correct, it will create a session token,</span></span>
<span class="line" id="L351"><span class="tok-comment">/// create a response cookie containing the token, and carry on with the request</span></span>
<span class="line" id="L352"><span class="tok-comment">/// - else it will redirect to the login page</span></span>
<span class="line" id="L353"><span class="tok-comment">/// - if the session token is present and correct: it will let the request through</span></span>
<span class="line" id="L354"><span class="tok-comment">/// - else: it will redirect to the login page</span></span>
<span class="line" id="L355"><span class="tok-comment">///</span></span>
<span class="line" id="L356"><span class="tok-comment">/// Please note the implications of this simple approach: IF YOU REUSE &quot;username&quot;</span></span>
<span class="line" id="L357"><span class="tok-comment">/// and &quot;password&quot; body params for anything else in your application, then the</span></span>
<span class="line" id="L358"><span class="tok-comment">/// mechanisms described above will still kick in. For that reason: please know what</span></span>
<span class="line" id="L359"><span class="tok-comment">/// you're doing.</span></span>
<span class="line" id="L360"><span class="tok-comment">///</span></span>
<span class="line" id="L361"><span class="tok-comment">/// See UserPassSessionArgs:</span></span>
<span class="line" id="L362"><span class="tok-comment">/// - username &amp; password param names can be defined by you</span></span>
<span class="line" id="L363"><span class="tok-comment">/// - session cookie name and max-age can be defined by you</span></span>
<span class="line" id="L364"><span class="tok-comment">/// - login page and redirect code (.302) can be defined by you</span></span>
<span class="line" id="L365"><span class="tok-comment">///</span></span>
<span class="line" id="L366"><span class="tok-comment">/// Comptime Parameters:</span></span>
<span class="line" id="L367"><span class="tok-comment">///</span></span>
<span class="line" id="L368"><span class="tok-comment">/// - `Lookup` must implement .get([]const u8) -&gt; []const u8 for user password retrieval</span></span>
<span class="line" id="L369"><span class="tok-comment">/// - `lockedPwLookups` : if true, accessing the provided Lookup instance will be protected</span></span>
<span class="line" id="L370"><span class="tok-comment">/// by a Mutex. You can access the mutex yourself via the `passwordLookupLock`.</span></span>
<span class="line" id="L371"><span class="tok-comment">///</span></span>
<span class="line" id="L372"><span class="tok-comment">/// Note: In order to be quick, you can set lockedTokenLookups to false.</span></span>
<span class="line" id="L373"><span class="tok-comment">/// -&gt; we generate it on init() and leave it static</span></span>
<span class="line" id="L374"><span class="tok-comment">/// -&gt; there is no way to 100% log out apart from re-starting the server</span></span>
<span class="line" id="L375"><span class="tok-comment">/// -&gt; because: we send a cookie to the browser that invalidates the session cookie</span></span>
<span class="line" id="L376"><span class="tok-comment">/// -&gt; another browser program with the page still open would still be able to use</span></span>
<span class="line" id="L377"><span class="tok-comment">/// -&gt; the session. Which is kindof OK, but not as cool as erasing the token</span></span>
<span class="line" id="L378"><span class="tok-comment">/// -&gt; on the server side which immediately block all other browsers as well.</span></span>
<span class="line" id="L379"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">UserPassSession</span>(<span class="tok-kw">comptime</span> Lookup: <span class="tok-type">type</span>, <span class="tok-kw">comptime</span> lockedPwLookups: <span class="tok-type">bool</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L380"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L381"> allocator: std.mem.Allocator,</span>
<span class="line" id="L382"> lookup: *Lookup,</span>
<span class="line" id="L383"> settings: UserPassSessionArgs,</span>
<span class="line" id="L384"></span>
<span class="line" id="L385"> <span class="tok-comment">// TODO: cookie store per user?</span>
</span>
<span class="line" id="L386"> sessionTokens: SessionTokenMap,</span>
<span class="line" id="L387"> passwordLookupLock: std.Thread.Mutex = .{},</span>
<span class="line" id="L388"> tokenLookupLock: std.Thread.Mutex = .{},</span>
<span class="line" id="L389"></span>
<span class="line" id="L390"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L391"> <span class="tok-kw">const</span> SessionTokenMap = std.StringHashMap(<span class="tok-type">void</span>);</span>
<span class="line" id="L392"> <span class="tok-kw">const</span> Hash = std.crypto.hash.sha2.Sha256;</span>
<span class="line" id="L393"></span>
<span class="line" id="L394"> <span class="tok-kw">const</span> Token = [Hash.digest_length * <span class="tok-number">2</span>]<span class="tok-type">u8</span>;</span>
<span class="line" id="L395"></span>
<span class="line" id="L396"> <span class="tok-comment">/// Construct this authenticator. See above and related types for more</span></span>
<span class="line" id="L397"> <span class="tok-comment">/// information.</span></span>
<span class="line" id="L398"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(</span>
<span class="line" id="L399"> allocator: std.mem.Allocator,</span>
<span class="line" id="L400"> lookup: *Lookup,</span>
<span class="line" id="L401"> args: UserPassSessionArgs,</span>
<span class="line" id="L402"> ) !Self {</span>
<span class="line" id="L403"> <span class="tok-kw">const</span> ret: Self = .{</span>
<span class="line" id="L404"> .allocator = allocator,</span>
<span class="line" id="L405"> .settings = .{</span>
<span class="line" id="L406"> .usernameParam = <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, args.usernameParam),</span>
<span class="line" id="L407"> .passwordParam = <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, args.passwordParam),</span>
<span class="line" id="L408"> .loginPage = <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, args.loginPage),</span>
<span class="line" id="L409"> .cookieName = <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, args.cookieName),</span>
<span class="line" id="L410"> .cookieMaxAge = args.cookieMaxAge,</span>
<span class="line" id="L411"> .redirectCode = args.redirectCode,</span>
<span class="line" id="L412"> },</span>
<span class="line" id="L413"> .lookup = lookup,</span>
<span class="line" id="L414"> .sessionTokens = SessionTokenMap.init(allocator),</span>
<span class="line" id="L415"> };</span>
<span class="line" id="L416"></span>
<span class="line" id="L417"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L418"> }</span>
<span class="line" id="L419"></span>
<span class="line" id="L420"> <span class="tok-comment">/// De-init this authenticator.</span></span>
<span class="line" id="L421"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L422"> self.allocator.free(self.settings.usernameParam);</span>
<span class="line" id="L423"> self.allocator.free(self.settings.passwordParam);</span>
<span class="line" id="L424"> self.allocator.free(self.settings.loginPage);</span>
<span class="line" id="L425"> self.allocator.free(self.settings.cookieName);</span>
<span class="line" id="L426"></span>
<span class="line" id="L427"> <span class="tok-comment">// clean up the session tokens: the key strings are duped</span>
</span>
<span class="line" id="L428"> <span class="tok-kw">var</span> key_it = self.sessionTokens.keyIterator();</span>
<span class="line" id="L429"> <span class="tok-kw">while</span> (key_it.next()) |key_ptr| {</span>
<span class="line" id="L430"> self.allocator.free(key_ptr.*);</span>
<span class="line" id="L431"> }</span>
<span class="line" id="L432"> self.sessionTokens.deinit();</span>
<span class="line" id="L433"> }</span>
<span class="line" id="L434"></span>
<span class="line" id="L435"> <span class="tok-comment">/// Check for session token cookie, remove the token from the valid tokens</span></span>
<span class="line" id="L436"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">logout</span>(self: *Self, r: *<span class="tok-kw">const</span> zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L437"> <span class="tok-comment">// we erase the list of valid tokens server-side (later) and set the</span>
</span>
<span class="line" id="L438"> <span class="tok-comment">// cookie to &quot;invalid&quot; on the client side.</span>
</span>
<span class="line" id="L439"> <span class="tok-kw">if</span> (r.setCookie(.{</span>
<span class="line" id="L440"> .name = self.settings.cookieName,</span>
<span class="line" id="L441"> .value = <span class="tok-str">&quot;invalid&quot;</span>,</span>
<span class="line" id="L442"> .max_age_s = -<span class="tok-number">1</span>,</span>
<span class="line" id="L443"> })) {</span>
<span class="line" id="L444"> zap.debug(<span class="tok-str">&quot;logout ok\n&quot;</span>, .{});</span>
<span class="line" id="L445"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L446"> zap.debug(<span class="tok-str">&quot;logout cookie setting failed: {any}\n&quot;</span>, .{err});</span>
<span class="line" id="L447"> }</span>
<span class="line" id="L448"></span>
<span class="line" id="L449"> r.parseCookies(<span class="tok-null">false</span>);</span>
<span class="line" id="L450"></span>
<span class="line" id="L451"> <span class="tok-comment">// check for session cookie</span>
</span>
<span class="line" id="L452"> <span class="tok-kw">if</span> (r.getCookieStr(self.allocator, self.settings.cookieName, <span class="tok-null">false</span>)) |maybe_cookie| {</span>
<span class="line" id="L453"> <span class="tok-kw">if</span> (maybe_cookie) |cookie| {</span>
<span class="line" id="L454"> <span class="tok-kw">defer</span> cookie.deinit();</span>
<span class="line" id="L455"> self.tokenLookupLock.lock();</span>
<span class="line" id="L456"> <span class="tok-kw">defer</span> self.tokenLookupLock.unlock();</span>
<span class="line" id="L457"> <span class="tok-kw">if</span> (self.sessionTokens.getKeyPtr(cookie.str)) |keyPtr| {</span>
<span class="line" id="L458"> <span class="tok-kw">const</span> keySlice = keyPtr.*;</span>
<span class="line" id="L459"> <span class="tok-comment">// if cookie is a valid session, remove it!</span>
</span>
<span class="line" id="L460"> _ = self.sessionTokens.remove(cookie.str);</span>
<span class="line" id="L461"> <span class="tok-comment">// only now can we let go of the cookie str slice that</span>
</span>
<span class="line" id="L462"> <span class="tok-comment">// was used as the key</span>
</span>
<span class="line" id="L463"> self.allocator.free(keySlice);</span>
<span class="line" id="L464"> }</span>
<span class="line" id="L465"> }</span>
<span class="line" id="L466"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L467"> zap.debug(<span class="tok-str">&quot;unreachable: UserPassSession.logout: {any}&quot;</span>, .{err});</span>
<span class="line" id="L468"> }</span>
<span class="line" id="L469"> }</span>
<span class="line" id="L470"></span>
<span class="line" id="L471"> <span class="tok-kw">fn</span> <span class="tok-fn">_internal_authenticateRequest</span>(self: *Self, r: *<span class="tok-kw">const</span> zap.Request) AuthResult {</span>
<span class="line" id="L472"> <span class="tok-comment">// if we're requesting the login page, let the request through</span>
</span>
<span class="line" id="L473"> <span class="tok-kw">if</span> (r.path) |p| {</span>
<span class="line" id="L474"> <span class="tok-kw">if</span> (std.mem.startsWith(<span class="tok-type">u8</span>, p, self.settings.loginPage)) {</span>
<span class="line" id="L475"> <span class="tok-kw">return</span> .AuthOK;</span>
<span class="line" id="L476"> }</span>
<span class="line" id="L477"> }</span>
<span class="line" id="L478"></span>
<span class="line" id="L479"> <span class="tok-comment">// parse body</span>
</span>
<span class="line" id="L480"> r.parseBody() <span class="tok-kw">catch</span> {</span>
<span class="line" id="L481"> <span class="tok-comment">// zap.debug(&quot;warning: parseBody() failed in UserPassSession: {any}&quot;, .{err});</span>
</span>
<span class="line" id="L482"> <span class="tok-comment">// this is not an error in case of e.g. gets with querystrings</span>
</span>
<span class="line" id="L483"> };</span>
<span class="line" id="L484"></span>
<span class="line" id="L485"> r.parseCookies(<span class="tok-null">false</span>);</span>
<span class="line" id="L486"></span>
<span class="line" id="L487"> <span class="tok-comment">// check for session cookie</span>
</span>
<span class="line" id="L488"> <span class="tok-kw">if</span> (r.getCookieStr(self.allocator, self.settings.cookieName, <span class="tok-null">false</span>)) |maybe_cookie| {</span>
<span class="line" id="L489"> <span class="tok-kw">if</span> (maybe_cookie) |cookie| {</span>
<span class="line" id="L490"> <span class="tok-kw">defer</span> cookie.deinit();</span>
<span class="line" id="L491"> <span class="tok-comment">// locked or unlocked token lookup</span>
</span>
<span class="line" id="L492"> self.tokenLookupLock.lock();</span>
<span class="line" id="L493"> <span class="tok-kw">defer</span> self.tokenLookupLock.unlock();</span>
<span class="line" id="L494"> <span class="tok-kw">if</span> (self.sessionTokens.contains(cookie.str)) {</span>
<span class="line" id="L495"> <span class="tok-comment">// cookie is a valid session!</span>
</span>
<span class="line" id="L496"> zap.debug(<span class="tok-str">&quot;Auth: COOKIE IS OK!!!!: {s}\n&quot;</span>, .{cookie.str});</span>
<span class="line" id="L497"> <span class="tok-kw">return</span> .AuthOK;</span>
<span class="line" id="L498"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L499"> zap.debug(<span class="tok-str">&quot;Auth: COOKIE IS BAD!!!!: {s}\n&quot;</span>, .{cookie.str});</span>
<span class="line" id="L500"> <span class="tok-comment">// this is not necessarily a bad thing. it could be a</span>
</span>
<span class="line" id="L501"> <span class="tok-comment">// stale cookie from a previous session. So let's check</span>
</span>
<span class="line" id="L502"> <span class="tok-comment">// if username and password are being sent and correct.</span>
</span>
<span class="line" id="L503"> }</span>
<span class="line" id="L504"> }</span>
<span class="line" id="L505"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L506"> zap.debug(<span class="tok-str">&quot;unreachable: could not check for cookie in UserPassSession: {any}&quot;</span>, .{err});</span>
<span class="line" id="L507"> }</span>
<span class="line" id="L508"></span>
<span class="line" id="L509"> <span class="tok-comment">// get params of username and password</span>
</span>
<span class="line" id="L510"> <span class="tok-kw">if</span> (r.getParamStr(self.allocator, self.settings.usernameParam, <span class="tok-null">false</span>)) |maybe_username| {</span>
<span class="line" id="L511"> <span class="tok-kw">if</span> (maybe_username) |*username| {</span>
<span class="line" id="L512"> <span class="tok-kw">defer</span> username.deinit();</span>
<span class="line" id="L513"> <span class="tok-kw">if</span> (r.getParamStr(self.allocator, self.settings.passwordParam, <span class="tok-null">false</span>)) |maybe_pw| {</span>
<span class="line" id="L514"> <span class="tok-kw">if</span> (maybe_pw) |*pw| {</span>
<span class="line" id="L515"> <span class="tok-kw">defer</span> pw.deinit();</span>
<span class="line" id="L516"></span>
<span class="line" id="L517"> <span class="tok-comment">// now check</span>
</span>
<span class="line" id="L518"> <span class="tok-kw">const</span> correct_pw_optional = brk: {</span>
<span class="line" id="L519"> <span class="tok-kw">if</span> (lockedPwLookups) {</span>
<span class="line" id="L520"> self.passwordLookupLock.lock();</span>
<span class="line" id="L521"> <span class="tok-kw">defer</span> self.passwordLookupLock.unlock();</span>
<span class="line" id="L522"> <span class="tok-kw">break</span> :brk self.lookup.*.get(username.str);</span>
<span class="line" id="L523"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L524"> <span class="tok-kw">break</span> :brk self.lookup.*.get(username.str);</span>
<span class="line" id="L525"> }</span>
<span class="line" id="L526"> };</span>
<span class="line" id="L527"> <span class="tok-kw">if</span> (correct_pw_optional) |correct_pw| {</span>
<span class="line" id="L528"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, pw.str, correct_pw)) {</span>
<span class="line" id="L529"> <span class="tok-comment">// create session token</span>
</span>
<span class="line" id="L530"> <span class="tok-kw">if</span> (self.createAndStoreSessionToken(username.str, pw.str)) |token| {</span>
<span class="line" id="L531"> <span class="tok-kw">defer</span> self.allocator.free(token);</span>
<span class="line" id="L532"> <span class="tok-comment">// now set the cookie header</span>
</span>
<span class="line" id="L533"> <span class="tok-kw">if</span> (r.setCookie(.{</span>
<span class="line" id="L534"> .name = self.settings.cookieName,</span>
<span class="line" id="L535"> .value = token,</span>
<span class="line" id="L536"> .max_age_s = self.settings.cookieMaxAge,</span>
<span class="line" id="L537"> })) {</span>
<span class="line" id="L538"> <span class="tok-kw">return</span> .AuthOK;</span>
<span class="line" id="L539"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L540"> zap.debug(<span class="tok-str">&quot;could not set session token: {any}&quot;</span>, .{err});</span>
<span class="line" id="L541"> }</span>
<span class="line" id="L542"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L543"> zap.debug(<span class="tok-str">&quot;could not create session token: {any}&quot;</span>, .{err});</span>
<span class="line" id="L544"> }</span>
<span class="line" id="L545"> <span class="tok-comment">// errors with token don't mean the auth itself wasn't OK</span>
</span>
<span class="line" id="L546"> <span class="tok-kw">return</span> .AuthOK;</span>
<span class="line" id="L547"> }</span>
<span class="line" id="L548"> }</span>
<span class="line" id="L549"> }</span>
<span class="line" id="L550"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L551"> zap.debug(<span class="tok-str">&quot;getParamSt() for password failed in UserPassSession: {any}&quot;</span>, .{err});</span>
<span class="line" id="L552"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L553"> }</span>
<span class="line" id="L554"> }</span>
<span class="line" id="L555"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L556"> zap.debug(<span class="tok-str">&quot;getParamSt() for user failed in UserPassSession: {any}&quot;</span>, .{err});</span>
<span class="line" id="L557"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L558"> }</span>
<span class="line" id="L559"> <span class="tok-kw">return</span> .AuthFailed;</span>
<span class="line" id="L560"> }</span>
<span class="line" id="L561"></span>
<span class="line" id="L562"> <span class="tok-comment">/// The zap authentication request handler.</span></span>
<span class="line" id="L563"> <span class="tok-comment">///</span></span>
<span class="line" id="L564"> <span class="tok-comment">/// See above for how it works.</span></span>
<span class="line" id="L565"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">authenticateRequest</span>(self: *Self, r: *<span class="tok-kw">const</span> zap.Request) AuthResult {</span>
<span class="line" id="L566"> <span class="tok-kw">switch</span> (self._internal_authenticateRequest(r)) {</span>
<span class="line" id="L567"> .AuthOK =&gt; {</span>
<span class="line" id="L568"> <span class="tok-comment">// username and pass are ok -&gt; created token, set header, caller can continue</span>
</span>
<span class="line" id="L569"> <span class="tok-kw">return</span> .AuthOK;</span>
<span class="line" id="L570"> },</span>
<span class="line" id="L571"> <span class="tok-comment">// this does not happen, just for completeness</span>
</span>
<span class="line" id="L572"> .Handled =&gt; <span class="tok-kw">return</span> .Handled,</span>
<span class="line" id="L573"> <span class="tok-comment">// auth failed -&gt; redirect</span>
</span>
<span class="line" id="L574"> .AuthFailed =&gt; {</span>
<span class="line" id="L575"> <span class="tok-comment">// we need to redirect and return .Handled</span>
</span>
<span class="line" id="L576"> self.redirect(r) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L577"> <span class="tok-comment">// we just give up</span>
</span>
<span class="line" id="L578"> zap.debug(<span class="tok-str">&quot;redirect() failed in UserPassSession: {any}&quot;</span>, .{err});</span>
<span class="line" id="L579"> };</span>
<span class="line" id="L580"> <span class="tok-kw">return</span> .Handled;</span>
<span class="line" id="L581"> },</span>
<span class="line" id="L582"> }</span>
<span class="line" id="L583"> }</span>
<span class="line" id="L584"></span>
<span class="line" id="L585"> <span class="tok-kw">fn</span> <span class="tok-fn">redirect</span>(self: *Self, r: *<span class="tok-kw">const</span> zap.Request) !<span class="tok-type">void</span> {</span>
<span class="line" id="L586"> <span class="tok-kw">try</span> r.redirectTo(self.settings.loginPage, self.settings.redirectCode);</span>
<span class="line" id="L587"> }</span>
<span class="line" id="L588"></span>
<span class="line" id="L589"> <span class="tok-kw">fn</span> <span class="tok-fn">createSessionToken</span>(self: *Self, username: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, password: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) ![]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L590"> <span class="tok-kw">var</span> hasher = Hash.init(.{});</span>
<span class="line" id="L591"> hasher.update(username);</span>
<span class="line" id="L592"> hasher.update(password);</span>
<span class="line" id="L593"> <span class="tok-kw">var</span> buf: [<span class="tok-number">16</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L594"> <span class="tok-kw">const</span> time_nano = std.time.nanoTimestamp();</span>
<span class="line" id="L595"> <span class="tok-kw">const</span> timestampHex = <span class="tok-kw">try</span> std.fmt.bufPrint(&amp;buf, <span class="tok-str">&quot;{0x}&quot;</span>, .{time_nano});</span>
<span class="line" id="L596"> hasher.update(timestampHex);</span>
<span class="line" id="L597"></span>
<span class="line" id="L598"> <span class="tok-kw">var</span> digest: [Hash.digest_length]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L599"> hasher.final(&amp;digest);</span>
<span class="line" id="L600"> <span class="tok-kw">const</span> token: Token = std.fmt.bytesToHex(digest, .lower);</span>
<span class="line" id="L601"> <span class="tok-kw">const</span> token_str = <span class="tok-kw">try</span> self.allocator.dupe(<span class="tok-type">u8</span>, token[<span class="tok-number">0</span>..token.len]);</span>
<span class="line" id="L602"> <span class="tok-kw">return</span> token_str;</span>
<span class="line" id="L603"> }</span>
<span class="line" id="L604"></span>
<span class="line" id="L605"> <span class="tok-kw">fn</span> <span class="tok-fn">createAndStoreSessionToken</span>(self: *Self, username: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, password: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) ![]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L606"> <span class="tok-kw">const</span> token = <span class="tok-kw">try</span> self.createSessionToken(username, password);</span>
<span class="line" id="L607"> self.tokenLookupLock.lock();</span>
<span class="line" id="L608"> <span class="tok-kw">defer</span> self.tokenLookupLock.unlock();</span>
<span class="line" id="L609"></span>
<span class="line" id="L610"> <span class="tok-kw">if</span> (!self.sessionTokens.contains(token)) {</span>
<span class="line" id="L611"> <span class="tok-kw">try</span> self.sessionTokens.put(<span class="tok-kw">try</span> self.allocator.dupe(<span class="tok-type">u8</span>, token), {});</span>
<span class="line" id="L612"> }</span>
<span class="line" id="L613"> <span class="tok-kw">return</span> token;</span>
<span class="line" id="L614"> }</span>
<span class="line" id="L615"> };</span>
<span class="line" id="L616">}</span>
<span class="line" id="L617"></span>
</code></pre></body>
</html>

172
docs/src/zap/log.zig.html Normal file
View file

@ -0,0 +1,172 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>log.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-comment">// TODO: rework logging in zap</span>
</span>
<span class="line" id="L4"></span>
<span class="line" id="L5">debugOn: <span class="tok-type">bool</span>,</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-comment">/// Access to facil.io's logging facilities</span></span>
<span class="line" id="L8"><span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L9"></span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(<span class="tok-kw">comptime</span> debug: <span class="tok-type">bool</span>) Self {</span>
<span class="line" id="L11"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L12"> .debugOn = debug,</span>
<span class="line" id="L13"> };</span>
<span class="line" id="L14">}</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">log</span>(self: *<span class="tok-kw">const</span> Self, <span class="tok-kw">comptime</span> fmt: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, args: <span class="tok-kw">anytype</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L17"> <span class="tok-kw">if</span> (self.debugOn) {</span>
<span class="line" id="L18"> std.debug.print(<span class="tok-str">&quot;[zap] - &quot;</span> ++ fmt, args);</span>
<span class="line" id="L19"> }</span>
<span class="line" id="L20">}</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> fio_log_level_none: <span class="tok-type">c_int</span>;</span>
<span class="line" id="L23"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> fio_log_level_fatal: <span class="tok-type">c_int</span>;</span>
<span class="line" id="L24"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> fio_log_level_error: <span class="tok-type">c_int</span>;</span>
<span class="line" id="L25"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> fio_log_level_warning: <span class="tok-type">c_int</span>;</span>
<span class="line" id="L26"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> fio_log_level_info: <span class="tok-type">c_int</span>;</span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">const</span> fio_log_level_debug: <span class="tok-type">c_int</span>;</span>
<span class="line" id="L28"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_set_log_level</span>(level: <span class="tok-type">c_int</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L29"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_get_log_level</span>() <span class="tok-type">c_int</span>;</span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_log_print</span>(level: <span class="tok-type">c_int</span>, msg: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_log_info</span>(msg: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L32"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_log_warning</span>(msg: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L33"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_log_error</span>(msg: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L34"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_log_fatal</span>(msg: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio_log_debug</span>(msg: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"><span class="tok-comment">// pub fn getDebugLogger(comptime debug: bool) type {</span>
</span>
<span class="line" id="L38"><span class="tok-comment">// return struct {</span>
</span>
<span class="line" id="L39"><span class="tok-comment">// pub fn log(comptime fmt: []const u8, args: anytype) void {</span>
</span>
<span class="line" id="L40"><span class="tok-comment">// if (debug) {</span>
</span>
<span class="line" id="L41"><span class="tok-comment">// std.debug.print(&quot;[zap] - &quot; ++ fmt, args);</span>
</span>
<span class="line" id="L42"><span class="tok-comment">// }</span>
</span>
<span class="line" id="L43"><span class="tok-comment">// }</span>
</span>
<span class="line" id="L44"><span class="tok-comment">// };</span>
</span>
<span class="line" id="L45"><span class="tok-comment">// }</span>
</span>
<span class="line" id="L46"></span>
</code></pre></body>
</html>

View file

@ -0,0 +1,307 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>middleware.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> zap = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zap.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-comment">/// Your middleware components need to contain a handler.</span></span>
<span class="line" id="L5"><span class="tok-comment">///</span></span>
<span class="line" id="L6"><span class="tok-comment">/// A Handler is one element in the chain of request handlers that will be tried</span></span>
<span class="line" id="L7"><span class="tok-comment">/// by the listener when a request arrives. Handlers indicate to the previous</span></span>
<span class="line" id="L8"><span class="tok-comment">/// handler whether they processed a request by returning `true` from their</span></span>
<span class="line" id="L9"><span class="tok-comment">/// `on_request` function, in which case a typical request handler would stop</span></span>
<span class="line" id="L10"><span class="tok-comment">/// trying to pass the request on to the next handler in the chain. See</span></span>
<span class="line" id="L11"><span class="tok-comment">/// the `handle_other` function in this struct.</span></span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Handler</span>(<span class="tok-kw">comptime</span> ContextType: <span class="tok-kw">anytype</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L13"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L14"> other_handler: ?*Self = <span class="tok-null">null</span>,</span>
<span class="line" id="L15"> on_request: ?RequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"> <span class="tok-comment">// will be set</span>
</span>
<span class="line" id="L18"> allocator: ?std.mem.Allocator = <span class="tok-null">null</span>,</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> RequestFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (*Self, zap.Request, *ContextType) <span class="tok-type">bool</span>;</span>
<span class="line" id="L21"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L22"></span>
<span class="line" id="L23"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(on_request: RequestFn, other: ?*Self) Self {</span>
<span class="line" id="L24"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L25"> .other_handler = other,</span>
<span class="line" id="L26"> .on_request = on_request,</span>
<span class="line" id="L27"> };</span>
<span class="line" id="L28"> }</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"> <span class="tok-comment">// example for handling a request request</span>
</span>
<span class="line" id="L31"> <span class="tok-comment">// which you can use in your components, e.g.:</span>
</span>
<span class="line" id="L32"> <span class="tok-comment">// return self.handler.handleOther(r, context);</span>
</span>
<span class="line" id="L33"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">handleOther</span>(self: *Self, r: zap.Request, context: *ContextType) <span class="tok-type">bool</span> {</span>
<span class="line" id="L34"> <span class="tok-comment">// in structs embedding a handler, we'd @fieldParentPtr the first</span>
</span>
<span class="line" id="L35"> <span class="tok-comment">// param to get to the real self</span>
</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"> <span class="tok-comment">// First, do our pre-other stuff</span>
</span>
<span class="line" id="L38"> <span class="tok-comment">// ..</span>
</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"> <span class="tok-comment">// then call the wrapped thing</span>
</span>
<span class="line" id="L41"> <span class="tok-kw">var</span> other_handler_finished = <span class="tok-null">false</span>;</span>
<span class="line" id="L42"> <span class="tok-kw">if</span> (self.other_handler) |other_handler| {</span>
<span class="line" id="L43"> <span class="tok-kw">if</span> (other_handler.on_request) |on_request| {</span>
<span class="line" id="L44"> other_handler_finished = on_request(other_handler, r, context);</span>
<span class="line" id="L45"> }</span>
<span class="line" id="L46"> }</span>
<span class="line" id="L47"></span>
<span class="line" id="L48"> <span class="tok-comment">// now do our post stuff</span>
</span>
<span class="line" id="L49"> <span class="tok-kw">return</span> other_handler_finished;</span>
<span class="line" id="L50"> }</span>
<span class="line" id="L51"> };</span>
<span class="line" id="L52">}</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"><span class="tok-comment">/// A convenience handler for artibrary zap.Endpoint</span></span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">EndpointHandler</span>(<span class="tok-kw">comptime</span> HandlerType: <span class="tok-kw">anytype</span>, <span class="tok-kw">comptime</span> ContextType: <span class="tok-kw">anytype</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L56"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L57"> handler: HandlerType,</span>
<span class="line" id="L58"> endpoint: *zap.Endpoint,</span>
<span class="line" id="L59"> breakOnFinish: <span class="tok-type">bool</span>,</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L62"></span>
<span class="line" id="L63"> <span class="tok-comment">/// Create an endpointhandler from an endpoint and pass in the next (other) handler in the chain.</span></span>
<span class="line" id="L64"> <span class="tok-comment">/// If `breakOnFinish` is `true`, the handler will stop handing requests down the chain if</span></span>
<span class="line" id="L65"> <span class="tok-comment">/// the endpoint processed the request.</span></span>
<span class="line" id="L66"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(endpoint: *zap.Endpoint, other: ?*HandlerType, breakOnFinish: <span class="tok-type">bool</span>) Self {</span>
<span class="line" id="L67"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L68"> .handler = HandlerType.init(onRequest, other),</span>
<span class="line" id="L69"> .endpoint = endpoint,</span>
<span class="line" id="L70"> .breakOnFinish = breakOnFinish,</span>
<span class="line" id="L71"> };</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"> <span class="tok-comment">/// Provides the handler as a common interface to chain stuff</span></span>
<span class="line" id="L75"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getHandler</span>(self: *Self) *HandlerType {</span>
<span class="line" id="L76"> <span class="tok-kw">return</span> &amp;self.handler;</span>
<span class="line" id="L77"> }</span>
<span class="line" id="L78"></span>
<span class="line" id="L79"> <span class="tok-comment">/// The Handler's request handling function. Gets called from the listener</span></span>
<span class="line" id="L80"> <span class="tok-comment">/// with the request and a context instance. Calls the endpoint.</span></span>
<span class="line" id="L81"> <span class="tok-comment">///</span></span>
<span class="line" id="L82"> <span class="tok-comment">/// If `breakOnFinish` is `true`, the handler will stop handing requests down the chain if</span></span>
<span class="line" id="L83"> <span class="tok-comment">/// the endpoint processed the request.</span></span>
<span class="line" id="L84"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">onRequest</span>(handler: *HandlerType, r: zap.Request, context: *ContextType) <span class="tok-type">bool</span> {</span>
<span class="line" id="L85"> <span class="tok-kw">var</span> self = <span class="tok-builtin">@fieldParentPtr</span>(Self, <span class="tok-str">&quot;handler&quot;</span>, handler);</span>
<span class="line" id="L86"> r.setUserContext(context);</span>
<span class="line" id="L87"> self.endpoint.onRequest(r);</span>
<span class="line" id="L88"></span>
<span class="line" id="L89"> <span class="tok-comment">// if the request was handled by the endpoint, we may break the chain here</span>
</span>
<span class="line" id="L90"> <span class="tok-kw">if</span> (r.isFinished() <span class="tok-kw">and</span> self.breakOnFinish) {</span>
<span class="line" id="L91"> <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L92"> }</span>
<span class="line" id="L93"> <span class="tok-kw">return</span> self.handler.handleOther(r, context);</span>
<span class="line" id="L94"> }</span>
<span class="line" id="L95"> };</span>
<span class="line" id="L96">}</span>
<span class="line" id="L97"></span>
<span class="line" id="L98"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Error = <span class="tok-kw">error</span>{</span>
<span class="line" id="L99"> <span class="tok-comment">/// The listener could not be created because the settings provided to its</span></span>
<span class="line" id="L100"> <span class="tok-comment">/// init() function contained an `on_request` callback that was not null.</span></span>
<span class="line" id="L101"> InitOnRequestIsNotNull,</span>
<span class="line" id="L102">};</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> RequestAllocatorFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> () std.mem.Allocator;</span>
<span class="line" id="L105"></span>
<span class="line" id="L106"><span class="tok-comment">/// Special Listener that supports chaining request handlers.</span></span>
<span class="line" id="L107"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Listener</span>(<span class="tok-kw">comptime</span> ContextType: <span class="tok-kw">anytype</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L108"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L109"> listener: zap.HttpListener = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L110"> settings: zap.HttpListenerSettings,</span>
<span class="line" id="L111"></span>
<span class="line" id="L112"> <span class="tok-comment">// static initial handler</span>
</span>
<span class="line" id="L113"> <span class="tok-kw">var</span> handler: ?*Handler(ContextType) = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L114"> <span class="tok-comment">// static allocator getter</span>
</span>
<span class="line" id="L115"> <span class="tok-kw">var</span> requestAllocator: ?RequestAllocatorFn = <span class="tok-null">null</span>;</span>
<span class="line" id="L116"></span>
<span class="line" id="L117"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L118"></span>
<span class="line" id="L119"> <span class="tok-comment">/// Construct and initialize a middleware handler.</span></span>
<span class="line" id="L120"> <span class="tok-comment">/// The passed in settings must have on_request set to null! If that is</span></span>
<span class="line" id="L121"> <span class="tok-comment">/// not the case, an InitOnRequestIsNotNull error will be returned.</span></span>
<span class="line" id="L122"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(settings: zap.HttpListenerSettings, initial_handler: *Handler(ContextType), request_alloc: ?RequestAllocatorFn) Error!Self {</span>
<span class="line" id="L123"> <span class="tok-comment">// override on_request with ourselves</span>
</span>
<span class="line" id="L124"> <span class="tok-kw">if</span> (settings.on_request != <span class="tok-null">null</span>) {</span>
<span class="line" id="L125"> <span class="tok-kw">return</span> Error.InitOnRequestIsNotNull;</span>
<span class="line" id="L126"> }</span>
<span class="line" id="L127"> requestAllocator = request_alloc;</span>
<span class="line" id="L128"> std.debug.assert(requestAllocator != <span class="tok-null">null</span>);</span>
<span class="line" id="L129"></span>
<span class="line" id="L130"> <span class="tok-kw">var</span> ret: Self = .{</span>
<span class="line" id="L131"> .settings = settings,</span>
<span class="line" id="L132"> };</span>
<span class="line" id="L133"></span>
<span class="line" id="L134"> ret.settings.on_request = onRequest;</span>
<span class="line" id="L135"> ret.listener = zap.HttpListener.init(ret.settings);</span>
<span class="line" id="L136"> handler = initial_handler;</span>
<span class="line" id="L137"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L138"> }</span>
<span class="line" id="L139"></span>
<span class="line" id="L140"> <span class="tok-comment">/// Start listening.</span></span>
<span class="line" id="L141"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">listen</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L142"> <span class="tok-kw">try</span> self.listener.listen();</span>
<span class="line" id="L143"> }</span>
<span class="line" id="L144"></span>
<span class="line" id="L145"> <span class="tok-comment">/// The listener's request handler, stepping through the chain of Handlers</span></span>
<span class="line" id="L146"> <span class="tok-comment">/// by calling the initial one which takes it from there.</span></span>
<span class="line" id="L147"> <span class="tok-comment">///</span></span>
<span class="line" id="L148"> <span class="tok-comment">/// This is just a reference implementation that you can use by default.</span></span>
<span class="line" id="L149"> <span class="tok-comment">/// Create your own listener if you want different behavior.</span></span>
<span class="line" id="L150"> <span class="tok-comment">/// (Didn't want to make this a callback. Submit an issue if you really</span></span>
<span class="line" id="L151"> <span class="tok-comment">/// think that's an issue).</span></span>
<span class="line" id="L152"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">onRequest</span>(r: zap.Request) <span class="tok-type">void</span> {</span>
<span class="line" id="L153"> <span class="tok-comment">// we are the 1st handler in the chain, so we create a context</span>
</span>
<span class="line" id="L154"> <span class="tok-kw">var</span> context: ContextType = .{};</span>
<span class="line" id="L155"></span>
<span class="line" id="L156"> <span class="tok-comment">// handlers might need an allocator</span>
</span>
<span class="line" id="L157"> <span class="tok-comment">// we CAN provide an allocator getter</span>
</span>
<span class="line" id="L158"> <span class="tok-kw">var</span> allocator: ?std.mem.Allocator = <span class="tok-null">null</span>;</span>
<span class="line" id="L159"> <span class="tok-kw">if</span> (requestAllocator) |foo| {</span>
<span class="line" id="L160"> allocator = foo();</span>
<span class="line" id="L161"> }</span>
<span class="line" id="L162"></span>
<span class="line" id="L163"> <span class="tok-kw">if</span> (handler) |initial_handler| {</span>
<span class="line" id="L164"> initial_handler.allocator = allocator;</span>
<span class="line" id="L165"> <span class="tok-kw">if</span> (initial_handler.on_request) |on_request| {</span>
<span class="line" id="L166"> <span class="tok-comment">// we don't care about the return value at the top level</span>
</span>
<span class="line" id="L167"> _ = on_request(initial_handler, r, &amp;context);</span>
<span class="line" id="L168"> }</span>
<span class="line" id="L169"> }</span>
<span class="line" id="L170"> }</span>
<span class="line" id="L171"> };</span>
<span class="line" id="L172">}</span>
<span class="line" id="L173"></span>
</code></pre></body>
</html>

View file

@ -0,0 +1,383 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>mustache.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> fio = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;fio.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> util = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;util.zig&quot;</span>);</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> struct_mustache_s = <span class="tok-kw">opaque</span> {};</span>
<span class="line" id="L8"><span class="tok-kw">const</span> mustache_s = struct_mustache_s;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> enum_mustache_error_en = <span class="tok-type">c_uint</span>;</span>
<span class="line" id="L10"><span class="tok-kw">const</span> mustache_error_en = enum_mustache_error_en;</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_mustache_new</span>(args: MustacheLoadArgsFio) ?*mustache_s;</span>
<span class="line" id="L13"><span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_mustache_build</span>(mustache: ?*mustache_s, data: fio.FIOBJ) fio.FIOBJ;</span>
<span class="line" id="L14"><span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_mustache_build2</span>(dest: fio.FIOBJ, mustache: ?*mustache_s, data: fio.FIOBJ) fio.FIOBJ;</span>
<span class="line" id="L15"><span class="tok-kw">extern</span> <span class="tok-kw">fn</span> <span class="tok-fn">fiobj_mustache_free</span>(mustache: ?*mustache_s) <span class="tok-type">void</span>;</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-comment">/// Load arguments used when creating a new Mustache instance.</span></span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> MustacheLoadArgs = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L19"> <span class="tok-comment">/// Filename. This enables partial templates on filesystem.</span></span>
<span class="line" id="L20"> filename: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"> <span class="tok-comment">/// String data. Should be used if no filename is specified.</span></span>
<span class="line" id="L23"> data: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L24">};</span>
<span class="line" id="L25"></span>
<span class="line" id="L26"><span class="tok-comment">/// Internal struct used for interfacing with fio.</span></span>
<span class="line" id="L27"><span class="tok-kw">const</span> MustacheLoadArgsFio = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L28"> filename: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L29"> filename_len: <span class="tok-type">usize</span>,</span>
<span class="line" id="L30"> data: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L31"> data_len: <span class="tok-type">usize</span>,</span>
<span class="line" id="L32"> err: [*c]mustache_error_en,</span>
<span class="line" id="L33">};</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-comment">/// Handle to the underlying fiobj mustache instance.</span></span>
<span class="line" id="L36">handle: *mustache_s,</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Error = <span class="tok-kw">error</span>{</span>
<span class="line" id="L39"> MUSTACHE_ERR_TOO_DEEP,</span>
<span class="line" id="L40"> MUSTACHE_ERR_CLOSURE_MISMATCH,</span>
<span class="line" id="L41"> MUSTACHE_ERR_FILE_NOT_FOUND,</span>
<span class="line" id="L42"> MUSTACHE_ERR_FILE_TOO_BIG,</span>
<span class="line" id="L43"> MUSTACHE_ERR_FILE_NAME_TOO_LONG,</span>
<span class="line" id="L44"> MUSTACHE_ERR_FILE_NAME_TOO_SHORT,</span>
<span class="line" id="L45"> MUSTACHE_ERR_EMPTY_TEMPLATE,</span>
<span class="line" id="L46"> MUSTACHE_ERR_DELIMITER_TOO_LONG,</span>
<span class="line" id="L47"> MUSTACHE_ERR_NAME_TOO_LONG,</span>
<span class="line" id="L48"> MUSTACHE_ERR_UNKNOWN,</span>
<span class="line" id="L49"> MUSTACHE_ERR_USER_ERROR,</span>
<span class="line" id="L50">};</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-comment">/// Create a new `Mustache` instance; `deinit()` should be called to free</span></span>
<span class="line" id="L53"><span class="tok-comment">/// the object after usage.</span></span>
<span class="line" id="L54"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(load_args: MustacheLoadArgs) Error!Self {</span>
<span class="line" id="L55"> <span class="tok-kw">var</span> err: mustache_error_en = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L56"></span>
<span class="line" id="L57"> <span class="tok-kw">const</span> args: MustacheLoadArgsFio = .{</span>
<span class="line" id="L58"> .filename = filn: {</span>
<span class="line" id="L59"> <span class="tok-kw">if</span> (load_args.filename) |filn| <span class="tok-kw">break</span> :filn filn.ptr <span class="tok-kw">else</span> <span class="tok-kw">break</span> :filn <span class="tok-null">null</span>;</span>
<span class="line" id="L60"> },</span>
<span class="line" id="L61"> .filename_len = filn_len: {</span>
<span class="line" id="L62"> <span class="tok-kw">if</span> (load_args.filename) |filn| <span class="tok-kw">break</span> :filn_len filn.len <span class="tok-kw">else</span> <span class="tok-kw">break</span> :filn_len <span class="tok-number">0</span>;</span>
<span class="line" id="L63"> },</span>
<span class="line" id="L64"> .data = data: {</span>
<span class="line" id="L65"> <span class="tok-kw">if</span> (load_args.data) |data| <span class="tok-kw">break</span> :data data.ptr <span class="tok-kw">else</span> <span class="tok-kw">break</span> :data <span class="tok-null">null</span>;</span>
<span class="line" id="L66"> },</span>
<span class="line" id="L67"> .data_len = data_len: {</span>
<span class="line" id="L68"> <span class="tok-kw">if</span> (load_args.data) |data| <span class="tok-kw">break</span> :data_len data.len <span class="tok-kw">else</span> <span class="tok-kw">break</span> :data_len <span class="tok-number">0</span>;</span>
<span class="line" id="L69"> },</span>
<span class="line" id="L70"> .err = &amp;err,</span>
<span class="line" id="L71"> };</span>
<span class="line" id="L72"></span>
<span class="line" id="L73"> <span class="tok-kw">const</span> ret = fiobj_mustache_new(args);</span>
<span class="line" id="L74"> <span class="tok-kw">switch</span> (err) {</span>
<span class="line" id="L75"> <span class="tok-number">0</span> =&gt; <span class="tok-kw">return</span> Self{</span>
<span class="line" id="L76"> .handle = ret.?,</span>
<span class="line" id="L77"> },</span>
<span class="line" id="L78"> <span class="tok-number">1</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_TOO_DEEP,</span>
<span class="line" id="L79"> <span class="tok-number">2</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_CLOSURE_MISMATCH,</span>
<span class="line" id="L80"> <span class="tok-number">3</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_FILE_NOT_FOUND,</span>
<span class="line" id="L81"> <span class="tok-number">4</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_FILE_TOO_BIG,</span>
<span class="line" id="L82"> <span class="tok-number">5</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_FILE_NAME_TOO_LONG,</span>
<span class="line" id="L83"> <span class="tok-number">6</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_FILE_NAME_TOO_SHORT,</span>
<span class="line" id="L84"> <span class="tok-number">7</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_EMPTY_TEMPLATE,</span>
<span class="line" id="L85"> <span class="tok-number">8</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_DELIMITER_TOO_LONG,</span>
<span class="line" id="L86"> <span class="tok-number">9</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_NAME_TOO_LONG,</span>
<span class="line" id="L87"> <span class="tok-number">10</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_UNKNOWN,</span>
<span class="line" id="L88"> <span class="tok-number">11</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_USER_ERROR,</span>
<span class="line" id="L89"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> Error.MUSTACHE_ERR_UNKNOWN,</span>
<span class="line" id="L90"> }</span>
<span class="line" id="L91"> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L92">}</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"><span class="tok-comment">/// Convenience function to create a new `Mustache` instance with in-memory data loaded;</span></span>
<span class="line" id="L95"><span class="tok-comment">/// `deinit()` should be called to free the object after usage..</span></span>
<span class="line" id="L96"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fromData</span>(data: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) Error!Self {</span>
<span class="line" id="L97"> <span class="tok-kw">return</span> Self.init(.{ .data = data });</span>
<span class="line" id="L98">}</span>
<span class="line" id="L99"></span>
<span class="line" id="L100"><span class="tok-comment">/// Convenience function to create a new `Mustache` instance with file-based data loaded;</span></span>
<span class="line" id="L101"><span class="tok-comment">/// `deinit()` should be called to free the object after usage..</span></span>
<span class="line" id="L102"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fromFile</span>(filename: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) Error!Self {</span>
<span class="line" id="L103"> <span class="tok-kw">return</span> Self.init(.{ .filename = filename });</span>
<span class="line" id="L104">}</span>
<span class="line" id="L105"></span>
<span class="line" id="L106"><span class="tok-comment">/// Free the data backing a `Mustache` instance.</span></span>
<span class="line" id="L107"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L108"> fiobj_mustache_free(self.handle);</span>
<span class="line" id="L109">}</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"><span class="tok-comment">// TODO: implement these - fiobj_mustache.c</span>
</span>
<span class="line" id="L112"><span class="tok-comment">// pub extern fn fiobj_mustache_build(mustache: ?*mustache_s, data: FIOBJ) FIOBJ;</span>
</span>
<span class="line" id="L113"><span class="tok-comment">// pub extern fn fiobj_mustache_build2(dest: FIOBJ, mustache: ?*mustache_s, data: FIOBJ) FIOBJ;</span>
</span>
<span class="line" id="L114"></span>
<span class="line" id="L115"><span class="tok-comment">/// The result from calling `build`.</span></span>
<span class="line" id="L116"><span class="tok-kw">const</span> MustacheBuildResult = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L117"> fiobj_result: fio.FIOBJ = <span class="tok-number">0</span>,</span>
<span class="line" id="L118"></span>
<span class="line" id="L119"> <span class="tok-comment">/// Holds the context converted into a fiobj.</span></span>
<span class="line" id="L120"> <span class="tok-comment">/// This is used in `build`.</span></span>
<span class="line" id="L121"> fiobj_context: fio.FIOBJ = <span class="tok-number">0</span>,</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"> <span class="tok-comment">/// Free the data backing a `MustacheBuildResult` instance.</span></span>
<span class="line" id="L124"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(m: *<span class="tok-kw">const</span> MustacheBuildResult) <span class="tok-type">void</span> {</span>
<span class="line" id="L125"> fio.fiobj_free_wrapped(m.fiobj_result);</span>
<span class="line" id="L126"> fio.fiobj_free_wrapped(m.fiobj_context);</span>
<span class="line" id="L127"> }</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"> <span class="tok-comment">/// Retrieve a string representation of the built template.</span></span>
<span class="line" id="L130"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">str</span>(m: *<span class="tok-kw">const</span> MustacheBuildResult) ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L131"> <span class="tok-kw">return</span> util.fio2str(m.fiobj_result);</span>
<span class="line" id="L132"> }</span>
<span class="line" id="L133">};</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"><span class="tok-comment">/// Build the Mustache template; `deinit()` should be called on the build</span></span>
<span class="line" id="L136"><span class="tok-comment">/// result to free the data.</span></span>
<span class="line" id="L137"><span class="tok-comment">// TODO: The build may be slow because it needs to convert zig types to facil.io</span>
</span>
<span class="line" id="L138"><span class="tok-comment">// types. However, this needs to be investigated into.</span>
</span>
<span class="line" id="L139"><span class="tok-comment">// See `fiobjectify` for more information.</span>
</span>
<span class="line" id="L140"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">build</span>(self: *Self, data: <span class="tok-kw">anytype</span>) MustacheBuildResult {</span>
<span class="line" id="L141"> <span class="tok-kw">const</span> T = <span class="tok-builtin">@TypeOf</span>(data);</span>
<span class="line" id="L142"> <span class="tok-kw">if</span> (<span class="tok-builtin">@typeInfo</span>(T) != .Struct) {</span>
<span class="line" id="L143"> <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;No struct: '&quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot;'&quot;</span>);</span>
<span class="line" id="L144"> }</span>
<span class="line" id="L145"></span>
<span class="line" id="L146"> <span class="tok-kw">var</span> result: MustacheBuildResult = .{};</span>
<span class="line" id="L147"></span>
<span class="line" id="L148"> result.fiobj_context = fiobjectify(data);</span>
<span class="line" id="L149"> result.fiobj_result = fiobj_mustache_build(self.handle, result.fiobj_context);</span>
<span class="line" id="L150"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L151">}</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"><span class="tok-comment">/// Internal function used to convert zig types to facil.io types.</span></span>
<span class="line" id="L154"><span class="tok-comment">/// Used when providing the context to `fiobj_mustache_build`.</span></span>
<span class="line" id="L155"><span class="tok-kw">fn</span> <span class="tok-fn">fiobjectify</span>(</span>
<span class="line" id="L156"> value: <span class="tok-kw">anytype</span>,</span>
<span class="line" id="L157">) fio.FIOBJ {</span>
<span class="line" id="L158"> <span class="tok-kw">const</span> T = <span class="tok-builtin">@TypeOf</span>(value);</span>
<span class="line" id="L159"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(T)) {</span>
<span class="line" id="L160"> .Float, .ComptimeFloat =&gt; {</span>
<span class="line" id="L161"> <span class="tok-kw">return</span> fio.fiobj_float_new(value);</span>
<span class="line" id="L162"> },</span>
<span class="line" id="L163"> .Int, .ComptimeInt =&gt; {</span>
<span class="line" id="L164"> <span class="tok-kw">return</span> fio.fiobj_num_new_bignum(value);</span>
<span class="line" id="L165"> },</span>
<span class="line" id="L166"> .Bool =&gt; {</span>
<span class="line" id="L167"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (value) fio.fiobj_true() <span class="tok-kw">else</span> fio.fiobj_false();</span>
<span class="line" id="L168"> },</span>
<span class="line" id="L169"> .Null =&gt; {</span>
<span class="line" id="L170"> <span class="tok-kw">return</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L171"> },</span>
<span class="line" id="L172"> .Optional =&gt; {</span>
<span class="line" id="L173"> <span class="tok-kw">if</span> (value) |payload| {</span>
<span class="line" id="L174"> <span class="tok-kw">return</span> fiobjectify(payload);</span>
<span class="line" id="L175"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L176"> <span class="tok-kw">return</span> fiobjectify(<span class="tok-null">null</span>);</span>
<span class="line" id="L177"> }</span>
<span class="line" id="L178"> },</span>
<span class="line" id="L179"> .Enum =&gt; {</span>
<span class="line" id="L180"> <span class="tok-kw">return</span> fio.fiobj_num_new_bignum(<span class="tok-builtin">@intFromEnum</span>(value));</span>
<span class="line" id="L181"> },</span>
<span class="line" id="L182"> .Union =&gt; {</span>
<span class="line" id="L183"> <span class="tok-kw">const</span> info = <span class="tok-builtin">@typeInfo</span>(T).Union;</span>
<span class="line" id="L184"> <span class="tok-kw">if</span> (info.tag_type) |UnionTagType| {</span>
<span class="line" id="L185"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (info.fields) |u_field| {</span>
<span class="line" id="L186"> <span class="tok-kw">if</span> (value == <span class="tok-builtin">@field</span>(UnionTagType, u_field.name)) {</span>
<span class="line" id="L187"> <span class="tok-kw">return</span> fiobjectify(<span class="tok-builtin">@field</span>(value, u_field.name));</span>
<span class="line" id="L188"> }</span>
<span class="line" id="L189"> }</span>
<span class="line" id="L190"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L191"> <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Unable to fiobjectify untagged union '&quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot;'&quot;</span>);</span>
<span class="line" id="L192"> }</span>
<span class="line" id="L193"> },</span>
<span class="line" id="L194"> .Struct =&gt; |S| {</span>
<span class="line" id="L195"> <span class="tok-comment">// create a new fio hashmap</span>
</span>
<span class="line" id="L196"> <span class="tok-kw">const</span> m = fio.fiobj_hash_new();</span>
<span class="line" id="L197"> <span class="tok-comment">// std.debug.print(&quot;new struct\n&quot;, .{});</span>
</span>
<span class="line" id="L198"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (S.fields) |Field| {</span>
<span class="line" id="L199"> <span class="tok-comment">// don't include void fields</span>
</span>
<span class="line" id="L200"> <span class="tok-kw">if</span> (Field.<span class="tok-type">type</span> == <span class="tok-type">void</span>) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L201"></span>
<span class="line" id="L202"> <span class="tok-comment">// std.debug.print(&quot; new field: {s}\n&quot;, .{Field.name});</span>
</span>
<span class="line" id="L203"> <span class="tok-kw">const</span> fname = fio.fiobj_str_new(util.toCharPtr(Field.name), Field.name.len);</span>
<span class="line" id="L204"> <span class="tok-comment">// std.debug.print(&quot; fiobj name : {any}\n&quot;, .{fname});</span>
</span>
<span class="line" id="L205"> <span class="tok-kw">const</span> v = <span class="tok-builtin">@field</span>(value, Field.name);</span>
<span class="line" id="L206"> <span class="tok-comment">// std.debug.print(&quot; value: {any}\n&quot;, .{v});</span>
</span>
<span class="line" id="L207"> <span class="tok-kw">const</span> fvalue = fiobjectify(v);</span>
<span class="line" id="L208"> <span class="tok-comment">// std.debug.print(&quot; fiobj value: {any}\n&quot;, .{fvalue});</span>
</span>
<span class="line" id="L209"> _ = fio.fiobj_hash_set(m, fname, fvalue);</span>
<span class="line" id="L210"> fio.fiobj_free_wrapped(fname);</span>
<span class="line" id="L211"> }</span>
<span class="line" id="L212"> <span class="tok-kw">return</span> m;</span>
<span class="line" id="L213"> },</span>
<span class="line" id="L214"> .ErrorSet =&gt; <span class="tok-kw">return</span> fiobjectify(<span class="tok-builtin">@as</span>([]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, <span class="tok-builtin">@errorName</span>(value))),</span>
<span class="line" id="L215"> .Pointer =&gt; |ptr_info| <span class="tok-kw">switch</span> (ptr_info.size) {</span>
<span class="line" id="L216"> .One =&gt; <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(ptr_info.child)) {</span>
<span class="line" id="L217"> .Array =&gt; {</span>
<span class="line" id="L218"> <span class="tok-kw">const</span> Slice = []<span class="tok-kw">const</span> std.meta.Elem(ptr_info.child);</span>
<span class="line" id="L219"> <span class="tok-kw">return</span> fiobjectify(<span class="tok-builtin">@as</span>(Slice, value));</span>
<span class="line" id="L220"> },</span>
<span class="line" id="L221"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L222"> <span class="tok-comment">// TODO: avoid loops?</span>
</span>
<span class="line" id="L223"> <span class="tok-kw">return</span> fiobjectify(value.*);</span>
<span class="line" id="L224"> },</span>
<span class="line" id="L225"> },</span>
<span class="line" id="L226"> <span class="tok-comment">// TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)</span>
</span>
<span class="line" id="L227"> .Slice =&gt; {</span>
<span class="line" id="L228"> <span class="tok-comment">// std.debug.print(&quot;new slice\n&quot;, .{});</span>
</span>
<span class="line" id="L229"> <span class="tok-kw">if</span> (ptr_info.child == <span class="tok-type">u8</span> <span class="tok-kw">and</span> std.unicode.utf8ValidateSlice(value)) {</span>
<span class="line" id="L230"> <span class="tok-kw">return</span> fio.fiobj_str_new(util.toCharPtr(value), value.len);</span>
<span class="line" id="L231"> }</span>
<span class="line" id="L232"></span>
<span class="line" id="L233"> <span class="tok-kw">const</span> arr = fio.fiobj_ary_new2(value.len);</span>
<span class="line" id="L234"> <span class="tok-kw">for</span> (value) |x| {</span>
<span class="line" id="L235"> <span class="tok-kw">const</span> v = fiobjectify(x);</span>
<span class="line" id="L236"> fio.fiobj_ary_push(arr, v);</span>
<span class="line" id="L237"> }</span>
<span class="line" id="L238"> <span class="tok-kw">return</span> arr;</span>
<span class="line" id="L239"> },</span>
<span class="line" id="L240"> <span class="tok-kw">else</span> =&gt; <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Unable to fiobjectify type '&quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot;'&quot;</span>),</span>
<span class="line" id="L241"> },</span>
<span class="line" id="L242"> .Array =&gt; <span class="tok-kw">return</span> fiobjectify(&amp;value),</span>
<span class="line" id="L243"> .Vector =&gt; |info| {</span>
<span class="line" id="L244"> <span class="tok-kw">const</span> array: [info.len]info.child = value;</span>
<span class="line" id="L245"> <span class="tok-kw">return</span> fiobjectify(&amp;array);</span>
<span class="line" id="L246"> },</span>
<span class="line" id="L247"> <span class="tok-kw">else</span> =&gt; <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Unable to fiobjectify type '&quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot;'&quot;</span>),</span>
<span class="line" id="L248"> }</span>
<span class="line" id="L249"> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L250">}</span>
<span class="line" id="L251"></span>
</code></pre></body>
</html>

View file

@ -0,0 +1,883 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>request.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Log = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;log.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> http = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;http.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">const</span> fio = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;fio.zig&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> util = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;util.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> zap = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zap.zig&quot;</span>);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpError = <span class="tok-kw">error</span>{</span>
<span class="line" id="L10"> HttpSendBody,</span>
<span class="line" id="L11"> HttpSetContentType,</span>
<span class="line" id="L12"> HttpSetHeader,</span>
<span class="line" id="L13"> HttpParseBody,</span>
<span class="line" id="L14"> HttpIterParams,</span>
<span class="line" id="L15"> SetCookie,</span>
<span class="line" id="L16"> SendFile,</span>
<span class="line" id="L17">};</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"><span class="tok-comment">/// Http Content Type enum.</span></span>
<span class="line" id="L20"><span class="tok-comment">/// Needs some love.</span></span>
<span class="line" id="L21"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ContentType = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L22"> TEXT,</span>
<span class="line" id="L23"> HTML,</span>
<span class="line" id="L24"> JSON,</span>
<span class="line" id="L25"> <span class="tok-comment">// TODO: more content types</span>
</span>
<span class="line" id="L26">};</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"><span class="tok-comment">/// Key value pair of strings from HTTP parameters</span></span>
<span class="line" id="L29"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpParamStrKV = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L30"> key: util.FreeOrNot,</span>
<span class="line" id="L31"> value: util.FreeOrNot,</span>
<span class="line" id="L32"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *<span class="tok-builtin">@This</span>()) <span class="tok-type">void</span> {</span>
<span class="line" id="L33"> self.key.deinit();</span>
<span class="line" id="L34"> self.value.deinit();</span>
<span class="line" id="L35"> }</span>
<span class="line" id="L36">};</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"><span class="tok-comment">/// List of key value pairs of Http param strings.</span></span>
<span class="line" id="L39"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpParamStrKVList = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L40"> items: []HttpParamStrKV,</span>
<span class="line" id="L41"> allocator: std.mem.Allocator,</span>
<span class="line" id="L42"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *<span class="tok-builtin">@This</span>()) <span class="tok-type">void</span> {</span>
<span class="line" id="L43"> <span class="tok-kw">for</span> (self.items) |*item| {</span>
<span class="line" id="L44"> item.deinit();</span>
<span class="line" id="L45"> }</span>
<span class="line" id="L46"> self.allocator.free(self.items);</span>
<span class="line" id="L47"> }</span>
<span class="line" id="L48">};</span>
<span class="line" id="L49"></span>
<span class="line" id="L50"><span class="tok-comment">/// List of key value pairs of Http params (might be of different types).</span></span>
<span class="line" id="L51"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpParamKVList = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L52"> items: []HttpParamKV,</span>
<span class="line" id="L53"> allocator: std.mem.Allocator,</span>
<span class="line" id="L54"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *<span class="tok-kw">const</span> <span class="tok-builtin">@This</span>()) <span class="tok-type">void</span> {</span>
<span class="line" id="L55"> <span class="tok-kw">for</span> (self.items) |*item| {</span>
<span class="line" id="L56"> item.deinit();</span>
<span class="line" id="L57"> }</span>
<span class="line" id="L58"> self.allocator.free(self.items);</span>
<span class="line" id="L59"> }</span>
<span class="line" id="L60">};</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"><span class="tok-comment">/// Enum for HttpParam tagged union</span></span>
<span class="line" id="L63"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpParamValueType = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L64"> <span class="tok-comment">// Null,</span>
</span>
<span class="line" id="L65"> Bool,</span>
<span class="line" id="L66"> Int,</span>
<span class="line" id="L67"> Float,</span>
<span class="line" id="L68"> String,</span>
<span class="line" id="L69"> Unsupported,</span>
<span class="line" id="L70"> Hash_Binfile,</span>
<span class="line" id="L71"> Array_Binfile,</span>
<span class="line" id="L72">};</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"><span class="tok-comment">/// Tagged union holding a typed Http param</span></span>
<span class="line" id="L75"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpParam = <span class="tok-kw">union</span>(HttpParamValueType) {</span>
<span class="line" id="L76"> Bool: <span class="tok-type">bool</span>,</span>
<span class="line" id="L77"> Int: <span class="tok-type">isize</span>,</span>
<span class="line" id="L78"> Float: <span class="tok-type">f64</span>,</span>
<span class="line" id="L79"> <span class="tok-comment">/// we don't do writable strings here</span></span>
<span class="line" id="L80"> String: util.FreeOrNot,</span>
<span class="line" id="L81"> <span class="tok-comment">/// value will always be null</span></span>
<span class="line" id="L82"> Unsupported: ?<span class="tok-type">void</span>,</span>
<span class="line" id="L83"> <span class="tok-comment">/// we assume hashes are because of file transmissions</span></span>
<span class="line" id="L84"> Hash_Binfile: HttpParamBinaryFile,</span>
<span class="line" id="L85"> <span class="tok-comment">/// value will always be null</span></span>
<span class="line" id="L86"> Array_Binfile: std.ArrayList(HttpParamBinaryFile),</span>
<span class="line" id="L87">};</span>
<span class="line" id="L88"></span>
<span class="line" id="L89"><span class="tok-comment">/// Key value pair of one typed Http param</span></span>
<span class="line" id="L90"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpParamKV = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L91"> key: util.FreeOrNot,</span>
<span class="line" id="L92"> value: ?HttpParam,</span>
<span class="line" id="L93"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *<span class="tok-builtin">@This</span>()) <span class="tok-type">void</span> {</span>
<span class="line" id="L94"> self.key.deinit();</span>
<span class="line" id="L95"> <span class="tok-kw">if</span> (self.value) |p| {</span>
<span class="line" id="L96"> <span class="tok-kw">switch</span> (p) {</span>
<span class="line" id="L97"> .String =&gt; |*s| s.deinit(),</span>
<span class="line" id="L98"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L99"> }</span>
<span class="line" id="L100"> }</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102">};</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"><span class="tok-comment">/// Struct representing an uploaded file.</span></span>
<span class="line" id="L105"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpParamBinaryFile = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L106"> <span class="tok-comment">/// file contents</span></span>
<span class="line" id="L107"> data: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L108"> <span class="tok-comment">/// mimetype</span></span>
<span class="line" id="L109"> mimetype: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L110"> <span class="tok-comment">/// filename</span></span>
<span class="line" id="L111"> filename: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L112"></span>
<span class="line" id="L113"> <span class="tok-comment">/// format function for printing file upload data</span></span>
<span class="line" id="L114"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>(value: <span class="tok-builtin">@This</span>(), <span class="tok-kw">comptime</span> _: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, _: std.fmt.FormatOptions, writer: <span class="tok-kw">anytype</span>) std.os.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L115"> <span class="tok-kw">const</span> d = value.data <span class="tok-kw">orelse</span> <span class="tok-str">&quot;\\0&quot;</span>;</span>
<span class="line" id="L116"> <span class="tok-kw">const</span> m = value.mimetype <span class="tok-kw">orelse</span> <span class="tok-str">&quot;null&quot;</span>;</span>
<span class="line" id="L117"> <span class="tok-kw">const</span> f = value.filename <span class="tok-kw">orelse</span> <span class="tok-str">&quot;null&quot;</span>;</span>
<span class="line" id="L118"> <span class="tok-kw">return</span> writer.print(<span class="tok-str">&quot;&lt;{s} ({s}): {any}&gt;&quot;</span>, .{ f, m, d });</span>
<span class="line" id="L119"> }</span>
<span class="line" id="L120">};</span>
<span class="line" id="L121"></span>
<span class="line" id="L122"><span class="tok-kw">fn</span> <span class="tok-fn">parseBinfilesFrom</span>(a: std.mem.Allocator, o: fio.FIOBJ) !HttpParam {</span>
<span class="line" id="L123"> <span class="tok-kw">const</span> key_name = fio.fiobj_str_new(<span class="tok-str">&quot;name&quot;</span>, <span class="tok-number">4</span>);</span>
<span class="line" id="L124"> <span class="tok-kw">const</span> key_data = fio.fiobj_str_new(<span class="tok-str">&quot;data&quot;</span>, <span class="tok-number">4</span>);</span>
<span class="line" id="L125"> <span class="tok-kw">const</span> key_type = fio.fiobj_str_new(<span class="tok-str">&quot;type&quot;</span>, <span class="tok-number">4</span>);</span>
<span class="line" id="L126"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L127"> fio.fiobj_free_wrapped(key_name);</span>
<span class="line" id="L128"> fio.fiobj_free_wrapped(key_data);</span>
<span class="line" id="L129"> fio.fiobj_free_wrapped(key_type);</span>
<span class="line" id="L130"> } <span class="tok-comment">// files: they should have &quot;data&quot;, &quot;type&quot;, and &quot;filename&quot; keys</span>
</span>
<span class="line" id="L131"> <span class="tok-kw">if</span> (fio.fiobj_hash_haskey(o, key_data) == <span class="tok-number">1</span> <span class="tok-kw">and</span> fio.fiobj_hash_haskey(o, key_type) == <span class="tok-number">1</span> <span class="tok-kw">and</span> fio.fiobj_hash_haskey(o, key_name) == <span class="tok-number">1</span>) {</span>
<span class="line" id="L132"> <span class="tok-kw">const</span> filename = fio.fiobj_obj2cstr(fio.fiobj_hash_get(o, key_name));</span>
<span class="line" id="L133"> <span class="tok-kw">const</span> mimetype = fio.fiobj_obj2cstr(fio.fiobj_hash_get(o, key_type));</span>
<span class="line" id="L134"> <span class="tok-kw">const</span> data = fio.fiobj_hash_get(o, key_data);</span>
<span class="line" id="L135"></span>
<span class="line" id="L136"> <span class="tok-kw">var</span> data_slice: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>;</span>
<span class="line" id="L137"></span>
<span class="line" id="L138"> <span class="tok-kw">switch</span> (fio.fiobj_type(data)) {</span>
<span class="line" id="L139"> fio.FIOBJ_T_DATA =&gt; {</span>
<span class="line" id="L140"> <span class="tok-kw">if</span> (fio.is_invalid(data) == <span class="tok-number">1</span>) {</span>
<span class="line" id="L141"> data_slice = <span class="tok-str">&quot;(zap: invalid data)&quot;</span>;</span>
<span class="line" id="L142"> std.log.warn(<span class="tok-str">&quot;WARNING: HTTP param binary file is not a data object\n&quot;</span>, .{});</span>
<span class="line" id="L143"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L144"> <span class="tok-comment">// the data</span>
</span>
<span class="line" id="L145"> <span class="tok-kw">const</span> data_len = fio.fiobj_data_len(data);</span>
<span class="line" id="L146"> <span class="tok-kw">var</span> data_buf = fio.fiobj_data_read(data, data_len);</span>
<span class="line" id="L147"></span>
<span class="line" id="L148"> <span class="tok-kw">if</span> (data_len &lt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L149"> std.log.warn(<span class="tok-str">&quot;WARNING: HTTP param binary file size negative: {d}\n&quot;</span>, .{data_len});</span>
<span class="line" id="L150"> std.log.warn(<span class="tok-str">&quot;FIOBJ_TYPE of data is: {d}\n&quot;</span>, .{fio.fiobj_type(data)});</span>
<span class="line" id="L151"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L152"> <span class="tok-kw">if</span> (data_buf.len != data_len) {</span>
<span class="line" id="L153"> std.log.warn(<span class="tok-str">&quot;WARNING: HTTP param binary file size mismatch: should {d}, is: {d}\n&quot;</span>, .{ data_len, data_buf.len });</span>
<span class="line" id="L154"> }</span>
<span class="line" id="L155"></span>
<span class="line" id="L156"> <span class="tok-kw">if</span> (data_buf.len &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L157"> data_slice = data_buf.data[<span class="tok-number">0</span>..data_buf.len];</span>
<span class="line" id="L158"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L159"> std.log.warn(<span class="tok-str">&quot;WARNING: HTTP param binary file buffer size negative: {d}\n&quot;</span>, .{data_buf.len});</span>
<span class="line" id="L160"> data_slice = <span class="tok-str">&quot;(zap: invalid data: negative BUFFER size)&quot;</span>;</span>
<span class="line" id="L161"> }</span>
<span class="line" id="L162"> }</span>
<span class="line" id="L163"> }</span>
<span class="line" id="L164"> },</span>
<span class="line" id="L165"> fio.FIOBJ_T_STRING =&gt; {</span>
<span class="line" id="L166"> <span class="tok-kw">const</span> fiostr = fio.fiobj_obj2cstr(data);</span>
<span class="line" id="L167"> <span class="tok-kw">if</span> (fiostr.len == <span class="tok-number">0</span>) {</span>
<span class="line" id="L168"> data_slice = <span class="tok-str">&quot;(zap: empty string data)&quot;</span>;</span>
<span class="line" id="L169"> std.log.warn(<span class="tok-str">&quot;WARNING: HTTP param binary file has empty string object\n&quot;</span>, .{});</span>
<span class="line" id="L170"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L171"> data_slice = fiostr.data[<span class="tok-number">0</span>..fiostr.len];</span>
<span class="line" id="L172"> }</span>
<span class="line" id="L173"> },</span>
<span class="line" id="L174"> fio.FIOBJ_T_ARRAY =&gt; {</span>
<span class="line" id="L175"> <span class="tok-comment">// OK, data is an array</span>
</span>
<span class="line" id="L176"> <span class="tok-kw">const</span> len = fio.fiobj_ary_count(data);</span>
<span class="line" id="L177"> <span class="tok-kw">const</span> fn_ary = fio.fiobj_hash_get(o, key_name);</span>
<span class="line" id="L178"> <span class="tok-kw">const</span> mt_ary = fio.fiobj_hash_get(o, key_type);</span>
<span class="line" id="L179"></span>
<span class="line" id="L180"> <span class="tok-kw">if</span> (fio.fiobj_ary_count(fn_ary) == len <span class="tok-kw">and</span> fio.fiobj_ary_count(mt_ary) == len) {</span>
<span class="line" id="L181"> <span class="tok-kw">var</span> i: <span class="tok-type">isize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L182"> <span class="tok-kw">var</span> ret = std.ArrayList(HttpParamBinaryFile).init(a);</span>
<span class="line" id="L183"> <span class="tok-kw">while</span> (i &lt; len) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L184"> <span class="tok-kw">const</span> file_data_obj = fio.fiobj_ary_entry(data, i);</span>
<span class="line" id="L185"> <span class="tok-kw">const</span> file_name_obj = fio.fiobj_ary_entry(fn_ary, i);</span>
<span class="line" id="L186"> <span class="tok-kw">const</span> file_mimetype_obj = fio.fiobj_ary_entry(mt_ary, i);</span>
<span class="line" id="L187"> <span class="tok-kw">var</span> has_error: <span class="tok-type">bool</span> = <span class="tok-null">false</span>;</span>
<span class="line" id="L188"> <span class="tok-kw">if</span> (fio.is_invalid(file_data_obj) == <span class="tok-number">1</span>) {</span>
<span class="line" id="L189"> std.log.debug(<span class="tok-str">&quot;file data invalid in array&quot;</span>, .{});</span>
<span class="line" id="L190"> has_error = <span class="tok-null">true</span>;</span>
<span class="line" id="L191"> }</span>
<span class="line" id="L192"> <span class="tok-kw">if</span> (fio.is_invalid(file_name_obj) == <span class="tok-number">1</span>) {</span>
<span class="line" id="L193"> std.log.debug(<span class="tok-str">&quot;file name invalid in array&quot;</span>, .{});</span>
<span class="line" id="L194"> has_error = <span class="tok-null">true</span>;</span>
<span class="line" id="L195"> }</span>
<span class="line" id="L196"> <span class="tok-kw">if</span> (fio.is_invalid(file_mimetype_obj) == <span class="tok-number">1</span>) {</span>
<span class="line" id="L197"> std.log.debug(<span class="tok-str">&quot;file mimetype invalid in array&quot;</span>, .{});</span>
<span class="line" id="L198"> has_error = <span class="tok-null">true</span>;</span>
<span class="line" id="L199"> }</span>
<span class="line" id="L200"> <span class="tok-kw">if</span> (has_error) {</span>
<span class="line" id="L201"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Invalid;</span>
<span class="line" id="L202"> }</span>
<span class="line" id="L203"></span>
<span class="line" id="L204"> <span class="tok-kw">const</span> file_data = fio.fiobj_obj2cstr(file_data_obj);</span>
<span class="line" id="L205"> <span class="tok-kw">const</span> file_name = fio.fiobj_obj2cstr(file_name_obj);</span>
<span class="line" id="L206"> <span class="tok-kw">const</span> file_mimetype = fio.fiobj_obj2cstr(file_mimetype_obj);</span>
<span class="line" id="L207"> <span class="tok-kw">try</span> ret.append(.{</span>
<span class="line" id="L208"> .data = file_data.data[<span class="tok-number">0</span>..file_data.len],</span>
<span class="line" id="L209"> .mimetype = file_mimetype.data[<span class="tok-number">0</span>..file_mimetype.len],</span>
<span class="line" id="L210"> .filename = file_name.data[<span class="tok-number">0</span>..file_name.len],</span>
<span class="line" id="L211"> });</span>
<span class="line" id="L212"> }</span>
<span class="line" id="L213"> <span class="tok-kw">return</span> .{ .Array_Binfile = ret };</span>
<span class="line" id="L214"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L215"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.ArrayLenMismatch;</span>
<span class="line" id="L216"> }</span>
<span class="line" id="L217"> },</span>
<span class="line" id="L218"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L219"> <span class="tok-comment">// don't know what to do</span>
</span>
<span class="line" id="L220"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported;</span>
<span class="line" id="L221"> },</span>
<span class="line" id="L222"> }</span>
<span class="line" id="L223"></span>
<span class="line" id="L224"> <span class="tok-kw">return</span> .{ .Hash_Binfile = .{</span>
<span class="line" id="L225"> .filename = filename.data[<span class="tok-number">0</span>..filename.len],</span>
<span class="line" id="L226"> .mimetype = mimetype.data[<span class="tok-number">0</span>..mimetype.len],</span>
<span class="line" id="L227"> .data = data_slice,</span>
<span class="line" id="L228"> } };</span>
<span class="line" id="L229"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L230"> <span class="tok-kw">return</span> .{ .Hash_Binfile = .{} };</span>
<span class="line" id="L231"> }</span>
<span class="line" id="L232">}</span>
<span class="line" id="L233"></span>
<span class="line" id="L234"><span class="tok-comment">/// Parse FIO object into a typed Http param. Supports file uploads.</span></span>
<span class="line" id="L235"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Fiobj2HttpParam</span>(a: std.mem.Allocator, o: fio.FIOBJ, dupe_string: <span class="tok-type">bool</span>) !?HttpParam {</span>
<span class="line" id="L236"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (fio.fiobj_type(o)) {</span>
<span class="line" id="L237"> fio.FIOBJ_T_NULL =&gt; <span class="tok-null">null</span>,</span>
<span class="line" id="L238"> fio.FIOBJ_T_TRUE =&gt; .{ .Bool = <span class="tok-null">true</span> },</span>
<span class="line" id="L239"> fio.FIOBJ_T_FALSE =&gt; .{ .Bool = <span class="tok-null">false</span> },</span>
<span class="line" id="L240"> fio.FIOBJ_T_NUMBER =&gt; .{ .Int = fio.fiobj_obj2num(o) },</span>
<span class="line" id="L241"> fio.FIOBJ_T_FLOAT =&gt; .{ .Float = fio.fiobj_obj2float(o) },</span>
<span class="line" id="L242"> fio.FIOBJ_T_STRING =&gt; .{ .String = <span class="tok-kw">try</span> util.fio2strAllocOrNot(a, o, dupe_string) },</span>
<span class="line" id="L243"> fio.FIOBJ_T_ARRAY =&gt; {</span>
<span class="line" id="L244"> <span class="tok-kw">return</span> .{ .Unsupported = <span class="tok-null">null</span> };</span>
<span class="line" id="L245"> },</span>
<span class="line" id="L246"> fio.FIOBJ_T_HASH =&gt; {</span>
<span class="line" id="L247"> <span class="tok-kw">const</span> file = <span class="tok-kw">try</span> parseBinfilesFrom(a, o);</span>
<span class="line" id="L248"> <span class="tok-kw">return</span> file;</span>
<span class="line" id="L249"> },</span>
<span class="line" id="L250"> <span class="tok-kw">else</span> =&gt; .{ .Unsupported = <span class="tok-null">null</span> },</span>
<span class="line" id="L251"> };</span>
<span class="line" id="L252">}</span>
<span class="line" id="L253"></span>
<span class="line" id="L254"><span class="tok-comment">/// Args for setting a cookie</span></span>
<span class="line" id="L255"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CookieArgs = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L256"> name: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L257"> value: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L258"> domain: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L259"> path: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L260"> <span class="tok-comment">/// max age in seconds. 0 -&gt; session</span></span>
<span class="line" id="L261"> max_age_s: <span class="tok-type">c_int</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L262"> secure: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L263"> http_only: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L264">};</span>
<span class="line" id="L265"></span>
<span class="line" id="L266">path: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L267">query: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L268">body: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L269">method: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L270">h: [*c]fio.http_s,</span>
<span class="line" id="L271"></span>
<span class="line" id="L272"><span class="tok-comment">/// NEVER touch this field!!!!</span></span>
<span class="line" id="L273"><span class="tok-comment">/// if you absolutely MUST, then you may provide context here</span></span>
<span class="line" id="L274"><span class="tok-comment">/// via setUserContext and getUserContext</span></span>
<span class="line" id="L275">_user_context: *UserContext,</span>
<span class="line" id="L276"><span class="tok-comment">/// NEVER touch this field!!!!</span></span>
<span class="line" id="L277"><span class="tok-comment">/// use markAsFinished() and isFinished() instead</span></span>
<span class="line" id="L278"><span class="tok-comment">/// this is a hack: the listener will put a pointer to this into the udata</span></span>
<span class="line" id="L279"><span class="tok-comment">/// field of `h`. So copies of the Request will all have way to the</span></span>
<span class="line" id="L280"><span class="tok-comment">/// same instance of this field.</span></span>
<span class="line" id="L281">_is_finished_request_global: <span class="tok-type">bool</span>,</span>
<span class="line" id="L282"><span class="tok-comment">/// NEVER touch this field!!!!</span></span>
<span class="line" id="L283"><span class="tok-comment">/// this is part of the hack.</span></span>
<span class="line" id="L284">_is_finished: *<span class="tok-type">bool</span> = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L285"></span>
<span class="line" id="L286"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> UserContext = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L287"> user_context: ?*<span class="tok-type">anyopaque</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L288">};</span>
<span class="line" id="L289"></span>
<span class="line" id="L290"><span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L291"></span>
<span class="line" id="L292"><span class="tok-comment">/// mark the current request as finished. Important for middleware-style</span></span>
<span class="line" id="L293"><span class="tok-comment">/// request handler chaining. Called when sending a body, redirecting, etc.</span></span>
<span class="line" id="L294"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">markAsFinished</span>(self: *<span class="tok-kw">const</span> Self, finished: <span class="tok-type">bool</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L295"> <span class="tok-comment">// we might be a copy</span>
</span>
<span class="line" id="L296"> self._is_finished.* = finished;</span>
<span class="line" id="L297">}</span>
<span class="line" id="L298"></span>
<span class="line" id="L299"><span class="tok-comment">/// tell whether request processing has finished. (e.g. response sent,</span></span>
<span class="line" id="L300"><span class="tok-comment">/// redirected, ...)</span></span>
<span class="line" id="L301"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isFinished</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L302"> <span class="tok-comment">// we might be a copy</span>
</span>
<span class="line" id="L303"> <span class="tok-kw">return</span> self._is_finished.*;</span>
<span class="line" id="L304">}</span>
<span class="line" id="L305"></span>
<span class="line" id="L306"><span class="tok-comment">/// if you absolutely must, you can set any context on the request here</span></span>
<span class="line" id="L307"><span class="tok-comment">// (note, this line is linked to from the readme) -- TODO: sync</span>
</span>
<span class="line" id="L308"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setUserContext</span>(self: *<span class="tok-kw">const</span> Self, context: *<span class="tok-type">anyopaque</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L309"> self._user_context.*.user_context = context;</span>
<span class="line" id="L310">}</span>
<span class="line" id="L311"></span>
<span class="line" id="L312"><span class="tok-comment">/// get the associated user context of the request.</span></span>
<span class="line" id="L313"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getUserContext</span>(self: *<span class="tok-kw">const</span> Self, <span class="tok-kw">comptime</span> Context: <span class="tok-type">type</span>) ?*Context {</span>
<span class="line" id="L314"> <span class="tok-kw">if</span> (self._user_context.*.user_context) |ptr| {</span>
<span class="line" id="L315"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(*Context, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(ptr)));</span>
<span class="line" id="L316"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L317"> <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L318"> }</span>
<span class="line" id="L319">}</span>
<span class="line" id="L320"></span>
<span class="line" id="L321"><span class="tok-comment">/// Tries to send an error stack trace.</span></span>
<span class="line" id="L322"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">sendError</span>(self: *<span class="tok-kw">const</span> Self, err: <span class="tok-type">anyerror</span>, errorcode_num: <span class="tok-type">usize</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L323"> <span class="tok-comment">// TODO: query accept headers</span>
</span>
<span class="line" id="L324"> <span class="tok-kw">if</span> (self._internal_sendError(err, errorcode_num)) {</span>
<span class="line" id="L325"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L326"> } <span class="tok-kw">else</span> |_| {</span>
<span class="line" id="L327"> self.sendBody(<span class="tok-builtin">@errorName</span>(err)) <span class="tok-kw">catch</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L328"> }</span>
<span class="line" id="L329">}</span>
<span class="line" id="L330"></span>
<span class="line" id="L331"><span class="tok-comment">/// Used internally. Probably does not need to be public.</span></span>
<span class="line" id="L332"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">_internal_sendError</span>(self: *<span class="tok-kw">const</span> Self, err: <span class="tok-type">anyerror</span>, errorcode_num: <span class="tok-type">usize</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L333"> <span class="tok-comment">// TODO: query accept headers</span>
</span>
<span class="line" id="L334"> <span class="tok-comment">// TODO: let's hope 20k is enough. Maybe just really allocate here</span>
</span>
<span class="line" id="L335"> self.h.*.status = errorcode_num;</span>
<span class="line" id="L336"> <span class="tok-kw">var</span> buf: [<span class="tok-number">20</span> * <span class="tok-number">1024</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L337"> <span class="tok-kw">var</span> fba = std.heap.FixedBufferAllocator.init(&amp;buf);</span>
<span class="line" id="L338"> <span class="tok-kw">var</span> string = std.ArrayList(<span class="tok-type">u8</span>).init(fba.allocator());</span>
<span class="line" id="L339"> <span class="tok-kw">var</span> writer = string.writer();</span>
<span class="line" id="L340"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;ERROR: {any}\n\n&quot;</span>, .{err});</span>
<span class="line" id="L341"></span>
<span class="line" id="L342"> <span class="tok-kw">const</span> debugInfo = <span class="tok-kw">try</span> std.debug.getSelfDebugInfo();</span>
<span class="line" id="L343"> <span class="tok-kw">const</span> ttyConfig: std.io.tty.Config = .no_color;</span>
<span class="line" id="L344"> <span class="tok-kw">try</span> std.debug.writeCurrentStackTrace(writer, debugInfo, ttyConfig, <span class="tok-null">null</span>);</span>
<span class="line" id="L345"> <span class="tok-kw">try</span> self.sendBody(string.items);</span>
<span class="line" id="L346">}</span>
<span class="line" id="L347"></span>
<span class="line" id="L348"><span class="tok-comment">/// Send body.</span></span>
<span class="line" id="L349"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">sendBody</span>(self: *<span class="tok-kw">const</span> Self, body: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L350"> <span class="tok-kw">const</span> ret = fio.http_send_body(self.h, <span class="tok-builtin">@as</span>(</span>
<span class="line" id="L351"> *<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L352"> <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(body.ptr)),</span>
<span class="line" id="L353"> ), body.len);</span>
<span class="line" id="L354"> zap.debug(<span class="tok-str">&quot;Request.sendBody(): ret = {}\n&quot;</span>, .{ret});</span>
<span class="line" id="L355"> <span class="tok-kw">if</span> (ret == -<span class="tok-number">1</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpSendBody;</span>
<span class="line" id="L356"> self.markAsFinished(<span class="tok-null">true</span>);</span>
<span class="line" id="L357">}</span>
<span class="line" id="L358"></span>
<span class="line" id="L359"><span class="tok-comment">/// Set content type and send json buffer.</span></span>
<span class="line" id="L360"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">sendJson</span>(self: *<span class="tok-kw">const</span> Self, json: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L361"> <span class="tok-kw">if</span> (self.setContentType(.JSON)) {</span>
<span class="line" id="L362"> <span class="tok-kw">if</span> (fio.http_send_body(self.h, <span class="tok-builtin">@as</span>(</span>
<span class="line" id="L363"> *<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L364"> <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(json.ptr)),</span>
<span class="line" id="L365"> ), json.len) != <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpSendBody;</span>
<span class="line" id="L366"> self.markAsFinished(<span class="tok-null">true</span>);</span>
<span class="line" id="L367"> } <span class="tok-kw">else</span> |err| <span class="tok-kw">return</span> err;</span>
<span class="line" id="L368">}</span>
<span class="line" id="L369"></span>
<span class="line" id="L370"><span class="tok-comment">/// Set content type.</span></span>
<span class="line" id="L371"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setContentType</span>(self: *<span class="tok-kw">const</span> Self, c: ContentType) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L372"> <span class="tok-kw">const</span> s = <span class="tok-kw">switch</span> (c) {</span>
<span class="line" id="L373"> .TEXT =&gt; <span class="tok-str">&quot;text/plain&quot;</span>,</span>
<span class="line" id="L374"> .JSON =&gt; <span class="tok-str">&quot;application/json&quot;</span>,</span>
<span class="line" id="L375"> <span class="tok-kw">else</span> =&gt; <span class="tok-str">&quot;text/html&quot;</span>,</span>
<span class="line" id="L376"> };</span>
<span class="line" id="L377"> zap.debug(<span class="tok-str">&quot;setting content-type to {s}\n&quot;</span>, .{s});</span>
<span class="line" id="L378"> <span class="tok-kw">return</span> self.setHeader(<span class="tok-str">&quot;content-type&quot;</span>, s);</span>
<span class="line" id="L379">}</span>
<span class="line" id="L380"></span>
<span class="line" id="L381"><span class="tok-comment">/// redirect to path with status code 302 by default</span></span>
<span class="line" id="L382"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">redirectTo</span>(self: *<span class="tok-kw">const</span> Self, path: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, code: ?http.StatusCode) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L383"> self.setStatus(<span class="tok-kw">if</span> (code) |status| status <span class="tok-kw">else</span> .found);</span>
<span class="line" id="L384"> <span class="tok-kw">try</span> self.setHeader(<span class="tok-str">&quot;Location&quot;</span>, path);</span>
<span class="line" id="L385"> <span class="tok-kw">try</span> self.sendBody(<span class="tok-str">&quot;moved&quot;</span>);</span>
<span class="line" id="L386"> self.markAsFinished(<span class="tok-null">true</span>);</span>
<span class="line" id="L387">}</span>
<span class="line" id="L388"></span>
<span class="line" id="L389"><span class="tok-comment">/// shows how to use the logger</span></span>
<span class="line" id="L390"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setContentTypeWithLogger</span>(</span>
<span class="line" id="L391"> self: *<span class="tok-kw">const</span> Self,</span>
<span class="line" id="L392"> c: ContentType,</span>
<span class="line" id="L393"> logger: *<span class="tok-kw">const</span> Log,</span>
<span class="line" id="L394">) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L395"> <span class="tok-kw">const</span> s = <span class="tok-kw">switch</span> (c) {</span>
<span class="line" id="L396"> .TEXT =&gt; <span class="tok-str">&quot;text/plain&quot;</span>,</span>
<span class="line" id="L397"> .JSON =&gt; <span class="tok-str">&quot;application/json&quot;</span>,</span>
<span class="line" id="L398"> <span class="tok-kw">else</span> =&gt; <span class="tok-str">&quot;text/html&quot;</span>,</span>
<span class="line" id="L399"> };</span>
<span class="line" id="L400"> logger.log(<span class="tok-str">&quot;setting content-type to {s}\n&quot;</span>, .{s});</span>
<span class="line" id="L401"> <span class="tok-kw">return</span> self.setHeader(<span class="tok-str">&quot;content-type&quot;</span>, s);</span>
<span class="line" id="L402">}</span>
<span class="line" id="L403"></span>
<span class="line" id="L404"><span class="tok-comment">/// Tries to determine the content type by file extension of request path, and sets it.</span></span>
<span class="line" id="L405"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setContentTypeFromPath</span>(self: *<span class="tok-kw">const</span> Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L406"> <span class="tok-kw">const</span> t = fio.http_mimetype_find2(self.h.*.path);</span>
<span class="line" id="L407"> <span class="tok-kw">if</span> (fio.is_invalid(t) == <span class="tok-number">1</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpSetContentType;</span>
<span class="line" id="L408"> <span class="tok-kw">const</span> ret = fio.fiobj_hash_set(</span>
<span class="line" id="L409"> self.h.*.private_data.out_headers,</span>
<span class="line" id="L410"> fio.HTTP_HEADER_CONTENT_TYPE,</span>
<span class="line" id="L411"> t,</span>
<span class="line" id="L412"> );</span>
<span class="line" id="L413"> <span class="tok-kw">if</span> (ret == -<span class="tok-number">1</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpSetContentType;</span>
<span class="line" id="L414">}</span>
<span class="line" id="L415"></span>
<span class="line" id="L416"><span class="tok-comment">/// Tries to determine the content type by filename extension, and sets it.</span></span>
<span class="line" id="L417"><span class="tok-comment">/// If the extension cannot be determined, NoExtensionInFilename error is</span></span>
<span class="line" id="L418"><span class="tok-comment">/// returned.</span></span>
<span class="line" id="L419"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setContentTypeFromFilename</span>(self: *<span class="tok-kw">const</span> Self, filename: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L420"> <span class="tok-kw">const</span> ext = std.fs.path.extension(filename);</span>
<span class="line" id="L421"></span>
<span class="line" id="L422"> <span class="tok-kw">if</span> (ext.len &gt; <span class="tok-number">1</span>) {</span>
<span class="line" id="L423"> <span class="tok-kw">const</span> e = ext[<span class="tok-number">1</span>..];</span>
<span class="line" id="L424"> <span class="tok-kw">const</span> obj = fio.http_mimetype_find(<span class="tok-builtin">@constCast</span>(e.ptr), e.len);</span>
<span class="line" id="L425"></span>
<span class="line" id="L426"> <span class="tok-kw">if</span> (util.fio2str(obj)) |mime_str| {</span>
<span class="line" id="L427"> <span class="tok-kw">try</span> self.setHeader(<span class="tok-str">&quot;content-type&quot;</span>, mime_str);</span>
<span class="line" id="L428"> }</span>
<span class="line" id="L429"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L430"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.NoExtensionInFilename;</span>
<span class="line" id="L431"> }</span>
<span class="line" id="L432">}</span>
<span class="line" id="L433"></span>
<span class="line" id="L434"><span class="tok-comment">/// Returns the header value of given key name. Returned mem is temp.</span></span>
<span class="line" id="L435"><span class="tok-comment">/// Do not free it.</span></span>
<span class="line" id="L436"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getHeader</span>(self: *<span class="tok-kw">const</span> Self, name: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L437"> <span class="tok-kw">const</span> hname = fio.fiobj_str_new(util.toCharPtr(name), name.len);</span>
<span class="line" id="L438"> <span class="tok-kw">defer</span> fio.fiobj_free_wrapped(hname);</span>
<span class="line" id="L439"> <span class="tok-kw">return</span> util.fio2str(fio.fiobj_hash_get(self.h.*.headers, hname));</span>
<span class="line" id="L440">}</span>
<span class="line" id="L441"></span>
<span class="line" id="L442"><span class="tok-comment">/// Set header.</span></span>
<span class="line" id="L443"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setHeader</span>(self: *<span class="tok-kw">const</span> Self, name: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, value: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L444"> <span class="tok-kw">const</span> hname: fio.fio_str_info_s = .{</span>
<span class="line" id="L445"> .data = util.toCharPtr(name),</span>
<span class="line" id="L446"> .len = name.len,</span>
<span class="line" id="L447"> .capa = name.len,</span>
<span class="line" id="L448"> };</span>
<span class="line" id="L449"></span>
<span class="line" id="L450"> zap.debug(<span class="tok-str">&quot;setHeader: hname = {s}\n&quot;</span>, .{name});</span>
<span class="line" id="L451"> <span class="tok-kw">const</span> vname: fio.fio_str_info_s = .{</span>
<span class="line" id="L452"> .data = util.toCharPtr(value),</span>
<span class="line" id="L453"> .len = value.len,</span>
<span class="line" id="L454"> .capa = value.len,</span>
<span class="line" id="L455"> };</span>
<span class="line" id="L456"> zap.debug(<span class="tok-str">&quot;setHeader: vname = {s}\n&quot;</span>, .{value});</span>
<span class="line" id="L457"> <span class="tok-kw">const</span> ret = fio.http_set_header2(self.h, hname, vname);</span>
<span class="line" id="L458"></span>
<span class="line" id="L459"> <span class="tok-comment">// FIXME without the following if, we get errors in release builds</span>
</span>
<span class="line" id="L460"> <span class="tok-comment">// at least we don't have to log unconditionally</span>
</span>
<span class="line" id="L461"> <span class="tok-kw">if</span> (ret == -<span class="tok-number">1</span>) {</span>
<span class="line" id="L462"> std.debug.print(<span class="tok-str">&quot;***************** zap.zig:274\n&quot;</span>, .{});</span>
<span class="line" id="L463"> }</span>
<span class="line" id="L464"> zap.debug(<span class="tok-str">&quot;setHeader: ret = {}\n&quot;</span>, .{ret});</span>
<span class="line" id="L465"></span>
<span class="line" id="L466"> <span class="tok-kw">if</span> (ret == <span class="tok-number">0</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L467"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpSetHeader;</span>
<span class="line" id="L468">}</span>
<span class="line" id="L469"></span>
<span class="line" id="L470"><span class="tok-comment">/// Set status by numeric value.</span></span>
<span class="line" id="L471"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setStatusNumeric</span>(self: *<span class="tok-kw">const</span> Self, status: <span class="tok-type">usize</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L472"> self.h.*.status = status;</span>
<span class="line" id="L473">}</span>
<span class="line" id="L474"></span>
<span class="line" id="L475"><span class="tok-comment">/// Set status by enum.</span></span>
<span class="line" id="L476"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setStatus</span>(self: *<span class="tok-kw">const</span> Self, status: http.StatusCode) <span class="tok-type">void</span> {</span>
<span class="line" id="L477"> self.h.*.status = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@intFromEnum</span>(status)));</span>
<span class="line" id="L478">}</span>
<span class="line" id="L479"></span>
<span class="line" id="L480"><span class="tok-comment">/// Sends a file if present in the filesystem orelse returns an error.</span></span>
<span class="line" id="L481"><span class="tok-comment">///</span></span>
<span class="line" id="L482"><span class="tok-comment">/// - efficiently sends a file using gzip compression</span></span>
<span class="line" id="L483"><span class="tok-comment">/// - also handles range requests if `Range` or `If-Range` headers are present in the request.</span></span>
<span class="line" id="L484"><span class="tok-comment">/// - sends the response headers and the specified file (the response's body).</span></span>
<span class="line" id="L485"><span class="tok-comment">///</span></span>
<span class="line" id="L486"><span class="tok-comment">/// On success, the `self.h` handle will be consumed and invalid.</span></span>
<span class="line" id="L487"><span class="tok-comment">/// On error, the handle will still be valid and should be used to send an error response</span></span>
<span class="line" id="L488"><span class="tok-comment">///</span></span>
<span class="line" id="L489"><span class="tok-comment">/// Important: sets last-modified and cache-control headers with a max-age value of 1 hour!</span></span>
<span class="line" id="L490"><span class="tok-comment">/// You can override that by setting those headers yourself, e.g.: setHeader(&quot;Cache-Control&quot;, &quot;no-cache&quot;)</span></span>
<span class="line" id="L491"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">sendFile</span>(self: *<span class="tok-kw">const</span> Self, file_path: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L492"> <span class="tok-kw">if</span> (fio.http_sendfile2(self.h, util.toCharPtr(file_path), file_path.len, <span class="tok-null">null</span>, <span class="tok-number">0</span>) != <span class="tok-number">0</span>)</span>
<span class="line" id="L493"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.SendFile;</span>
<span class="line" id="L494"> self.markAsFinished(<span class="tok-null">true</span>);</span>
<span class="line" id="L495">}</span>
<span class="line" id="L496"></span>
<span class="line" id="L497"><span class="tok-comment">/// Attempts to decode the request's body.</span></span>
<span class="line" id="L498"><span class="tok-comment">/// This should be called BEFORE parseQuery</span></span>
<span class="line" id="L499"><span class="tok-comment">/// Result is accessible via parametersToOwnedSlice(), parametersToOwnedStrSlice()</span></span>
<span class="line" id="L500"><span class="tok-comment">///</span></span>
<span class="line" id="L501"><span class="tok-comment">/// Supported body types:</span></span>
<span class="line" id="L502"><span class="tok-comment">/// - application/x-www-form-urlencoded</span></span>
<span class="line" id="L503"><span class="tok-comment">/// - application/json</span></span>
<span class="line" id="L504"><span class="tok-comment">/// - multipart/form-data</span></span>
<span class="line" id="L505"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">parseBody</span>(self: *<span class="tok-kw">const</span> Self) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L506"> <span class="tok-kw">if</span> (fio.http_parse_body(self.h) == -<span class="tok-number">1</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpParseBody;</span>
<span class="line" id="L507">}</span>
<span class="line" id="L508"></span>
<span class="line" id="L509"><span class="tok-comment">/// Parses the query part of an HTTP request</span></span>
<span class="line" id="L510"><span class="tok-comment">/// This should be called AFTER parseBody(), just in case the body is a JSON</span></span>
<span class="line" id="L511"><span class="tok-comment">/// object that doesn't have a hash map at its root.</span></span>
<span class="line" id="L512"><span class="tok-comment">///</span></span>
<span class="line" id="L513"><span class="tok-comment">/// Result is accessible via parametersToOwnedSlice(), parametersToOwnedStrSlice()</span></span>
<span class="line" id="L514"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">parseQuery</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L515"> fio.http_parse_query(self.h);</span>
<span class="line" id="L516">}</span>
<span class="line" id="L517"></span>
<span class="line" id="L518"><span class="tok-comment">/// Parse received cookie headers</span></span>
<span class="line" id="L519"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">parseCookies</span>(self: *<span class="tok-kw">const</span> Self, url_encoded: <span class="tok-type">bool</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L520"> fio.http_parse_cookies(self.h, <span class="tok-kw">if</span> (url_encoded) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>);</span>
<span class="line" id="L521">}</span>
<span class="line" id="L522"></span>
<span class="line" id="L523"><span class="tok-comment">/// Set a response cookie</span></span>
<span class="line" id="L524"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setCookie</span>(self: *<span class="tok-kw">const</span> Self, args: CookieArgs) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L525"> <span class="tok-kw">const</span> c: fio.http_cookie_args_s = .{</span>
<span class="line" id="L526"> .name = util.toCharPtr(args.name),</span>
<span class="line" id="L527"> .name_len = <span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@intCast</span>(args.name.len)),</span>
<span class="line" id="L528"> .value = util.toCharPtr(args.value),</span>
<span class="line" id="L529"> .value_len = <span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@intCast</span>(args.value.len)),</span>
<span class="line" id="L530"> .domain = <span class="tok-kw">if</span> (args.domain) |p| util.toCharPtr(p) <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L531"> .domain_len = <span class="tok-kw">if</span> (args.domain) |p| <span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@intCast</span>(p.len)) <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L532"> .path = <span class="tok-kw">if</span> (args.path) |p| util.toCharPtr(p) <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L533"> .path_len = <span class="tok-kw">if</span> (args.path) |p| <span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@intCast</span>(p.len)) <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L534"> .max_age = args.max_age_s,</span>
<span class="line" id="L535"> .secure = <span class="tok-kw">if</span> (args.secure) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L536"> .http_only = <span class="tok-kw">if</span> (args.http_only) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L537"> };</span>
<span class="line" id="L538"></span>
<span class="line" id="L539"> <span class="tok-comment">// TODO WAT?</span>
</span>
<span class="line" id="L540"> <span class="tok-comment">// if we:</span>
</span>
<span class="line" id="L541"> <span class="tok-comment">// if(fio.http_set_cookie(...) == -1)</span>
</span>
<span class="line" id="L542"> <span class="tok-comment">// instead of capturing it in `ret` first and then checking it,</span>
</span>
<span class="line" id="L543"> <span class="tok-comment">// all ReleaseXXX builds return an error!</span>
</span>
<span class="line" id="L544"> <span class="tok-comment">// TODO: still happening?</span>
</span>
<span class="line" id="L545"> <span class="tok-kw">const</span> ret = fio.http_set_cookie(self.h, c);</span>
<span class="line" id="L546"> <span class="tok-kw">if</span> (ret == -<span class="tok-number">1</span>) {</span>
<span class="line" id="L547"> std.log.err(<span class="tok-str">&quot;fio.http_set_cookie returned: {}\n&quot;</span>, .{ret});</span>
<span class="line" id="L548"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.SetCookie;</span>
<span class="line" id="L549"> }</span>
<span class="line" id="L550">}</span>
<span class="line" id="L551"></span>
<span class="line" id="L552"><span class="tok-comment">/// Returns named cookie. Works like getParamStr().</span></span>
<span class="line" id="L553"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getCookieStr</span>(self: *<span class="tok-kw">const</span> Self, a: std.mem.Allocator, name: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, always_alloc: <span class="tok-type">bool</span>) !?util.FreeOrNot {</span>
<span class="line" id="L554"> <span class="tok-kw">if</span> (self.h.*.cookies == <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L555"> <span class="tok-kw">const</span> key = fio.fiobj_str_new(name.ptr, name.len);</span>
<span class="line" id="L556"> <span class="tok-kw">defer</span> fio.fiobj_free_wrapped(key);</span>
<span class="line" id="L557"> <span class="tok-kw">const</span> value = fio.fiobj_hash_get(self.h.*.cookies, key);</span>
<span class="line" id="L558"> <span class="tok-kw">if</span> (value == fio.FIOBJ_INVALID) {</span>
<span class="line" id="L559"> <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L560"> }</span>
<span class="line" id="L561"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> util.fio2strAllocOrNot(a, value, always_alloc);</span>
<span class="line" id="L562">}</span>
<span class="line" id="L563"></span>
<span class="line" id="L564"><span class="tok-comment">/// Returns the number of cookies after parsing.</span></span>
<span class="line" id="L565"><span class="tok-comment">///</span></span>
<span class="line" id="L566"><span class="tok-comment">/// Parse with parseCookies()</span></span>
<span class="line" id="L567"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getCookiesCount</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">isize</span> {</span>
<span class="line" id="L568"> <span class="tok-kw">if</span> (self.h.*.cookies == <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L569"> <span class="tok-kw">return</span> fio.fiobj_obj2num(self.h.*.cookies);</span>
<span class="line" id="L570">}</span>
<span class="line" id="L571"></span>
<span class="line" id="L572"><span class="tok-comment">/// Returns the number of parameters after parsing.</span></span>
<span class="line" id="L573"><span class="tok-comment">///</span></span>
<span class="line" id="L574"><span class="tok-comment">/// Parse with parseBody() and / or parseQuery()</span></span>
<span class="line" id="L575"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getParamCount</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">isize</span> {</span>
<span class="line" id="L576"> <span class="tok-kw">if</span> (self.h.*.params == <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L577"> <span class="tok-kw">return</span> fio.fiobj_obj2num(self.h.*.params);</span>
<span class="line" id="L578">}</span>
<span class="line" id="L579"></span>
<span class="line" id="L580"><span class="tok-comment">/// Same as parametersToOwnedStrList() but for cookies</span></span>
<span class="line" id="L581"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">cookiesToOwnedStrList</span>(self: *<span class="tok-kw">const</span> Self, a: std.mem.Allocator, always_alloc: <span class="tok-type">bool</span>) <span class="tok-type">anyerror</span>!HttpParamStrKVList {</span>
<span class="line" id="L582"> <span class="tok-kw">var</span> params = <span class="tok-kw">try</span> std.ArrayList(HttpParamStrKV).initCapacity(a, <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(self.getCookiesCount())));</span>
<span class="line" id="L583"> <span class="tok-kw">var</span> context: _parametersToOwnedStrSliceContext = .{</span>
<span class="line" id="L584"> .params = &amp;params,</span>
<span class="line" id="L585"> .allocator = a,</span>
<span class="line" id="L586"> .always_alloc = always_alloc,</span>
<span class="line" id="L587"> };</span>
<span class="line" id="L588"> <span class="tok-kw">const</span> howmany = fio.fiobj_each1(self.h.*.cookies, <span class="tok-number">0</span>, _each_nextParamStr, &amp;context);</span>
<span class="line" id="L589"> <span class="tok-kw">if</span> (howmany != self.getCookiesCount()) {</span>
<span class="line" id="L590"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpIterParams;</span>
<span class="line" id="L591"> }</span>
<span class="line" id="L592"> <span class="tok-kw">return</span> .{ .items = <span class="tok-kw">try</span> params.toOwnedSlice(), .allocator = a };</span>
<span class="line" id="L593">}</span>
<span class="line" id="L594"></span>
<span class="line" id="L595"><span class="tok-comment">/// Same as parametersToOwnedList() but for cookies</span></span>
<span class="line" id="L596"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">cookiesToOwnedList</span>(self: *<span class="tok-kw">const</span> Self, a: std.mem.Allocator, dupe_strings: <span class="tok-type">bool</span>) !HttpParamKVList {</span>
<span class="line" id="L597"> <span class="tok-kw">var</span> params = <span class="tok-kw">try</span> std.ArrayList(HttpParamKV).initCapacity(a, <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(self.getCookiesCount())));</span>
<span class="line" id="L598"> <span class="tok-kw">var</span> context: _parametersToOwnedSliceContext = .{ .params = &amp;params, .allocator = a, .dupe_strings = dupe_strings };</span>
<span class="line" id="L599"> <span class="tok-kw">const</span> howmany = fio.fiobj_each1(self.h.*.cookies, <span class="tok-number">0</span>, _each_nextParam, &amp;context);</span>
<span class="line" id="L600"> <span class="tok-kw">if</span> (howmany != self.getCookiesCount()) {</span>
<span class="line" id="L601"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpIterParams;</span>
<span class="line" id="L602"> }</span>
<span class="line" id="L603"> <span class="tok-kw">return</span> .{ .items = <span class="tok-kw">try</span> params.toOwnedSlice(), .allocator = a };</span>
<span class="line" id="L604">}</span>
<span class="line" id="L605"></span>
<span class="line" id="L606"><span class="tok-comment">/// Returns the query / body parameters as key/value pairs, as strings.</span></span>
<span class="line" id="L607"><span class="tok-comment">/// Supported param types that will be converted:</span></span>
<span class="line" id="L608"><span class="tok-comment">///</span></span>
<span class="line" id="L609"><span class="tok-comment">/// - Bool</span></span>
<span class="line" id="L610"><span class="tok-comment">/// - Int</span></span>
<span class="line" id="L611"><span class="tok-comment">/// - Float</span></span>
<span class="line" id="L612"><span class="tok-comment">/// - String</span></span>
<span class="line" id="L613"><span class="tok-comment">///</span></span>
<span class="line" id="L614"><span class="tok-comment">/// At the moment, no fio ARRAYs are supported as well as HASH maps.</span></span>
<span class="line" id="L615"><span class="tok-comment">/// So, for JSON body payloads: parse the body instead.</span></span>
<span class="line" id="L616"><span class="tok-comment">///</span></span>
<span class="line" id="L617"><span class="tok-comment">/// Requires parseBody() and/or parseQuery() have been called.</span></span>
<span class="line" id="L618"><span class="tok-comment">/// Returned list needs to be deinited.</span></span>
<span class="line" id="L619"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">parametersToOwnedStrList</span>(self: *<span class="tok-kw">const</span> Self, a: std.mem.Allocator, always_alloc: <span class="tok-type">bool</span>) <span class="tok-type">anyerror</span>!HttpParamStrKVList {</span>
<span class="line" id="L620"> <span class="tok-kw">var</span> params = <span class="tok-kw">try</span> std.ArrayList(HttpParamStrKV).initCapacity(a, <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(self.getParamCount())));</span>
<span class="line" id="L621"> <span class="tok-kw">var</span> context: _parametersToOwnedStrSliceContext = .{</span>
<span class="line" id="L622"> .params = &amp;params,</span>
<span class="line" id="L623"> .allocator = a,</span>
<span class="line" id="L624"> .always_alloc = always_alloc,</span>
<span class="line" id="L625"> };</span>
<span class="line" id="L626"> <span class="tok-kw">const</span> howmany = fio.fiobj_each1(self.h.*.params, <span class="tok-number">0</span>, _each_nextParamStr, &amp;context);</span>
<span class="line" id="L627"> <span class="tok-kw">if</span> (howmany != self.getParamCount()) {</span>
<span class="line" id="L628"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpIterParams;</span>
<span class="line" id="L629"> }</span>
<span class="line" id="L630"> <span class="tok-kw">return</span> .{ .items = <span class="tok-kw">try</span> params.toOwnedSlice(), .allocator = a };</span>
<span class="line" id="L631">}</span>
<span class="line" id="L632"></span>
<span class="line" id="L633"><span class="tok-kw">const</span> _parametersToOwnedStrSliceContext = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L634"> allocator: std.mem.Allocator,</span>
<span class="line" id="L635"> params: *std.ArrayList(HttpParamStrKV),</span>
<span class="line" id="L636"> last_error: ?<span class="tok-type">anyerror</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L637"> always_alloc: <span class="tok-type">bool</span>,</span>
<span class="line" id="L638">};</span>
<span class="line" id="L639"></span>
<span class="line" id="L640"><span class="tok-kw">fn</span> <span class="tok-fn">_each_nextParamStr</span>(fiobj_value: fio.FIOBJ, context: ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">c_int</span> {</span>
<span class="line" id="L641"> <span class="tok-kw">const</span> ctx: *_parametersToOwnedStrSliceContext = <span class="tok-builtin">@as</span>(*_parametersToOwnedStrSliceContext, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(context)));</span>
<span class="line" id="L642"> <span class="tok-comment">// this is thread-safe, guaranteed by fio</span>
</span>
<span class="line" id="L643"> <span class="tok-kw">const</span> fiobj_key: fio.FIOBJ = fio.fiobj_hash_key_in_loop();</span>
<span class="line" id="L644"> ctx.params.append(.{</span>
<span class="line" id="L645"> .key = util.fio2strAllocOrNot(ctx.allocator, fiobj_key, ctx.always_alloc) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L646"> ctx.last_error = err;</span>
<span class="line" id="L647"> <span class="tok-kw">return</span> -<span class="tok-number">1</span>;</span>
<span class="line" id="L648"> },</span>
<span class="line" id="L649"> .value = util.fio2strAllocOrNot(ctx.allocator, fiobj_value, ctx.always_alloc) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L650"> ctx.last_error = err;</span>
<span class="line" id="L651"> <span class="tok-kw">return</span> -<span class="tok-number">1</span>;</span>
<span class="line" id="L652"> },</span>
<span class="line" id="L653"> }) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L654"> <span class="tok-comment">// what to do?</span>
</span>
<span class="line" id="L655"> <span class="tok-comment">// signal the caller that an error occured by returning -1</span>
</span>
<span class="line" id="L656"> <span class="tok-comment">// also, set the error</span>
</span>
<span class="line" id="L657"> ctx.last_error = err;</span>
<span class="line" id="L658"> <span class="tok-kw">return</span> -<span class="tok-number">1</span>;</span>
<span class="line" id="L659"> };</span>
<span class="line" id="L660"> <span class="tok-kw">return</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L661">}</span>
<span class="line" id="L662"></span>
<span class="line" id="L663"><span class="tok-comment">/// Returns the query / body parameters as key/value pairs</span></span>
<span class="line" id="L664"><span class="tok-comment">/// Supported param types that will be converted:</span></span>
<span class="line" id="L665"><span class="tok-comment">///</span></span>
<span class="line" id="L666"><span class="tok-comment">/// - Bool</span></span>
<span class="line" id="L667"><span class="tok-comment">/// - Int</span></span>
<span class="line" id="L668"><span class="tok-comment">/// - Float</span></span>
<span class="line" id="L669"><span class="tok-comment">/// - String</span></span>
<span class="line" id="L670"><span class="tok-comment">///</span></span>
<span class="line" id="L671"><span class="tok-comment">/// At the moment, no fio ARRAYs are supported as well as HASH maps.</span></span>
<span class="line" id="L672"><span class="tok-comment">/// So, for JSON body payloads: parse the body instead.</span></span>
<span class="line" id="L673"><span class="tok-comment">///</span></span>
<span class="line" id="L674"><span class="tok-comment">/// Requires parseBody() and/or parseQuery() have been called.</span></span>
<span class="line" id="L675"><span class="tok-comment">/// Returned slice needs to be freed.</span></span>
<span class="line" id="L676"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">parametersToOwnedList</span>(self: *<span class="tok-kw">const</span> Self, a: std.mem.Allocator, dupe_strings: <span class="tok-type">bool</span>) !HttpParamKVList {</span>
<span class="line" id="L677"> <span class="tok-kw">var</span> params = <span class="tok-kw">try</span> std.ArrayList(HttpParamKV).initCapacity(a, <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(self.getParamCount())));</span>
<span class="line" id="L678"> <span class="tok-kw">var</span> context: _parametersToOwnedSliceContext = .{ .params = &amp;params, .allocator = a, .dupe_strings = dupe_strings };</span>
<span class="line" id="L679"> <span class="tok-kw">const</span> howmany = fio.fiobj_each1(self.h.*.params, <span class="tok-number">0</span>, _each_nextParam, &amp;context);</span>
<span class="line" id="L680"> <span class="tok-kw">if</span> (howmany != self.getParamCount()) {</span>
<span class="line" id="L681"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpIterParams;</span>
<span class="line" id="L682"> }</span>
<span class="line" id="L683"> <span class="tok-kw">return</span> .{ .items = <span class="tok-kw">try</span> params.toOwnedSlice(), .allocator = a };</span>
<span class="line" id="L684">}</span>
<span class="line" id="L685"></span>
<span class="line" id="L686"><span class="tok-kw">const</span> _parametersToOwnedSliceContext = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L687"> params: *std.ArrayList(HttpParamKV),</span>
<span class="line" id="L688"> last_error: ?<span class="tok-type">anyerror</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L689"> allocator: std.mem.Allocator,</span>
<span class="line" id="L690"> dupe_strings: <span class="tok-type">bool</span>,</span>
<span class="line" id="L691">};</span>
<span class="line" id="L692"></span>
<span class="line" id="L693"><span class="tok-kw">fn</span> <span class="tok-fn">_each_nextParam</span>(fiobj_value: fio.FIOBJ, context: ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">c_int</span> {</span>
<span class="line" id="L694"> <span class="tok-kw">const</span> ctx: *_parametersToOwnedSliceContext = <span class="tok-builtin">@as</span>(*_parametersToOwnedSliceContext, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(context)));</span>
<span class="line" id="L695"> <span class="tok-comment">// this is thread-safe, guaranteed by fio</span>
</span>
<span class="line" id="L696"> <span class="tok-kw">const</span> fiobj_key: fio.FIOBJ = fio.fiobj_hash_key_in_loop();</span>
<span class="line" id="L697"> ctx.params.append(.{</span>
<span class="line" id="L698"> .key = util.fio2strAllocOrNot(ctx.allocator, fiobj_key, ctx.dupe_strings) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L699"> ctx.last_error = err;</span>
<span class="line" id="L700"> <span class="tok-kw">return</span> -<span class="tok-number">1</span>;</span>
<span class="line" id="L701"> },</span>
<span class="line" id="L702"> .value = Fiobj2HttpParam(ctx.allocator, fiobj_value, ctx.dupe_strings) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L703"> ctx.last_error = err;</span>
<span class="line" id="L704"> <span class="tok-kw">return</span> -<span class="tok-number">1</span>;</span>
<span class="line" id="L705"> },</span>
<span class="line" id="L706"> }) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L707"> <span class="tok-comment">// what to do?</span>
</span>
<span class="line" id="L708"> <span class="tok-comment">// signal the caller that an error occured by returning -1</span>
</span>
<span class="line" id="L709"> <span class="tok-comment">// also, set the error</span>
</span>
<span class="line" id="L710"> ctx.last_error = err;</span>
<span class="line" id="L711"> <span class="tok-kw">return</span> -<span class="tok-number">1</span>;</span>
<span class="line" id="L712"> };</span>
<span class="line" id="L713"> <span class="tok-kw">return</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L714">}</span>
<span class="line" id="L715"></span>
<span class="line" id="L716"><span class="tok-comment">/// get named parameter as string</span></span>
<span class="line" id="L717"><span class="tok-comment">/// Supported param types that will be converted:</span></span>
<span class="line" id="L718"><span class="tok-comment">///</span></span>
<span class="line" id="L719"><span class="tok-comment">/// - Bool</span></span>
<span class="line" id="L720"><span class="tok-comment">/// - Int</span></span>
<span class="line" id="L721"><span class="tok-comment">/// - Float</span></span>
<span class="line" id="L722"><span class="tok-comment">/// - String</span></span>
<span class="line" id="L723"><span class="tok-comment">///</span></span>
<span class="line" id="L724"><span class="tok-comment">/// At the moment, no fio ARRAYs are supported as well as HASH maps.</span></span>
<span class="line" id="L725"><span class="tok-comment">/// So, for JSON body payloads: parse the body instead.</span></span>
<span class="line" id="L726"><span class="tok-comment">///</span></span>
<span class="line" id="L727"><span class="tok-comment">/// Requires parseBody() and/or parseQuery() have been called.</span></span>
<span class="line" id="L728"><span class="tok-comment">/// The returned string needs to be deinited with .deinit()</span></span>
<span class="line" id="L729"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getParamStr</span>(self: *<span class="tok-kw">const</span> Self, a: std.mem.Allocator, name: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, always_alloc: <span class="tok-type">bool</span>) !?util.FreeOrNot {</span>
<span class="line" id="L730"> <span class="tok-kw">if</span> (self.h.*.params == <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L731"> <span class="tok-kw">const</span> key = fio.fiobj_str_new(name.ptr, name.len);</span>
<span class="line" id="L732"> <span class="tok-kw">defer</span> fio.fiobj_free_wrapped(key);</span>
<span class="line" id="L733"> <span class="tok-kw">const</span> value = fio.fiobj_hash_get(self.h.*.params, key);</span>
<span class="line" id="L734"> <span class="tok-kw">if</span> (value == fio.FIOBJ_INVALID) {</span>
<span class="line" id="L735"> <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L736"> }</span>
<span class="line" id="L737"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> util.fio2strAllocOrNot(a, value, always_alloc);</span>
<span class="line" id="L738">}</span>
<span class="line" id="L739"></span>
</code></pre></body>
</html>

202
docs/src/zap/tls.zig.html Normal file
View file

@ -0,0 +1,202 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>tls.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> fio = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;fio.zig&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-comment">/// Server-Side TLS function wrapper</span></span>
<span class="line" id="L4"><span class="tok-kw">const</span> Tls = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L5"></span>
<span class="line" id="L6">fio_tls: ?*<span class="tok-type">anyopaque</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">/// TLS settings used in init() and addCertificate()</span></span>
<span class="line" id="L9"><span class="tok-comment">/// If all values are NULL, a TLS object wll be created without a</span></span>
<span class="line" id="L10"><span class="tok-comment">/// certificate. This could be used for clients together with Tls.trust().</span></span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> TlsSettings = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L12"> <span class="tok-comment">/// If a server name is provided, then NULL values _can_ be used to create an anonymous (unverified)</span></span>
<span class="line" id="L13"> <span class="tok-comment">/// context / settings object.</span></span>
<span class="line" id="L14"> server_name: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L15"> public_certificate_file: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L16"> private_key_file: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L17"> <span class="tok-comment">/// The private_key_password can be NULL if the private key PEM file isn't password protected.</span></span>
<span class="line" id="L18"> private_key_password: ?[*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L19">};</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"><span class="tok-comment">/// Creates a new SSL/TLS context / settings object with a default certificate (if any).</span></span>
<span class="line" id="L22"><span class="tok-comment">/// If a server name is provided, then NULL values can be used to create an anonymous (unverified)</span></span>
<span class="line" id="L23"><span class="tok-comment">/// context / settings object. If all values are NULL, a TLS object will be created without a</span></span>
<span class="line" id="L24"><span class="tok-comment">/// certificate. This could be used for clients together with Tls.trust().</span></span>
<span class="line" id="L25"><span class="tok-comment">/// The private_key_password can be NULL if the private key PEM file isn't password protected.</span></span>
<span class="line" id="L26"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(settings: TlsSettings) !Tls {</span>
<span class="line" id="L27"> <span class="tok-kw">const</span> ret = fio.fio_tls_new(</span>
<span class="line" id="L28"> settings.server_name,</span>
<span class="line" id="L29"> settings.public_certificate_file,</span>
<span class="line" id="L30"> settings.private_key_file,</span>
<span class="line" id="L31"> settings.private_key_password,</span>
<span class="line" id="L32"> );</span>
<span class="line" id="L33"> <span class="tok-kw">if</span> (ret == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.FileNotFound;</span>
<span class="line" id="L34"> <span class="tok-kw">return</span> Tls{ .fio_tls = ret };</span>
<span class="line" id="L35">}</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"><span class="tok-comment">/// Destroys the SSL/TLS context / settings object and frees any related resources / memory.</span></span>
<span class="line" id="L38"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(tls: *<span class="tok-kw">const</span> Tls) <span class="tok-type">void</span> {</span>
<span class="line" id="L39"> fio.fio_tls_destroy(tls.fio_tls);</span>
<span class="line" id="L40">}</span>
<span class="line" id="L41"></span>
<span class="line" id="L42"><span class="tok-comment">// pub fn incRefCount(tls: *Tls) !void {</span>
</span>
<span class="line" id="L43"><span class="tok-comment">// if (tls.fio_tls == null) {</span>
</span>
<span class="line" id="L44"><span class="tok-comment">// return error.Uninitialized;</span>
</span>
<span class="line" id="L45"><span class="tok-comment">// }</span>
</span>
<span class="line" id="L46"><span class="tok-comment">// fio.fio_tls_dup(tls.fio_tls);</span>
</span>
<span class="line" id="L47"><span class="tok-comment">// }</span>
</span>
<span class="line" id="L48"></span>
<span class="line" id="L49"><span class="tok-comment">/// Adds a certificate a new SSL/TLS context / settings object (SNI support).</span></span>
<span class="line" id="L50"><span class="tok-comment">/// The private_key_password can be NULL if the private key PEM file isn't password protected.</span></span>
<span class="line" id="L51"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">addCertificate</span>(tls: *Tls, settings: TlsSettings) !<span class="tok-type">void</span> {</span>
<span class="line" id="L52"> <span class="tok-kw">if</span> (tls.fio_tls == <span class="tok-null">null</span>) {</span>
<span class="line" id="L53"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Uninitialized;</span>
<span class="line" id="L54"> }</span>
<span class="line" id="L55"></span>
<span class="line" id="L56"> <span class="tok-kw">const</span> ret = fio.fio_tls_cert_add(</span>
<span class="line" id="L57"> tls.fio_tls,</span>
<span class="line" id="L58"> settings.server_name,</span>
<span class="line" id="L59"> settings.public_certificate_file,</span>
<span class="line" id="L60"> settings.private_key_file,</span>
<span class="line" id="L61"> settings.private_key_password,</span>
<span class="line" id="L62"> );</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"> <span class="tok-kw">if</span> (ret != <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.FileNotFound;</span>
<span class="line" id="L65"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L66">}</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"><span class="tok-comment">/// Adds a certificate to the &quot;trust&quot; list, which automatically adds a peer verification requirement.</span></span>
<span class="line" id="L69"><span class="tok-comment">/// Note: when the fio_tls_s object is used for server connections, this will limit connections to</span></span>
<span class="line" id="L70"><span class="tok-comment">/// clients that connect using a trusted certificate.</span></span>
<span class="line" id="L71"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">trust</span>(tls: *Tls, public_cert_file: [*:<span class="tok-number">0</span>]<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L72"> <span class="tok-kw">if</span> (tls.fio_tls == <span class="tok-null">null</span>) {</span>
<span class="line" id="L73"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Uninitialized;</span>
<span class="line" id="L74"> }</span>
<span class="line" id="L75"></span>
<span class="line" id="L76"> <span class="tok-kw">const</span> ret = fio.fio_tls_trust(tls.fio_tls, public_cert_file);</span>
<span class="line" id="L77"> <span class="tok-kw">if</span> (ret != <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.FileNotFound;</span>
<span class="line" id="L78"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L79">}</span>
<span class="line" id="L80"></span>
</code></pre></body>
</html>

208
docs/src/zap/util.zig.html Normal file
View file

@ -0,0 +1,208 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>util.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> fio = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;fio.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-comment">/// Used internally: convert a FIO object into its string representation.</span></span>
<span class="line" id="L5"><span class="tok-comment">/// note: since this is called from within request functions, we don't make</span></span>
<span class="line" id="L6"><span class="tok-comment">/// copies. Also, we return temp memory from fio. -&gt; don't hold on to it outside</span></span>
<span class="line" id="L7"><span class="tok-comment">/// of a request function. FIO temp memory strings do not need to be freed.</span></span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio2str</span>(o: fio.FIOBJ) ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L9"> <span class="tok-kw">if</span> (o == <span class="tok-number">0</span>) <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L10"> <span class="tok-kw">const</span> x: fio.fio_str_info_s = fio.fiobj_obj2cstr(o);</span>
<span class="line" id="L11"> <span class="tok-kw">if</span> (x.data == <span class="tok-number">0</span>)</span>
<span class="line" id="L12"> <span class="tok-kw">return</span> <span class="tok-null">null</span>; <span class="tok-comment">// TODO: should we return an error? Actually, looking at fiobj_obj2cstr, this is unreachable</span>
</span>
<span class="line" id="L13"> <span class="tok-kw">return</span> x.data[<span class="tok-number">0</span>..x.len];</span>
<span class="line" id="L14">}</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-comment">/// A &quot;string&quot; type used internally that carries a flag whether its buffer needs</span></span>
<span class="line" id="L17"><span class="tok-comment">/// to be freed or not - and honors it in `deinit()`. That way, it's always</span></span>
<span class="line" id="L18"><span class="tok-comment">/// safe to call deinit().</span></span>
<span class="line" id="L19"><span class="tok-comment">/// For instance, slices taken directly from the zap.Request need not be freed.</span></span>
<span class="line" id="L20"><span class="tok-comment">/// But the ad-hoc created string representation of a float parameter must be</span></span>
<span class="line" id="L21"><span class="tok-comment">/// freed after use.</span></span>
<span class="line" id="L22"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FreeOrNot = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L23"> str: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L24"> freeme: <span class="tok-type">bool</span>,</span>
<span class="line" id="L25"> allocator: ?std.mem.Allocator = <span class="tok-null">null</span>,</span>
<span class="line" id="L26"></span>
<span class="line" id="L27"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *<span class="tok-kw">const</span> <span class="tok-builtin">@This</span>()) <span class="tok-type">void</span> {</span>
<span class="line" id="L28"> <span class="tok-kw">if</span> (self.freeme) {</span>
<span class="line" id="L29"> self.allocator.?.free(self.str);</span>
<span class="line" id="L30"> }</span>
<span class="line" id="L31"> }</span>
<span class="line" id="L32">};</span>
<span class="line" id="L33"></span>
<span class="line" id="L34"><span class="tok-comment">/// Used internally: convert a FIO object into its string representation.</span></span>
<span class="line" id="L35"><span class="tok-comment">/// Depending on the type of the object, a buffer will be created. Hence a</span></span>
<span class="line" id="L36"><span class="tok-comment">/// FreeOrNot type is used as the return type.</span></span>
<span class="line" id="L37"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fio2strAllocOrNot</span>(a: std.mem.Allocator, o: fio.FIOBJ, always_alloc: <span class="tok-type">bool</span>) !FreeOrNot {</span>
<span class="line" id="L38"> <span class="tok-kw">if</span> (o == <span class="tok-number">0</span>) <span class="tok-kw">return</span> .{ .str = <span class="tok-str">&quot;null&quot;</span>, .freeme = <span class="tok-null">false</span> };</span>
<span class="line" id="L39"> <span class="tok-kw">if</span> (o == fio.FIOBJ_INVALID) <span class="tok-kw">return</span> .{ .str = <span class="tok-str">&quot;invalid&quot;</span>, .freeme = <span class="tok-null">false</span> };</span>
<span class="line" id="L40"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (fio.fiobj_type(o)) {</span>
<span class="line" id="L41"> fio.FIOBJ_T_TRUE =&gt; .{ .str = <span class="tok-str">&quot;true&quot;</span>, .freeme = <span class="tok-null">false</span> },</span>
<span class="line" id="L42"> fio.FIOBJ_T_FALSE =&gt; .{ .str = <span class="tok-str">&quot;false&quot;</span>, .freeme = <span class="tok-null">false</span> },</span>
<span class="line" id="L43"> <span class="tok-comment">// according to fio2str above, the orelse should never happen</span>
</span>
<span class="line" id="L44"> fio.FIOBJ_T_NUMBER =&gt; .{ .str = <span class="tok-kw">try</span> a.dupe(<span class="tok-type">u8</span>, fio2str(o) <span class="tok-kw">orelse</span> <span class="tok-str">&quot;null&quot;</span>), .freeme = <span class="tok-null">true</span>, .allocator = a },</span>
<span class="line" id="L45"> fio.FIOBJ_T_FLOAT =&gt; .{ .str = <span class="tok-kw">try</span> a.dupe(<span class="tok-type">u8</span>, fio2str(o) <span class="tok-kw">orelse</span> <span class="tok-str">&quot;null&quot;</span>), .freeme = <span class="tok-null">true</span>, .allocator = a },</span>
<span class="line" id="L46"> <span class="tok-comment">// the string comes out of the request, so it is safe to not make a copy</span>
</span>
<span class="line" id="L47"> fio.FIOBJ_T_STRING =&gt; .{ .str = <span class="tok-kw">if</span> (always_alloc) <span class="tok-kw">try</span> a.dupe(<span class="tok-type">u8</span>, fio2str(o) <span class="tok-kw">orelse</span> <span class="tok-str">&quot;&quot;</span>) <span class="tok-kw">else</span> fio2str(o) <span class="tok-kw">orelse</span> <span class="tok-str">&quot;&quot;</span>, .freeme = <span class="tok-kw">if</span> (always_alloc) <span class="tok-null">true</span> <span class="tok-kw">else</span> <span class="tok-null">false</span>, .allocator = a },</span>
<span class="line" id="L48"> <span class="tok-kw">else</span> =&gt; .{ .str = <span class="tok-str">&quot;unknown_type&quot;</span>, .freeme = <span class="tok-null">false</span> },</span>
<span class="line" id="L49"> };</span>
<span class="line" id="L50">}</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-comment">/// Used internally: convert a zig slice into a FIO string.</span></span>
<span class="line" id="L53"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">str2fio</span>(s: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) fio.fio_str_info_s {</span>
<span class="line" id="L54"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L55"> .data = toCharPtr(s),</span>
<span class="line" id="L56"> .len = s.len,</span>
<span class="line" id="L57"> .capa = s.len,</span>
<span class="line" id="L58"> };</span>
<span class="line" id="L59">}</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"><span class="tok-comment">/// Used internally: convert a zig slice into a C pointer</span></span>
<span class="line" id="L62"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">toCharPtr</span>(s: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) [*c]<span class="tok-type">u8</span> {</span>
<span class="line" id="L63"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>([*c]<span class="tok-type">u8</span>, <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(s.ptr)));</span>
<span class="line" id="L64">}</span>
<span class="line" id="L65"></span>
<span class="line" id="L66"><span class="tok-comment">//</span>
</span>
<span class="line" id="L67"><span class="tok-comment">// JSON helpers</span>
</span>
<span class="line" id="L68"><span class="tok-comment">//</span>
</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"><span class="tok-comment">/// Concenience: format an arbitrary value into a JSON string buffer.</span></span>
<span class="line" id="L71"><span class="tok-comment">/// Provide your own buf; this function is NOT mutex-protected!</span></span>
<span class="line" id="L72"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">stringifyBuf</span>(</span>
<span class="line" id="L73"> buffer: []<span class="tok-type">u8</span>,</span>
<span class="line" id="L74"> value: <span class="tok-kw">anytype</span>,</span>
<span class="line" id="L75"> options: std.json.StringifyOptions,</span>
<span class="line" id="L76">) ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L77"> <span class="tok-kw">var</span> fba = std.heap.FixedBufferAllocator.init(buffer);</span>
<span class="line" id="L78"> <span class="tok-kw">var</span> string = std.ArrayList(<span class="tok-type">u8</span>).init(fba.allocator());</span>
<span class="line" id="L79"> <span class="tok-kw">if</span> (std.json.stringify(value, options, string.writer())) {</span>
<span class="line" id="L80"> <span class="tok-kw">return</span> string.items;</span>
<span class="line" id="L81"> } <span class="tok-kw">else</span> |_| { <span class="tok-comment">// error</span>
</span>
<span class="line" id="L82"> <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L83"> }</span>
<span class="line" id="L84">}</span>
<span class="line" id="L85"></span>
</code></pre></body>
</html>

View file

@ -0,0 +1,346 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>websockets.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> zap = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zap.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> fio = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;fio.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">const</span> util = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;util.zig&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-comment">/// The Handle type used for WebSocket connections. Do not mess with this.</span></span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> WsHandle = ?*fio.ws_s;</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-comment">/// WebSocket Handler. Pass in a Context type and it will give you a struct that</span></span>
<span class="line" id="L10"><span class="tok-comment">/// contains all the types and functions you need. See the websocket example</span></span>
<span class="line" id="L11"><span class="tok-comment">/// for more details.</span></span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Handler</span>(<span class="tok-kw">comptime</span> ContextType: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L13"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L14"> <span class="tok-comment">/// OnMessage Callback on a websocket, type.</span></span>
<span class="line" id="L15"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> WsOnMessageFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (</span>
<span class="line" id="L16"> <span class="tok-comment">/// user-provided context, passed in from websocketHttpUpgrade()</span></span>
<span class="line" id="L17"> context: ?*ContextType,</span>
<span class="line" id="L18"> <span class="tok-comment">/// websocket handle, used to identify the websocket internally</span></span>
<span class="line" id="L19"> handle: WsHandle,</span>
<span class="line" id="L20"> <span class="tok-comment">/// the received message</span></span>
<span class="line" id="L21"> message: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L22"> <span class="tok-comment">/// indicator if message is text or binary</span></span>
<span class="line" id="L23"> is_text: <span class="tok-type">bool</span>,</span>
<span class="line" id="L24"> ) <span class="tok-type">void</span>;</span>
<span class="line" id="L25"></span>
<span class="line" id="L26"> <span class="tok-comment">/// Callback (type) when websocket is closed. uuid is a connection identifier,</span></span>
<span class="line" id="L27"> <span class="tok-comment">/// it is -1 if a connection could not be established</span></span>
<span class="line" id="L28"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> WsOnCloseFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (context: ?*ContextType, uuid: <span class="tok-type">isize</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"> <span class="tok-comment">/// A websocket callback function type. provides the context passed in at</span></span>
<span class="line" id="L31"> <span class="tok-comment">/// websocketHttpUpgrade().</span></span>
<span class="line" id="L32"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> WsFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (context: ?*ContextType, handle: WsHandle) <span class="tok-type">void</span>;</span>
<span class="line" id="L33"></span>
<span class="line" id="L34"> <span class="tok-comment">/// Websocket connection handler creation settings. Provide the callbacks you need,</span></span>
<span class="line" id="L35"> <span class="tok-comment">/// and an optional context.</span></span>
<span class="line" id="L36"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> WebSocketSettings = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L37"> <span class="tok-comment">/// on_message(context, handle, message, is_text)</span></span>
<span class="line" id="L38"> on_message: ?WsOnMessageFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L39"> <span class="tok-comment">/// on_open(context)</span></span>
<span class="line" id="L40"> on_open: ?WsFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L41"> <span class="tok-comment">/// on_ready(context)</span></span>
<span class="line" id="L42"> on_ready: ?WsFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L43"> <span class="tok-comment">/// on_shutdown(context, uuid)</span></span>
<span class="line" id="L44"> on_shutdown: ?WsFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L45"> <span class="tok-comment">/// on_close(context)</span></span>
<span class="line" id="L46"> on_close: ?WsOnCloseFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L47"> <span class="tok-comment">/// passed-in user-defined context</span></span>
<span class="line" id="L48"> context: ?*ContextType = <span class="tok-null">null</span>,</span>
<span class="line" id="L49"> };</span>
<span class="line" id="L50"></span>
<span class="line" id="L51"> <span class="tok-comment">/// This function will end the HTTP stage of the connection and attempt to &quot;upgrade&quot; to a WebSockets connection.</span></span>
<span class="line" id="L52"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">upgrade</span>(h: [*c]fio.http_s, settings: *WebSocketSettings) WebSocketError!<span class="tok-type">void</span> {</span>
<span class="line" id="L53"> <span class="tok-kw">const</span> fio_settings: fio.websocket_settings_s = .{</span>
<span class="line" id="L54"> .on_message = internal_on_message,</span>
<span class="line" id="L55"> .on_open = internal_on_open,</span>
<span class="line" id="L56"> .on_ready = internal_on_ready,</span>
<span class="line" id="L57"> .on_shutdown = internal_on_shutdown,</span>
<span class="line" id="L58"> .on_close = internal_on_close,</span>
<span class="line" id="L59"> .udata = settings,</span>
<span class="line" id="L60"> };</span>
<span class="line" id="L61"> <span class="tok-kw">if</span> (fio.http_upgrade2ws(h, fio_settings) != <span class="tok-number">0</span>) {</span>
<span class="line" id="L62"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.UpgradeError;</span>
<span class="line" id="L63"> }</span>
<span class="line" id="L64"> }</span>
<span class="line" id="L65"></span>
<span class="line" id="L66"> <span class="tok-kw">fn</span> <span class="tok-fn">internal_on_message</span>(handle: WsHandle, msg: fio.fio_str_info_s, is_text: <span class="tok-type">u8</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L67"> <span class="tok-kw">const</span> user_provided_settings: ?*WebSocketSettings = <span class="tok-builtin">@as</span>(?*WebSocketSettings, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(fio.websocket_udata_get(handle))));</span>
<span class="line" id="L68"> <span class="tok-kw">const</span> message = msg.data[<span class="tok-number">0</span>..msg.len];</span>
<span class="line" id="L69"> <span class="tok-kw">if</span> (user_provided_settings) |settings| {</span>
<span class="line" id="L70"> <span class="tok-kw">if</span> (settings.on_message) |on_message| {</span>
<span class="line" id="L71"> on_message(settings.context, handle, message, is_text == <span class="tok-number">1</span>);</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"> }</span>
<span class="line" id="L75"></span>
<span class="line" id="L76"> <span class="tok-kw">fn</span> <span class="tok-fn">internal_on_open</span>(handle: WsHandle) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L77"> <span class="tok-kw">const</span> user_provided_settings: ?*WebSocketSettings = <span class="tok-builtin">@as</span>(?*WebSocketSettings, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(fio.websocket_udata_get(handle))));</span>
<span class="line" id="L78"> <span class="tok-kw">if</span> (user_provided_settings) |settings| {</span>
<span class="line" id="L79"> <span class="tok-kw">if</span> (settings.on_open) |on_open| {</span>
<span class="line" id="L80"> on_open(settings.context, handle);</span>
<span class="line" id="L81"> }</span>
<span class="line" id="L82"> }</span>
<span class="line" id="L83"> }</span>
<span class="line" id="L84"></span>
<span class="line" id="L85"> <span class="tok-kw">fn</span> <span class="tok-fn">internal_on_ready</span>(handle: WsHandle) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L86"> <span class="tok-kw">const</span> user_provided_settings: ?*WebSocketSettings = <span class="tok-builtin">@as</span>(?*WebSocketSettings, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(fio.websocket_udata_get(handle))));</span>
<span class="line" id="L87"> <span class="tok-kw">if</span> (user_provided_settings) |settings| {</span>
<span class="line" id="L88"> <span class="tok-kw">if</span> (settings.on_ready) |on_ready| {</span>
<span class="line" id="L89"> on_ready(settings.context, handle);</span>
<span class="line" id="L90"> }</span>
<span class="line" id="L91"> }</span>
<span class="line" id="L92"> }</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-kw">fn</span> <span class="tok-fn">internal_on_shutdown</span>(handle: WsHandle) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L95"> <span class="tok-kw">const</span> user_provided_settings: ?*WebSocketSettings = <span class="tok-builtin">@as</span>(?*WebSocketSettings, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(fio.websocket_udata_get(handle))));</span>
<span class="line" id="L96"> <span class="tok-kw">if</span> (user_provided_settings) |settings| {</span>
<span class="line" id="L97"> <span class="tok-kw">if</span> (settings.on_shutdown) |on_shutdown| {</span>
<span class="line" id="L98"> on_shutdown(settings.context, handle);</span>
<span class="line" id="L99"> }</span>
<span class="line" id="L100"> }</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"> <span class="tok-kw">fn</span> <span class="tok-fn">internal_on_close</span>(uuid: <span class="tok-type">isize</span>, udata: ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L104"> <span class="tok-kw">const</span> user_provided_settings: ?*WebSocketSettings = <span class="tok-builtin">@as</span>(?*WebSocketSettings, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(udata)));</span>
<span class="line" id="L105"> <span class="tok-kw">if</span> (user_provided_settings) |settings| {</span>
<span class="line" id="L106"> <span class="tok-kw">if</span> (settings.on_close) |on_close| {</span>
<span class="line" id="L107"> on_close(settings.context, uuid);</span>
<span class="line" id="L108"> }</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110"> }</span>
<span class="line" id="L111"></span>
<span class="line" id="L112"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> WebSocketError = <span class="tok-kw">error</span>{</span>
<span class="line" id="L113"> WriteError,</span>
<span class="line" id="L114"> UpgradeError,</span>
<span class="line" id="L115"> SubscribeError,</span>
<span class="line" id="L116"> };</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"> <span class="tok-comment">/// Write to the websocket identified by the handle.</span></span>
<span class="line" id="L119"> <span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(handle: WsHandle, message: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, is_text: <span class="tok-type">bool</span>) WebSocketError!<span class="tok-type">void</span> {</span>
<span class="line" id="L120"> <span class="tok-kw">if</span> (fio.websocket_write(</span>
<span class="line" id="L121"> handle,</span>
<span class="line" id="L122"> fio.str2fio(message),</span>
<span class="line" id="L123"> <span class="tok-kw">if</span> (is_text) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L124"> ) != <span class="tok-number">0</span>) {</span>
<span class="line" id="L125"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.WriteError;</span>
<span class="line" id="L126"> }</span>
<span class="line" id="L127"> }</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"> <span class="tok-comment">/// The context pointer is stored in facilio's udata pointer. Use</span></span>
<span class="line" id="L130"> <span class="tok-comment">/// this function to turn that pointer into a pointer to your</span></span>
<span class="line" id="L131"> <span class="tok-comment">/// ContextType.</span></span>
<span class="line" id="L132"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">udataToContext</span>(udata: *<span class="tok-type">anyopaque</span>) *ContextType {</span>
<span class="line" id="L133"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(*ContextType, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(udata)));</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"></span>
<span class="line" id="L136"> <span class="tok-comment">/// Close the websocket connection.</span></span>
<span class="line" id="L137"> <span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">close</span>(handle: WsHandle) <span class="tok-type">void</span> {</span>
<span class="line" id="L138"> fio.websocket_close(handle);</span>
<span class="line" id="L139"> }</span>
<span class="line" id="L140"></span>
<span class="line" id="L141"> <span class="tok-comment">/// Settings for publishing a message in a channel.</span></span>
<span class="line" id="L142"> <span class="tok-kw">const</span> PublishArgs = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L143"> channel: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L144"> message: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L145"> is_json: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L146"> };</span>
<span class="line" id="L147"></span>
<span class="line" id="L148"> <span class="tok-comment">/// Publish a message in a channel.</span></span>
<span class="line" id="L149"> <span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">publish</span>(args: PublishArgs) <span class="tok-type">void</span> {</span>
<span class="line" id="L150"> fio.fio_publish(.{</span>
<span class="line" id="L151"> .channel = util.str2fio(args.channel),</span>
<span class="line" id="L152"> .message = util.str2fio(args.message),</span>
<span class="line" id="L153"> .is_json = <span class="tok-kw">if</span> (args.is_json) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L154"> });</span>
<span class="line" id="L155"> }</span>
<span class="line" id="L156"></span>
<span class="line" id="L157"> <span class="tok-comment">/// Type for callback on subscription message.</span></span>
<span class="line" id="L158"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> SubscriptionOnMessageFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (context: ?*ContextType, handle: WsHandle, channel: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, message: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L159"></span>
<span class="line" id="L160"> <span class="tok-comment">/// Type for callback on unsubscribe message.</span></span>
<span class="line" id="L161"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> SubscriptionOnUnsubscribeFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (context: ?*ContextType) <span class="tok-type">void</span>;</span>
<span class="line" id="L162"></span>
<span class="line" id="L163"> <span class="tok-comment">/// Settings for subscribing to a channel.</span></span>
<span class="line" id="L164"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> SubscribeArgs = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L165"> <span class="tok-comment">/// channel name</span></span>
<span class="line" id="L166"> channel: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L167"> <span class="tok-comment">/// on message callback</span></span>
<span class="line" id="L168"> on_message: ?SubscriptionOnMessageFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L169"> <span class="tok-comment">/// on unsubscribe callback</span></span>
<span class="line" id="L170"> on_unsubscribe: ?SubscriptionOnUnsubscribeFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L171"> <span class="tok-comment">/// this is not wrapped nicely yet</span></span>
<span class="line" id="L172"> match: fio.fio_match_fn = <span class="tok-null">null</span>,</span>
<span class="line" id="L173"> <span class="tok-comment">/// When using direct message forwarding (no on_message callback), this indicates if</span></span>
<span class="line" id="L174"> <span class="tok-comment">/// messages should be sent to the client as binary blobs, which is the safest approach.</span></span>
<span class="line" id="L175"> <span class="tok-comment">/// By default, facil.io will test for UTF-8 data validity and send the data as text if</span></span>
<span class="line" id="L176"> <span class="tok-comment">/// it's a valid UTF-8. Messages above ~32Kb might be assumed to be binary rather than</span></span>
<span class="line" id="L177"> <span class="tok-comment">/// tested.</span></span>
<span class="line" id="L178"> force_binary: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L179"> <span class="tok-comment">/// When using direct message forwarding (no on_message callback), this indicates if</span></span>
<span class="line" id="L180"> <span class="tok-comment">/// messages should be sent to the client as UTF-8 text. By default, facil.io will test</span></span>
<span class="line" id="L181"> <span class="tok-comment">/// for UTF-8 data validity and send the data as text if it's a valid UTF-8. Messages</span></span>
<span class="line" id="L182"> <span class="tok-comment">/// above ~32Kb might be assumed to be binary rather than tested. force_binary has</span></span>
<span class="line" id="L183"> <span class="tok-comment">/// precedence over force_text.</span></span>
<span class="line" id="L184"> force_text: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L185"> <span class="tok-comment">/// your provided arbitrary context</span></span>
<span class="line" id="L186"> context: ?*ContextType = <span class="tok-null">null</span>,</span>
<span class="line" id="L187"> };</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"> <span class="tok-comment">/// Subscribe to a channel.</span></span>
<span class="line" id="L190"> <span class="tok-comment">/// Returns a subscription ID on success and 0 on failure.</span></span>
<span class="line" id="L191"> <span class="tok-comment">/// we copy the pointer so make sure the struct stays valid.</span></span>
<span class="line" id="L192"> <span class="tok-comment">/// we need it to look up the ziggified callbacks.</span></span>
<span class="line" id="L193"> <span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">subscribe</span>(handle: WsHandle, args: *SubscribeArgs) WebSocketError!<span class="tok-type">usize</span> {</span>
<span class="line" id="L194"> <span class="tok-kw">if</span> (handle == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.SubscribeError;</span>
<span class="line" id="L195"> <span class="tok-kw">const</span> fio_args: fio.websocket_subscribe_s_zigcompat = .{</span>
<span class="line" id="L196"> .ws = handle.?,</span>
<span class="line" id="L197"> .channel = util.str2fio(args.channel),</span>
<span class="line" id="L198"> .on_message = <span class="tok-kw">if</span> (args.on_message) |_| internal_subscription_on_message <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L199"> .on_unsubscribe = <span class="tok-kw">if</span> (args.on_unsubscribe) |_| internal_subscription_on_unsubscribe <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L200"> .match = args.match,</span>
<span class="line" id="L201"> .force_binary = <span class="tok-kw">if</span> (args.force_binary) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L202"> .force_text = <span class="tok-kw">if</span> (args.force_text) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L203"> .udata = args,</span>
<span class="line" id="L204"> };</span>
<span class="line" id="L205"> <span class="tok-kw">const</span> ret = fio.websocket_subscribe_zigcompat(fio_args);</span>
<span class="line" id="L206"> <span class="tok-kw">if</span> (ret == <span class="tok-number">0</span>) {</span>
<span class="line" id="L207"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.SubscribeError;</span>
<span class="line" id="L208"> }</span>
<span class="line" id="L209"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L210"> }</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">internal_subscription_on_message</span>(handle: WsHandle, channel: fio.fio_str_info_s, message: fio.fio_str_info_s, udata: ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L213"> <span class="tok-kw">if</span> (udata) |p| {</span>
<span class="line" id="L214"> <span class="tok-kw">const</span> args = <span class="tok-builtin">@as</span>(*SubscribeArgs, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(p)));</span>
<span class="line" id="L215"> <span class="tok-kw">if</span> (args.on_message) |on_message| {</span>
<span class="line" id="L216"> on_message(args.context, handle, channel.data[<span class="tok-number">0</span>..channel.len], message.data[<span class="tok-number">0</span>..message.len]);</span>
<span class="line" id="L217"> }</span>
<span class="line" id="L218"> }</span>
<span class="line" id="L219"> }</span>
<span class="line" id="L220"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">internal_subscription_on_unsubscribe</span>(udata: ?*<span class="tok-type">anyopaque</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L221"> <span class="tok-kw">if</span> (udata) |p| {</span>
<span class="line" id="L222"> <span class="tok-kw">const</span> args = <span class="tok-builtin">@as</span>(*SubscribeArgs, <span class="tok-builtin">@ptrCast</span>(<span class="tok-builtin">@alignCast</span>(p)));</span>
<span class="line" id="L223"> <span class="tok-kw">if</span> (args.on_unsubscribe) |on_unsubscribe| {</span>
<span class="line" id="L224"> on_unsubscribe(args.context);</span>
<span class="line" id="L225"> }</span>
<span class="line" id="L226"> }</span>
<span class="line" id="L227"> }</span>
<span class="line" id="L228"> };</span>
<span class="line" id="L229">}</span>
<span class="line" id="L230"></span>
</code></pre></body>
</html>

548
docs/src/zap/zap.zig.html Normal file
View file

@ -0,0 +1,548 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>zap.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// zig type definitions for facilio lib</span>
</span>
<span class="line" id="L2"><span class="tok-comment">// or maybe let's just make it zap directly...</span>
</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-comment">/// The facilio C API. No need to use this.</span></span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fio = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;fio.zig&quot;</span>);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-comment">/// Server-Side TLS function wrapper</span></span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Tls = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tls.zig&quot;</span>);</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-comment">/// Endpoint and supporting types.</span></span>
<span class="line" id="L13"><span class="tok-comment">/// Create one and pass in your callbacks. Then,</span></span>
<span class="line" id="L14"><span class="tok-comment">/// pass it to a HttpListener's `register()` function to register with the</span></span>
<span class="line" id="L15"><span class="tok-comment">/// listener.</span></span>
<span class="line" id="L16"><span class="tok-comment">///</span></span>
<span class="line" id="L17"><span class="tok-comment">/// **NOTE**: A common endpoint pattern for zap is to create your own struct</span></span>
<span class="line" id="L18"><span class="tok-comment">/// that embeds an Endpoint, provides specific callbacks, and uses</span></span>
<span class="line" id="L19"><span class="tok-comment">/// `@fieldParentPtr` to get a reference to itself.</span></span>
<span class="line" id="L20"><span class="tok-comment">///</span></span>
<span class="line" id="L21"><span class="tok-comment">/// Example:</span></span>
<span class="line" id="L22"><span class="tok-comment">/// A simple endpoint listening on the /stop route that shuts down zap.</span></span>
<span class="line" id="L23"><span class="tok-comment">/// The main thread usually continues at the instructions after the call to zap.start().</span></span>
<span class="line" id="L24"><span class="tok-comment">///</span></span>
<span class="line" id="L25"><span class="tok-comment">/// ```zig</span></span>
<span class="line" id="L26"><span class="tok-comment">/// const StopEndpoint = struct {</span></span>
<span class="line" id="L27"><span class="tok-comment">/// ep: zap.Endpoint = undefined,</span></span>
<span class="line" id="L28"><span class="tok-comment">///</span></span>
<span class="line" id="L29"><span class="tok-comment">/// pub fn init(</span></span>
<span class="line" id="L30"><span class="tok-comment">/// path: []const u8,</span></span>
<span class="line" id="L31"><span class="tok-comment">/// ) StopEndpoint {</span></span>
<span class="line" id="L32"><span class="tok-comment">/// return .{</span></span>
<span class="line" id="L33"><span class="tok-comment">/// .ep = zap.Endpoint.init(.{</span></span>
<span class="line" id="L34"><span class="tok-comment">/// .path = path,</span></span>
<span class="line" id="L35"><span class="tok-comment">/// .get = get,</span></span>
<span class="line" id="L36"><span class="tok-comment">/// }),</span></span>
<span class="line" id="L37"><span class="tok-comment">/// };</span></span>
<span class="line" id="L38"><span class="tok-comment">/// }</span></span>
<span class="line" id="L39"><span class="tok-comment">///</span></span>
<span class="line" id="L40"><span class="tok-comment">/// // access the internal Endpoint</span></span>
<span class="line" id="L41"><span class="tok-comment">/// pub fn endpoint(self: *StopEndpoint) *zap.Endpoint {</span></span>
<span class="line" id="L42"><span class="tok-comment">/// return &amp;self.ep;</span></span>
<span class="line" id="L43"><span class="tok-comment">/// }</span></span>
<span class="line" id="L44"><span class="tok-comment">///</span></span>
<span class="line" id="L45"><span class="tok-comment">/// fn get(e: *zap.Endpoint, r: zap.Request) void {</span></span>
<span class="line" id="L46"><span class="tok-comment">/// const self: *StopEndpoint = @fieldParentPtr(StopEndpoint, &quot;ep&quot;, e);</span></span>
<span class="line" id="L47"><span class="tok-comment">/// _ = self;</span></span>
<span class="line" id="L48"><span class="tok-comment">/// _ = r;</span></span>
<span class="line" id="L49"><span class="tok-comment">/// zap.stop();</span></span>
<span class="line" id="L50"><span class="tok-comment">/// }</span></span>
<span class="line" id="L51"><span class="tok-comment">/// };</span></span>
<span class="line" id="L52"><span class="tok-comment">/// ```</span></span>
<span class="line" id="L53"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Endpoint = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;endpoint.zig&quot;</span>);</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">usingnamespace</span> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;util.zig&quot;</span>);</span>
<span class="line" id="L56"><span class="tok-kw">pub</span> <span class="tok-kw">usingnamespace</span> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;http.zig&quot;</span>);</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"><span class="tok-comment">/// A struct to handle Mustache templating.</span></span>
<span class="line" id="L59"><span class="tok-comment">///</span></span>
<span class="line" id="L60"><span class="tok-comment">/// This is a wrapper around fiobj's mustache template handling.</span></span>
<span class="line" id="L61"><span class="tok-comment">/// See http://facil.io/0.7.x/fiobj_mustache for more information.</span></span>
<span class="line" id="L62"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Mustache = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;mustache.zig&quot;</span>);</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"><span class="tok-comment">/// Authenticators</span></span>
<span class="line" id="L65"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Auth = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;http_auth.zig&quot;</span>);</span>
<span class="line" id="L66"></span>
<span class="line" id="L67"><span class="tok-comment">/// Http request and supporting types.</span></span>
<span class="line" id="L68"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Request = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;request.zig&quot;</span>);</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"><span class="tok-comment">/// Middleware support.</span></span>
<span class="line" id="L71"><span class="tok-comment">/// Contains a special Listener and a Handler struct that support chaining</span></span>
<span class="line" id="L72"><span class="tok-comment">/// requests handlers, with an optional stop once a handler indicates it</span></span>
<span class="line" id="L73"><span class="tok-comment">/// processed the request. Also sports an EndpointHandler for using regular zap</span></span>
<span class="line" id="L74"><span class="tok-comment">/// Endpoints as Handlers.</span></span>
<span class="line" id="L75"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Middleware = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;middleware.zig&quot;</span>);</span>
<span class="line" id="L76"></span>
<span class="line" id="L77"><span class="tok-comment">/// Websocket API</span></span>
<span class="line" id="L78"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> WebSockets = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;websockets.zig&quot;</span>);</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Log = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;log.zig&quot;</span>);</span>
<span class="line" id="L81"><span class="tok-kw">const</span> http = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;http.zig&quot;</span>);</span>
<span class="line" id="L82"></span>
<span class="line" id="L83"><span class="tok-kw">const</span> util = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;util.zig&quot;</span>);</span>
<span class="line" id="L84"></span>
<span class="line" id="L85"><span class="tok-comment">// TODO: replace with comptime debug logger like in log.zig</span>
</span>
<span class="line" id="L86"><span class="tok-kw">var</span> _debug: <span class="tok-type">bool</span> = <span class="tok-null">false</span>;</span>
<span class="line" id="L87"></span>
<span class="line" id="L88"><span class="tok-comment">/// Start the IO reactor</span></span>
<span class="line" id="L89"><span class="tok-comment">///</span></span>
<span class="line" id="L90"><span class="tok-comment">/// Will start listeners etc.</span></span>
<span class="line" id="L91"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">start</span>(args: fio.fio_start_args) <span class="tok-type">void</span> {</span>
<span class="line" id="L92"> fio.fio_start(args);</span>
<span class="line" id="L93">}</span>
<span class="line" id="L94"></span>
<span class="line" id="L95"><span class="tok-comment">/// Stop ZAP:</span></span>
<span class="line" id="L96"><span class="tok-comment">///</span></span>
<span class="line" id="L97"><span class="tok-comment">/// 1. Stop accepting further incoming requests</span></span>
<span class="line" id="L98"><span class="tok-comment">/// 2. Wait for all running request handlers to return</span></span>
<span class="line" id="L99"><span class="tok-comment">/// 3. return from `zap.start(...)`</span></span>
<span class="line" id="L100"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">stop</span>() <span class="tok-type">void</span> {</span>
<span class="line" id="L101"> fio.fio_stop();</span>
<span class="line" id="L102">}</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"><span class="tok-comment">/// Extremely simplistic zap debug function.</span></span>
<span class="line" id="L105"><span class="tok-comment">/// TODO: re-wwrite logging or use std.log</span></span>
<span class="line" id="L106"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">debug</span>(<span class="tok-kw">comptime</span> fmt: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, args: <span class="tok-kw">anytype</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L107"> <span class="tok-kw">if</span> (_debug) {</span>
<span class="line" id="L108"> std.debug.print(<span class="tok-str">&quot;[zap] - &quot;</span> ++ fmt, args);</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110">}</span>
<span class="line" id="L111"></span>
<span class="line" id="L112"><span class="tok-comment">/// Enable zap debug logging</span></span>
<span class="line" id="L113"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">enableDebugLog</span>() <span class="tok-type">void</span> {</span>
<span class="line" id="L114"> _debug = <span class="tok-null">true</span>;</span>
<span class="line" id="L115">}</span>
<span class="line" id="L116"></span>
<span class="line" id="L117"><span class="tok-comment">/// start Zap with debug logging on</span></span>
<span class="line" id="L118"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">startWithLogging</span>(args: fio.fio_start_args) <span class="tok-type">void</span> {</span>
<span class="line" id="L119"> debug = <span class="tok-null">true</span>;</span>
<span class="line" id="L120"> fio.fio_start(args);</span>
<span class="line" id="L121">}</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ListenError = <span class="tok-kw">error</span>{</span>
<span class="line" id="L124"> AlreadyListening,</span>
<span class="line" id="L125"> ListenError,</span>
<span class="line" id="L126">};</span>
<span class="line" id="L127"></span>
<span class="line" id="L128"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpError = <span class="tok-kw">error</span>{</span>
<span class="line" id="L129"> HttpSendBody,</span>
<span class="line" id="L130"> HttpSetContentType,</span>
<span class="line" id="L131"> HttpSetHeader,</span>
<span class="line" id="L132"> HttpParseBody,</span>
<span class="line" id="L133"> HttpIterParams,</span>
<span class="line" id="L134"> SetCookie,</span>
<span class="line" id="L135"> SendFile,</span>
<span class="line" id="L136">};</span>
<span class="line" id="L137"></span>
<span class="line" id="L138"><span class="tok-comment">/// Http Content Type enum.</span></span>
<span class="line" id="L139"><span class="tok-comment">/// Needs some love.</span></span>
<span class="line" id="L140"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ContentType = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L141"> TEXT,</span>
<span class="line" id="L142"> HTML,</span>
<span class="line" id="L143"> JSON,</span>
<span class="line" id="L144"> <span class="tok-comment">// TODO: more content types</span>
</span>
<span class="line" id="L145">};</span>
<span class="line" id="L146"></span>
<span class="line" id="L147"><span class="tok-comment">/// Used internally: facilio Http request callback function type</span></span>
<span class="line" id="L148"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FioHttpRequestFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (r: [*c]fio.http_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span>;</span>
<span class="line" id="L149"></span>
<span class="line" id="L150"><span class="tok-comment">/// Zap Http request callback function type.</span></span>
<span class="line" id="L151"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpRequestFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (Request) <span class="tok-type">void</span>;</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"><span class="tok-comment">/// websocket connection upgrade callback type</span></span>
<span class="line" id="L154"><span class="tok-comment">/// fn(request, targetstring)</span></span>
<span class="line" id="L155"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpUpgradeFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (r: Request, target_protocol: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">void</span>;</span>
<span class="line" id="L156"></span>
<span class="line" id="L157"><span class="tok-comment">/// http finish, called when zap finishes. You get your udata back in the</span></span>
<span class="line" id="L158"><span class="tok-comment">/// HttpFinishSetting struct.</span></span>
<span class="line" id="L159"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpFinishSettings = [*c]fio.struct_http_settings_s;</span>
<span class="line" id="L160"></span>
<span class="line" id="L161"><span class="tok-comment">/// Http finish callback type</span></span>
<span class="line" id="L162"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpFinishFn = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> (HttpFinishSettings) <span class="tok-type">void</span>;</span>
<span class="line" id="L163"></span>
<span class="line" id="L164"><span class="tok-comment">/// Listener settings</span></span>
<span class="line" id="L165"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpListenerSettings = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L166"> port: <span class="tok-type">usize</span>,</span>
<span class="line" id="L167"> interface: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L168"> on_request: ?HttpRequestFn,</span>
<span class="line" id="L169"> on_response: ?HttpRequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L170"> on_upgrade: ?HttpUpgradeFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L171"> on_finish: ?HttpFinishFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L172"> <span class="tok-comment">// provide any pointer in there for &quot;user data&quot;. it will be passed pack in</span>
</span>
<span class="line" id="L173"> <span class="tok-comment">// on_finish()'s copy of the struct_http_settings_s</span>
</span>
<span class="line" id="L174"> udata: ?*<span class="tok-type">anyopaque</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L175"> public_folder: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L176"> max_clients: ?<span class="tok-type">isize</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L177"> max_body_size: ?<span class="tok-type">usize</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L178"> timeout: ?<span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L179"> log: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L180"> ws_timeout: <span class="tok-type">u8</span> = <span class="tok-number">40</span>,</span>
<span class="line" id="L181"> ws_max_msg_size: <span class="tok-type">usize</span> = <span class="tok-number">262144</span>,</span>
<span class="line" id="L182"> tls: ?Tls = <span class="tok-null">null</span>,</span>
<span class="line" id="L183">};</span>
<span class="line" id="L184"></span>
<span class="line" id="L185"><span class="tok-comment">/// Http listener</span></span>
<span class="line" id="L186"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HttpListener = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L187"> settings: HttpListenerSettings,</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L190"> <span class="tok-kw">var</span> the_one_and_only_listener: ?*HttpListener = <span class="tok-null">null</span>;</span>
<span class="line" id="L191"></span>
<span class="line" id="L192"> <span class="tok-comment">/// Create a listener</span></span>
<span class="line" id="L193"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(settings: HttpListenerSettings) Self {</span>
<span class="line" id="L194"> std.debug.assert(settings.on_request != <span class="tok-null">null</span>);</span>
<span class="line" id="L195"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L196"> .settings = settings,</span>
<span class="line" id="L197"> };</span>
<span class="line" id="L198"> }</span>
<span class="line" id="L199"></span>
<span class="line" id="L200"> <span class="tok-comment">// we could make it dynamic by passing a HttpListener via udata</span>
</span>
<span class="line" id="L201"> <span class="tok-comment">/// Used internally: the listener's facilio request callback</span></span>
<span class="line" id="L202"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">theOneAndOnlyRequestCallBack</span>(r: [*c]fio.http_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L203"> <span class="tok-kw">if</span> (the_one_and_only_listener) |l| {</span>
<span class="line" id="L204"> <span class="tok-kw">var</span> req: Request = .{</span>
<span class="line" id="L205"> .path = util.fio2str(r.*.path),</span>
<span class="line" id="L206"> .query = util.fio2str(r.*.query),</span>
<span class="line" id="L207"> .body = util.fio2str(r.*.body),</span>
<span class="line" id="L208"> .method = util.fio2str(r.*.method),</span>
<span class="line" id="L209"> .h = r,</span>
<span class="line" id="L210"> ._is_finished_request_global = <span class="tok-null">false</span>,</span>
<span class="line" id="L211"> ._user_context = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L212"> };</span>
<span class="line" id="L213"> req._is_finished = &amp;req._is_finished_request_global;</span>
<span class="line" id="L214"></span>
<span class="line" id="L215"> <span class="tok-kw">var</span> user_context: Request.UserContext = .{};</span>
<span class="line" id="L216"> req._user_context = &amp;user_context;</span>
<span class="line" id="L217"></span>
<span class="line" id="L218"> req.markAsFinished(<span class="tok-null">false</span>);</span>
<span class="line" id="L219"> std.debug.assert(l.settings.on_request != <span class="tok-null">null</span>);</span>
<span class="line" id="L220"> <span class="tok-kw">if</span> (l.settings.on_request) |on_request| {</span>
<span class="line" id="L221"> <span class="tok-comment">// l.settings.on_request.?(req);</span>
</span>
<span class="line" id="L222"> on_request(req);</span>
<span class="line" id="L223"> }</span>
<span class="line" id="L224"> }</span>
<span class="line" id="L225"> }</span>
<span class="line" id="L226"></span>
<span class="line" id="L227"> <span class="tok-comment">/// Used internally: the listener's facilio response callback</span></span>
<span class="line" id="L228"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">theOneAndOnlyResponseCallBack</span>(r: [*c]fio.http_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L229"> <span class="tok-kw">if</span> (the_one_and_only_listener) |l| {</span>
<span class="line" id="L230"> <span class="tok-kw">var</span> req: Request = .{</span>
<span class="line" id="L231"> .path = util.fio2str(r.*.path),</span>
<span class="line" id="L232"> .query = util.fio2str(r.*.query),</span>
<span class="line" id="L233"> .body = util.fio2str(r.*.body),</span>
<span class="line" id="L234"> .method = util.fio2str(r.*.method),</span>
<span class="line" id="L235"> .h = r,</span>
<span class="line" id="L236"> ._is_finished_request_global = <span class="tok-null">false</span>,</span>
<span class="line" id="L237"> ._user_context = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L238"> };</span>
<span class="line" id="L239"> req._is_finished = &amp;req._is_finished_request_global;</span>
<span class="line" id="L240"></span>
<span class="line" id="L241"> <span class="tok-kw">var</span> user_context: Request.UserContext = .{};</span>
<span class="line" id="L242"> req._user_context = &amp;user_context;</span>
<span class="line" id="L243"></span>
<span class="line" id="L244"> l.settings.on_response.?(req);</span>
<span class="line" id="L245"> }</span>
<span class="line" id="L246"> }</span>
<span class="line" id="L247"></span>
<span class="line" id="L248"> <span class="tok-comment">/// Used internally: the listener's facilio upgrade callback</span></span>
<span class="line" id="L249"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">theOneAndOnlyUpgradeCallBack</span>(r: [*c]fio.http_s, target: [*c]<span class="tok-type">u8</span>, target_len: <span class="tok-type">usize</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L250"> <span class="tok-kw">if</span> (the_one_and_only_listener) |l| {</span>
<span class="line" id="L251"> <span class="tok-kw">var</span> req: Request = .{</span>
<span class="line" id="L252"> .path = util.fio2str(r.*.path),</span>
<span class="line" id="L253"> .query = util.fio2str(r.*.query),</span>
<span class="line" id="L254"> .body = util.fio2str(r.*.body),</span>
<span class="line" id="L255"> .method = util.fio2str(r.*.method),</span>
<span class="line" id="L256"> .h = r,</span>
<span class="line" id="L257"> ._is_finished_request_global = <span class="tok-null">false</span>,</span>
<span class="line" id="L258"> ._user_context = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L259"> };</span>
<span class="line" id="L260"> <span class="tok-kw">const</span> zigtarget: []<span class="tok-type">u8</span> = target[<span class="tok-number">0</span>..target_len];</span>
<span class="line" id="L261"> req._is_finished = &amp;req._is_finished_request_global;</span>
<span class="line" id="L262"></span>
<span class="line" id="L263"> <span class="tok-kw">var</span> user_context: Request.UserContext = .{};</span>
<span class="line" id="L264"> req._user_context = &amp;user_context;</span>
<span class="line" id="L265"></span>
<span class="line" id="L266"> l.settings.on_upgrade.?(req, zigtarget);</span>
<span class="line" id="L267"> }</span>
<span class="line" id="L268"> }</span>
<span class="line" id="L269"></span>
<span class="line" id="L270"> <span class="tok-comment">/// Used internally: the listener's facilio finish callback</span></span>
<span class="line" id="L271"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">theOneAndOnlyFinishCallBack</span>(s: [*c]fio.struct_http_settings_s) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L272"> <span class="tok-kw">if</span> (the_one_and_only_listener) |l| {</span>
<span class="line" id="L273"> l.settings.on_finish.?(s);</span>
<span class="line" id="L274"> }</span>
<span class="line" id="L275"> }</span>
<span class="line" id="L276"></span>
<span class="line" id="L277"> <span class="tok-comment">/// Start listening</span></span>
<span class="line" id="L278"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">listen</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L279"> <span class="tok-kw">var</span> pfolder: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>;</span>
<span class="line" id="L280"> <span class="tok-kw">var</span> pfolder_len: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L281"></span>
<span class="line" id="L282"> <span class="tok-kw">if</span> (self.settings.public_folder) |pf| {</span>
<span class="line" id="L283"> debug(<span class="tok-str">&quot;HttpListener.listen(): public folder is {s}\n&quot;</span>, .{pf});</span>
<span class="line" id="L284"> pfolder_len = pf.len;</span>
<span class="line" id="L285"> pfolder = pf.ptr;</span>
<span class="line" id="L286"> }</span>
<span class="line" id="L287"></span>
<span class="line" id="L288"> <span class="tok-kw">const</span> x: fio.http_settings_s = .{</span>
<span class="line" id="L289"> .on_request = <span class="tok-kw">if</span> (self.settings.on_request) |_| Self.theOneAndOnlyRequestCallBack <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L290"> .on_upgrade = <span class="tok-kw">if</span> (self.settings.on_upgrade) |_| Self.theOneAndOnlyUpgradeCallBack <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L291"> .on_response = <span class="tok-kw">if</span> (self.settings.on_response) |_| Self.theOneAndOnlyResponseCallBack <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L292"> .on_finish = <span class="tok-kw">if</span> (self.settings.on_finish) |_| Self.theOneAndOnlyFinishCallBack <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L293"> .udata = <span class="tok-null">null</span>,</span>
<span class="line" id="L294"> .public_folder = pfolder,</span>
<span class="line" id="L295"> .public_folder_length = pfolder_len,</span>
<span class="line" id="L296"> .max_header_size = <span class="tok-number">32</span> * <span class="tok-number">1024</span>,</span>
<span class="line" id="L297"> .max_body_size = self.settings.max_body_size <span class="tok-kw">orelse</span> <span class="tok-number">50</span> * <span class="tok-number">1024</span> * <span class="tok-number">1024</span>,</span>
<span class="line" id="L298"> <span class="tok-comment">// fio provides good default:</span>
</span>
<span class="line" id="L299"> .max_clients = self.settings.max_clients <span class="tok-kw">orelse</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L300"> .tls = <span class="tok-kw">if</span> (self.settings.tls) |tls| tls.fio_tls <span class="tok-kw">else</span> <span class="tok-null">null</span>,</span>
<span class="line" id="L301"> .reserved1 = <span class="tok-number">0</span>,</span>
<span class="line" id="L302"> .reserved2 = <span class="tok-number">0</span>,</span>
<span class="line" id="L303"> .reserved3 = <span class="tok-number">0</span>,</span>
<span class="line" id="L304"> .ws_max_msg_size = <span class="tok-number">0</span>,</span>
<span class="line" id="L305"> .timeout = self.settings.timeout <span class="tok-kw">orelse</span> <span class="tok-number">5</span>,</span>
<span class="line" id="L306"> .ws_timeout = self.settings.ws_timeout,</span>
<span class="line" id="L307"> .log = <span class="tok-kw">if</span> (self.settings.log) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L308"> .is_client = <span class="tok-number">0</span>,</span>
<span class="line" id="L309"> };</span>
<span class="line" id="L310"> <span class="tok-comment">// TODO: BUG: without this print/sleep statement, -Drelease* loop forever</span>
</span>
<span class="line" id="L311"> <span class="tok-comment">// in debug2 and debug3 of hello example</span>
</span>
<span class="line" id="L312"> <span class="tok-comment">// std.debug.print(&quot;X\n&quot;, .{});</span>
</span>
<span class="line" id="L313"> <span class="tok-comment">// TODO: still happening?</span>
</span>
<span class="line" id="L314"> std.time.sleep(<span class="tok-number">500</span> * std.time.ns_per_ms);</span>
<span class="line" id="L315"></span>
<span class="line" id="L316"> <span class="tok-kw">var</span> portbuf: [<span class="tok-number">100</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L317"> <span class="tok-kw">const</span> printed_port = <span class="tok-kw">try</span> std.fmt.bufPrintZ(&amp;portbuf, <span class="tok-str">&quot;{d}&quot;</span>, .{self.settings.port});</span>
<span class="line" id="L318"></span>
<span class="line" id="L319"> <span class="tok-kw">const</span> ret = fio.http_listen(printed_port.ptr, self.settings.interface, x);</span>
<span class="line" id="L320"> <span class="tok-kw">if</span> (ret == -<span class="tok-number">1</span>) {</span>
<span class="line" id="L321"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.ListenError;</span>
<span class="line" id="L322"> }</span>
<span class="line" id="L323"></span>
<span class="line" id="L324"> <span class="tok-comment">// set ourselves up to handle requests:</span>
</span>
<span class="line" id="L325"> <span class="tok-comment">// TODO: do we mind the race condition?</span>
</span>
<span class="line" id="L326"> <span class="tok-comment">// the HttpRequestFn will check if this is null and not process</span>
</span>
<span class="line" id="L327"> <span class="tok-comment">// the request if it isn't set. hence, if started under full load, the</span>
</span>
<span class="line" id="L328"> <span class="tok-comment">// first request(s) might not be serviced, as long as it takes from</span>
</span>
<span class="line" id="L329"> <span class="tok-comment">// fio.http_listen() to here</span>
</span>
<span class="line" id="L330"> Self.the_one_and_only_listener = self;</span>
<span class="line" id="L331"> }</span>
<span class="line" id="L332">};</span>
<span class="line" id="L333"></span>
<span class="line" id="L334"><span class="tok-comment">/// Low-level API</span></span>
<span class="line" id="L335"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> LowLevel = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L336"> <span class="tok-comment">/// lower level listening, if you don't want to use a listener but rather use</span></span>
<span class="line" id="L337"> <span class="tok-comment">/// the listen() function.</span></span>
<span class="line" id="L338"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> ListenSettings = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L339"> on_request: ?FioHttpRequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L340"> on_upgrade: ?FioHttpRequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L341"> on_response: ?FioHttpRequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L342"> on_finish: ?FioHttpRequestFn = <span class="tok-null">null</span>,</span>
<span class="line" id="L343"> public_folder: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L344"> max_header_size: <span class="tok-type">usize</span> = <span class="tok-number">32</span> * <span class="tok-number">1024</span>,</span>
<span class="line" id="L345"> max_body_size: <span class="tok-type">usize</span> = <span class="tok-number">50</span> * <span class="tok-number">1024</span> * <span class="tok-number">1024</span>,</span>
<span class="line" id="L346"> max_clients: <span class="tok-type">isize</span> = <span class="tok-number">100</span>,</span>
<span class="line" id="L347"> keepalive_timeout_s: <span class="tok-type">u8</span> = <span class="tok-number">5</span>,</span>
<span class="line" id="L348"> log: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L349"></span>
<span class="line" id="L350"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L351"></span>
<span class="line" id="L352"> <span class="tok-comment">/// Create settings with defaults</span></span>
<span class="line" id="L353"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>() Self {</span>
<span class="line" id="L354"> <span class="tok-kw">return</span> .{};</span>
<span class="line" id="L355"> }</span>
<span class="line" id="L356"> };</span>
<span class="line" id="L357"></span>
<span class="line" id="L358"> <span class="tok-comment">/// Low level listen function</span></span>
<span class="line" id="L359"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">listen</span>(port: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, interface: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, settings: ListenSettings) ListenError!<span class="tok-type">void</span> {</span>
<span class="line" id="L360"> <span class="tok-kw">var</span> pfolder: [*c]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>;</span>
<span class="line" id="L361"> <span class="tok-kw">var</span> pfolder_len: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L362"></span>
<span class="line" id="L363"> <span class="tok-kw">if</span> (settings.public_folder) |pf| {</span>
<span class="line" id="L364"> pfolder_len = pf.len;</span>
<span class="line" id="L365"> pfolder = pf.ptr;</span>
<span class="line" id="L366"> }</span>
<span class="line" id="L367"> <span class="tok-kw">const</span> x: fio.http_settings_s = .{</span>
<span class="line" id="L368"> .on_request = settings.on_request,</span>
<span class="line" id="L369"> .on_upgrade = settings.on_upgrade,</span>
<span class="line" id="L370"> .on_response = settings.on_response,</span>
<span class="line" id="L371"> .on_finish = settings.on_finish,</span>
<span class="line" id="L372"> .udata = <span class="tok-null">null</span>,</span>
<span class="line" id="L373"> .public_folder = pfolder,</span>
<span class="line" id="L374"> .public_folder_length = pfolder_len,</span>
<span class="line" id="L375"> .max_header_size = settings.max_header_size,</span>
<span class="line" id="L376"> .max_body_size = settings.max_body_size,</span>
<span class="line" id="L377"> .max_clients = settings.max_clients,</span>
<span class="line" id="L378"> .tls = <span class="tok-null">null</span>,</span>
<span class="line" id="L379"> .reserved1 = <span class="tok-number">0</span>,</span>
<span class="line" id="L380"> .reserved2 = <span class="tok-number">0</span>,</span>
<span class="line" id="L381"> .reserved3 = <span class="tok-number">0</span>,</span>
<span class="line" id="L382"> .ws_max_msg_size = settings.ws_max_msg_size,</span>
<span class="line" id="L383"> .timeout = settings.keepalive_timeout_s,</span>
<span class="line" id="L384"> .ws_timeout = <span class="tok-number">0</span>,</span>
<span class="line" id="L385"> .log = <span class="tok-kw">if</span> (settings.log) <span class="tok-number">1</span> <span class="tok-kw">else</span> <span class="tok-number">0</span>,</span>
<span class="line" id="L386"> .is_client = <span class="tok-number">0</span>,</span>
<span class="line" id="L387"> };</span>
<span class="line" id="L388"> <span class="tok-comment">// TODO: BUG: without this print/sleep statement, -Drelease* loop forever</span>
</span>
<span class="line" id="L389"> <span class="tok-comment">// in debug2 and debug3 of hello example</span>
</span>
<span class="line" id="L390"> <span class="tok-comment">// std.debug.print(&quot;X\n&quot;, .{});</span>
</span>
<span class="line" id="L391"> <span class="tok-comment">// TODO: still happening?</span>
</span>
<span class="line" id="L392"> std.time.sleep(<span class="tok-number">500</span> * std.time.ns_per_ms);</span>
<span class="line" id="L393"></span>
<span class="line" id="L394"> <span class="tok-kw">if</span> (fio.http_listen(port, interface, x) == -<span class="tok-number">1</span>) {</span>
<span class="line" id="L395"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.ListenError;</span>
<span class="line" id="L396"> }</span>
<span class="line" id="L397"> }</span>
<span class="line" id="L398"></span>
<span class="line" id="L399"> <span class="tok-comment">/// lower level sendBody</span></span>
<span class="line" id="L400"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">sendBody</span>(request: [*c]fio.http_s, body: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) HttpError!<span class="tok-type">void</span> {</span>
<span class="line" id="L401"> <span class="tok-kw">const</span> ret = fio.http_send_body(request, <span class="tok-builtin">@as</span>(</span>
<span class="line" id="L402"> *<span class="tok-type">anyopaque</span>,</span>
<span class="line" id="L403"> <span class="tok-builtin">@ptrFromInt</span>(<span class="tok-builtin">@intFromPtr</span>(body.ptr)),</span>
<span class="line" id="L404"> ), body.len);</span>
<span class="line" id="L405"> debug(<span class="tok-str">&quot;sendBody(): ret = {}\n&quot;</span>, .{ret});</span>
<span class="line" id="L406"> <span class="tok-kw">if</span> (ret != -<span class="tok-number">1</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.HttpSendBody;</span>
<span class="line" id="L407"> }</span>
<span class="line" id="L408">};</span>
<span class="line" id="L409"></span>
</code></pre></body>
</html>

2147
docs/ziglexer.js Normal file

File diff suppressed because it is too large Load diff