There are no doc comments for this declaration.
";
- }
- domTldDocs.classList.remove("hidden");
- }
-
- function typeIsErrSet(typeIndex) {
- let typeObj = getType(typeIndex);
- return typeObj.kind === typeKinds.ErrorSet;
- }
-
- function typeIsStructWithNoFields(typeIndex) {
- let typeObj = getType(typeIndex);
- if (typeObj.kind !== typeKinds.Struct) return false;
- return typeObj.field_types.length == 0;
- }
-
- function typeIsGenericFn(typeIndex) {
- let typeObj = getType(typeIndex);
- if (typeObj.kind !== typeKinds.Fn) {
- return false;
- }
- return typeObj.generic_ret != null;
- }
-
- function renderFn(fnDecl) {
- if ("refPath" in fnDecl.value.expr) {
- let last = fnDecl.value.expr.refPath.length - 1;
- let lastExpr = fnDecl.value.expr.refPath[last];
- console.assert("declRef" in lastExpr);
- fnDecl = getDecl(lastExpr.declRef);
- }
-
- let value = resolveValue(fnDecl.value);
- console.assert("type" in value.expr);
- let typeObj = getType(value.expr.type);
-
- domFnProtoCode.innerHTML = renderTokens(ex(value.expr, { fnDecl: fnDecl }));
- domFnSourceLink.classList.remove("hidden");
- domFnSourceLink.innerHTML = "[" + short + "
" + "
" + long + "
";
- }
- else {
- tdDesc.innerHTML = markdown(short, container);
- }
- } else {
- tdDesc.innerHTML = "
No documentation provided.
";
- }
- }
- domSectFns.classList.remove("hidden");
- }
-
- let containerNode = getAstNode(container.src);
- if (containerNode.fields && containerNode.fields.length > 0) {
- resizeDomList(domListFields, containerNode.fields.length, "
");
-
- for (let i = 0; i < containerNode.fields.length; i += 1) {
- let fieldNode = getAstNode(containerNode.fields[i]);
- let divDom = domListFields.children[i];
- let fieldName = fieldNode.name;
- let docs = fieldNode.docs;
- let docsNonEmpty = docs != null && docs !== "";
- let extraPreClass = docsNonEmpty ? " fieldHasDocs" : "";
-
- let html =
- '
";
-
- if (docsNonEmpty) {
- html += '
' + markdown(docs) + "
";
- }
- divDom.innerHTML = html;
- }
- domSectFields.classList.remove("hidden");
- }
-
- if (varsList.length !== 0) {
- resizeDomList(
- domListGlobalVars,
- varsList.length,
- '
| | |
'
- );
- for (let i = 0; i < varsList.length; i += 1) {
- let decl = varsList[i];
- let trDom = domListGlobalVars.children[i];
-
- let tdName = trDom.children[0];
- let tdNameA = tdName.children[0];
- let tdType = trDom.children[1];
- let preType = tdType.children[0];
- let tdDesc = trDom.children[2];
-
- tdNameA.setAttribute("href", navLinkDecl(decl.name));
- tdNameA.textContent = decl.name;
-
- preType.innerHTML = renderTokens(ex(walkResultTypeRef(decl.value), {}));
-
- let docs = getAstNode(decl.src).docs;
- if (docs != null) {
- tdDesc.innerHTML = shortDescMarkdown(docs);
- } else {
- tdDesc.textContent = "";
- }
- }
- domSectGlobalVars.classList.remove("hidden");
- }
-
- if (valsList.length !== 0) {
- resizeDomList(
- domListValues,
- valsList.length,
- '
| | |
'
- );
- for (let i = 0; i < valsList.length; i += 1) {
- let decl = valsList[i];
- let trDom = domListValues.children[i];
-
- let tdName = trDom.children[0];
- let tdNameA = tdName.children[0];
- let tdType = trDom.children[1];
- let preType = tdType.children[0];
- let tdDesc = trDom.children[2];
-
- tdNameA.setAttribute("href", navLinkDecl(decl.name));
- tdNameA.textContent = decl.name;
-
- preType.innerHTML = renderTokens(ex(walkResultTypeRef(decl.value), {}));
-
- let docs = getAstNode(decl.src).docs;
- if (docs != null) {
- tdDesc.innerHTML = shortDescMarkdown(docs);
- } else {
- tdDesc.textContent = "";
- }
- }
- domSectValues.classList.remove("hidden");
- }
-
- if (testsList.length !== 0) {
- resizeDomList(
- domListTests,
- testsList.length,
- '
| | |
'
- );
- for (let i = 0; i < testsList.length; i += 1) {
- let decl = testsList[i];
- let trDom = domListTests.children[i];
-
- let tdName = trDom.children[0];
- let tdNamePre = tdName.children[0];
- let tdType = trDom.children[1];
- let tdTypePre = tdType.children[0];
- let tdDesc = trDom.children[2];
-
- tdNamePre.innerHTML = renderSingleToken(Tok.identifier(decl.name));
-
- tdTypePre.innerHTML = ex(walkResultTypeRef(decl.value), {});
-
- let docs = getAstNode(decl.src).docs;
- if (docs != null) {
- tdDesc.innerHTML = shortDescMarkdown(docs);
- } else {
- tdDesc.textContent = "";
- }
- }
- domSectTests.classList.remove("hidden");
- }
-
- if (container.kind !== typeKinds.Struct || containerNode.fields.length > 0) {
- domHdrName.innerHTML = "
" +
- zigAnalysis.typeKinds[container.kind] +
- "
";
- domHdrName.classList.remove("hidden");
- }
- }
-
- function operatorCompare(a, b) {
- if (a === b) {
- return 0;
- } else if (a < b) {
- return -1;
- } else {
- return 1;
- }
- }
-
- function detectRootIsStd() {
- let rootMod = zigAnalysis.modules[zigAnalysis.rootMod];
- if (rootMod.table["std"] == null) {
- // no std mapped into the root module
- return false;
- }
- let stdMod = zigAnalysis.modules[rootMod.table["std"]];
- if (stdMod == null) return false;
- return rootMod.file === stdMod.file;
- }
-
- function indexTypeKinds() {
- let map = {};
- for (let i = 0; i < zigAnalysis.typeKinds.length; i += 1) {
- map[zigAnalysis.typeKinds[i]] = i;
- }
- // This is just for debugging purposes, not needed to function
- let assertList = [
- "Type",
- "Void",
- "Bool",
- "NoReturn",
- "Int",
- "Float",
- "Pointer",
- "Array",
- "Struct",
- "ComptimeFloat",
- "ComptimeInt",
- "Undefined",
- "Null",
- "Optional",
- "ErrorUnion",
- "ErrorSet",
- "Enum",
- "Union",
- "Fn",
- "Opaque",
- "Frame",
- "AnyFrame",
- "Vector",
- "EnumLiteral",
- ];
- for (let i = 0; i < assertList.length; i += 1) {
- if (map[assertList[i]] == null)
- throw new Error("No type kind '" + assertList[i] + "' found");
- }
- return map;
- }
-
- function findTypeTypeId() {
- for (let i = 0; i < zigAnalysis.types.length; i += 1) {
- if (getType(i).kind == typeKinds.Type) {
- return i;
- }
- }
- throw new Error("No type 'type' found");
- }
-
-
- function updateCurNav() {
- curNav = {
- hash: location.hash,
- mode: NAV_MODES.API,
- modNames: [],
- modObjs: [],
- declNames: [],
- declObjs: [],
- callName: null,
- activeGuide: null,
- activeGuideScrollTo: null,
- };
- curNavSearch = "";
-
- const mode = location.hash.substring(0, 3);
- let query = location.hash.substring(3);
-
- let qpos = query.indexOf("?");
- let nonSearchPart;
- if (qpos === -1) {
- nonSearchPart = query;
- } else {
- nonSearchPart = query.substring(0, qpos);
- curNavSearch = decodeURIComponent(query.substring(qpos + 1));
- }
-
- const DEFAULT_HASH = NAV_MODES.API + zigAnalysis.modules[zigAnalysis.rootMod].name;
- switch (mode) {
- case NAV_MODES.API:
- // #A;MODULE:decl.decl.decl?search-term
- curNav.mode = mode;
- {
- let parts = nonSearchPart.split(":");
- if (parts[0] == "") {
- location.hash = DEFAULT_HASH;
- } else {
- curNav.modNames = decodeURIComponent(parts[0]).split(".");
- }
-
- if (parts[1] != null) {
- curNav.declNames = decodeURIComponent(parts[1]).split(".");
- }
- }
- return;
- case NAV_MODES.GUIDES:
- curNav.mode = mode;
-
- {
- let parts = nonSearchPart.split(":");
- curNav.activeGuide = parts[0];
- if (parts[1] != null) {
- curNav.activeGuideScrollTo = decodeURIComponent(":" + parts[1]);
- }
- }
- return;
- default:
- location.hash = DEFAULT_HASH;
- return;
- }
- }
-
- function onHashChange(ev) {
- scrollHistory[curNav.hash] = scrollMonitor.map(function (x) {
- return [x, x.scrollTop]
- });
-
- if (skipNextHashChange == decodeURIComponent(location.hash)) {
- skipNextHashChange = null;
- return;
- }
- skipNextHashChange = null;
- updateCurNav();
-
- if (domSearch.value !== curNavSearch) {
- domSearch.value = curNavSearch;
- if (domSearch.value.length == 0)
- domSearchPlaceholder.classList.remove("hidden");
- else
- domSearchPlaceholder.classList.add("hidden");
- }
- render();
- if (imFeelingLucky) {
- imFeelingLucky = false;
- activateSelectedResult();
- }
-
- scroll();
- }
-
- function scroll() {
- const cur = scrollHistory[location.hash];
- if (cur) {
- for (let [elem, offset] of cur) {
- elem.scrollTo(0, offset);
- }
- } else {
- if (curNav.activeGuideScrollTo) return;
- for (let elem of scrollMonitor) {
- elem.scrollTo(0, 0);
- }
- }
- }
-
- function findSubDecl(parentTypeOrDecl, childName) {
- let parentType = parentTypeOrDecl;
- {
- // Generic functions / resolving decls
- if ("value" in parentType) {
- const rv = resolveValue(parentType.value);
- if ("type" in rv.expr) {
- const t = getType(rv.expr.type);
- parentType = t;
- if (t.kind == typeKinds.Fn && t.generic_ret != null) {
- let resolvedGenericRet = resolveValue({ expr: t.generic_ret });
-
- if ("call" in resolvedGenericRet.expr) {
- let call = zigAnalysis.calls[resolvedGenericRet.expr.call];
- let resolvedFunc = resolveValue({ expr: call.func });
- if (!("type" in resolvedFunc.expr)) return null;
- let callee = getType(resolvedFunc.expr.type);
- if (!callee.generic_ret) return null;
- resolvedGenericRet = resolveValue({ expr: callee.generic_ret });
- }
-
- if ("type" in resolvedGenericRet.expr) {
- parentType = getType(resolvedGenericRet.expr.type);
- }
- }
- }
- }
- }
-
- if (parentType.pubDecls) {
- for (let i = 0; i < parentType.pubDecls.length; i += 1) {
- let declIndex = parentType.pubDecls[i];
- let childDecl = getDecl(declIndex);
- if (childDecl.name === childName) {
- childDecl.find_subdecl_idx = declIndex;
- return childDecl;
- } else if (childDecl.is_uns) {
- let declValue = resolveValue(childDecl.value);
- if (!("type" in declValue.expr)) continue;
- let uns_container = getType(declValue.expr.type);
- let uns_res = findSubDecl(uns_container, childName);
- if (uns_res !== null) return uns_res;
- }
- }
- }
-
- if (parentType.privDecls) {
- for (let i = 0; i < parentType.privDecls.length; i += 1) {
- let declIndex = parentType.privDecls[i];
- let childDecl = getDecl(declIndex);
- if (childDecl.name === childName) {
- childDecl.find_subdecl_idx = declIndex;
- childDecl.is_private = true;
- return childDecl;
- } else if (childDecl.is_uns) {
- let declValue = resolveValue(childDecl.value);
- if (!("type" in declValue.expr)) continue;
- let uns_container = getType(declValue.expr.type);
- let uns_res = findSubDecl(uns_container, childName);
- uns_res.is_private = true;
- if (uns_res !== null) return uns_res;
- }
- }
- }
-
- return null;
- }
-
- function computeCanonicalModulePaths() {
- let list = new Array(zigAnalysis.modules.length);
- // Now we try to find all the modules from root.
- let rootMod = zigAnalysis.modules[zigAnalysis.rootMod];
- // Breadth-first to keep the path shortest possible.
- let stack = [
- {
- path: [],
- mod: rootMod,
- },
- ];
- while (stack.length !== 0) {
- let item = stack.shift();
- for (let key in item.mod.table) {
- let childModIndex = item.mod.table[key];
- if (list[childModIndex] != null) continue;
- let childMod = zigAnalysis.modules[childModIndex];
- if (childMod == null) continue;
-
- let newPath = item.path.concat([key]);
- list[childModIndex] = newPath;
- stack.push({
- path: newPath,
- mod: childMod,
- });
- }
- }
-
- for (let i = 0; i < zigAnalysis.modules.length; i += 1) {
- const p = zigAnalysis.modules[i];
- // TODO
- // declSearchIndex.add(p.name, {moduleId: i});
- }
- return list;
- }
-
- function computeCanonDeclPaths() {
- let list = new Array(zigAnalysis.decls.length);
- canonTypeDecls = new Array(zigAnalysis.types.length);
-
- for (let modI = 0; modI < zigAnalysis.modules.length; modI += 1) {
- let mod = zigAnalysis.modules[modI];
- let modNames = canonModPaths[modI];
- if (modNames === undefined) continue;
-
- let stack = [
- {
- declNames: [],
- declIndexes: [],
- type: getType(mod.main),
- },
- ];
- while (stack.length !== 0) {
- let item = stack.shift();
-
- if (isContainerType(item.type)) {
- let t = item.type;
-
- let len = t.pubDecls ? t.pubDecls.length : 0;
- for (let declI = 0; declI < len; declI += 1) {
- let declIndex = t.pubDecls[declI];
- if (list[declIndex] != null) continue;
-
- let decl = getDecl(declIndex);
-
- if (decl.is_uns) {
- let unsDeclList = [decl];
- while (unsDeclList.length != 0) {
- let unsDecl = unsDeclList.pop();
- let unsDeclVal = resolveValue(unsDecl.value);
- if (!("type" in unsDeclVal.expr)) continue;
- let unsType = getType(unsDeclVal.expr.type);
- if (!isContainerType(unsType)) continue;
- let unsPubDeclLen = unsType.pubDecls ? unsType.pubDecls.length : 0;
- for (let unsDeclI = 0; unsDeclI < unsPubDeclLen; unsDeclI += 1) {
- let childDeclIndex = unsType.pubDecls[unsDeclI];
- let childDecl = getDecl(childDeclIndex);
-
- if (childDecl.is_uns) {
- unsDeclList.push(childDecl);
- } else {
- addDeclToSearchResults(childDecl, childDeclIndex, modNames, item, list, stack);
- }
- }
- }
- } else {
- addDeclToSearchResults(decl, declIndex, modNames, item, list, stack);
- }
- }
- }
- }
- }
- window.cdp = list;
- return list;
- }
-
- function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
- let {value: declVal, seenDecls} = resolveValue(decl.value, true);
- let declNames = item.declNames.concat([decl.name]);
- let declIndexes = item.declIndexes.concat([declIndex]);
-
- if (list[declIndex] != null) return;
- list[declIndex] = {
- modNames: modNames,
- declNames: declNames,
- declIndexes: declIndexes,
- };
-
- for (let sd of seenDecls) {
- if (list[sd] != null) continue;
- list[sd] = {
- modNames: modNames,
- declNames: declNames,
- declIndexes: declIndexes,
- };
- }
-
- // add to search index
- {
- declSearchIndex.add(decl.name, { declIndex });
- }
-
-
- if ("type" in declVal.expr) {
- let value = getType(declVal.expr.type);
- if (declCanRepresentTypeKind(value.kind)) {
- canonTypeDecls[declVal.type] = declIndex;
- }
-
- if (isContainerType(value)) {
- stack.push({
- declNames: declNames,
- declIndexes: declIndexes,
- type: value,
- });
- }
-
- // Generic function
- if (typeIsGenericFn(declVal.expr.type)) {
- let ret = resolveGenericRet(value);
- if (ret != null && "type" in ret.expr) {
- let generic_type = getType(ret.expr.type);
- if (isContainerType(generic_type)) {
- stack.push({
- declNames: declNames,
- declIndexes: declIndexes,
- type: generic_type,
- });
- }
- }
- }
- }
- }
-
- function declLinkOrSrcLink(index) {
-
- let match = getCanonDeclPath(index);
- if (match) return navLink(match.modNames, match.declNames);
-
- // could not find a precomputed decl path
- const decl = getDecl(index);
-
- // try to find a public decl by scanning declRefs and declPaths
- let value = decl.value;
- let i = 0;
- while (true) {
- i += 1;
- if (i >= 10000) {
- throw "getCanonDeclPath quota exceeded"
- }
-
- if ("refPath" in value.expr) {
- value = { expr: value.expr.refPath[value.expr.refPath.length - 1] };
- continue;
- }
-
- if ("declRef" in value.expr) {
- let cp = canonDeclPaths[value.expr.declRef];
- if (cp) return navLink(cp.modNames, cp.declNames);
-
- value = getDecl(value.expr.declRef).value;
- continue;
- }
-
- if ("as" in value.expr) {
- value = {
- typeRef: zigAnalysis.exprs[value.expr.as.typeRefArg],
- expr: zigAnalysis.exprs[value.expr.as.exprArg],
- };
- continue;
- }
-
- // if we got here it means that we failed
- // produce a link to source code instead
- return sourceFileLink(decl);
-
- }
-
- }
-
- function getCanonDeclPath(index) {
- if (canonDeclPaths == null) {
- canonDeclPaths = computeCanonDeclPaths();
- }
-
- return canonDeclPaths[index];
-
-
- }
-
- function getCanonTypeDecl(index) {
- getCanonDeclPath(0);
- //let ct = (canonTypeDecls);
- return canonTypeDecls[index];
- }
-
- function escapeHtml(text) {
- return text.replace(/[&"<>]/g, function(m) {
- return escapeHtmlReplacements[m];
- });
- }
-
- function shortDesc(docs) {
- const trimmed_docs = docs.trim();
- let index = trimmed_docs.indexOf("\n\n");
- let cut = false;
-
- if (index < 0 || index > 130) {
- if (trimmed_docs.length > 130) {
- index = 130;
- cut = true;
- } else {
- index = trimmed_docs.length;
- }
- }
-
- let slice = trimmed_docs.slice(0, index);
- if (cut) slice += "...";
- return slice;
- }
-
- function shortDescMarkdown(docs) {
- return markdown(shortDesc(docs));
- }
-
- function parseGuides() {
- for (let j = 0; j < zigAnalysis.guideSections.length; j += 1) {
- const section = zigAnalysis.guideSections[j];
- for (let i = 0; i < section.guides.length; i += 1) {
- let reader = new commonmark.Parser({ smart: true });
- const guide = section.guides[i];
-
- // Find the first text thing to use as a sidebar title
- guide.title = null;
- guide.toc = "";
-
- // Discover Title & TOC for this guide
- {
- let reader = new commonmark.Parser({smart: true});
- let ast = reader.parse(guide.body);
- let walker = ast.walker();
- let heading_idx = 0;
- let event, node, doc, last, last_ul;
- while ((event = walker.next())) {
- node = event.node;
- if (event.entering) {
- if (node.type === 'document') {
- doc = node;
- continue;
- }
-
-
- if (node.next) {
- walker.resumeAt(node.next, true);
- } else {
- walker.resumeAt(node, false);
- }
- node.unlink();
-
- if (node.type === 'heading') {
- if (node.level == 1) {
- if (guide.title == null) {
- let doc_node = new commonmark.Node("document", node.sourcepos);
- while (node.firstChild) {
- doc_node.appendChild(node.firstChild);
- }
- let writer = new commonmark.HtmlRenderer();
- let result = writer.render(doc_node);
- guide.title = result;
- }
-
- continue; // don't index H1
- }
-
- // turn heading node into list item & add link node to it
- {
- node._type = "link";
- node.destination = NAV_MODES.GUIDES + guide.name + ":" + heading_idx;
- heading_idx += 1;
- let listItem = new commonmark.Node("item", node.sourcepos);
- // TODO: strip links from inside node
- listItem.appendChild(node);
- listItem.level = node.level;
- node = listItem;
- }
-
- if (last_ul) {
- // are we inside or outside of it?
-
- let target_ul = last_ul;
- while(target_ul.level > node.level) {
- target_ul = target_ul.parent;
- }
- while(target_ul.level < node.level) {
- let ul_node = new commonmark.Node("list", node.sourcepos);
- ul_node.level = target_ul.level + 1;
- ul_node.listType = "bullet";
- ul_node.listStart = null;
- target_ul.appendChild(ul_node);
- target_ul = ul_node;
- }
-
- target_ul.appendChild(node);
- last_ul = target_ul;
- } else {
- let ul_node = new commonmark.Node("list", node.sourcepos);
- ul_node.level = 2;
- ul_node.listType = "bullet";
- ul_node.listStart = null;
- doc.prependChild(ul_node);
-
- while (ul_node.level < node.level) {
- let current_ul_node = new commonmark.Node("list", node.sourcepos);
- current_ul_node.level = ul_node.level + 1;
- current_ul_node.listType = "bullet";
- current_ul_node.listStart = null;
- ul_node.appendChild(current_ul_node);
- ul_node = current_ul_node;
- }
-
- last_ul = ul_node;
-
- ul_node.appendChild(node);
- }
- }
- }
- }
-
- let writer = new commonmark.HtmlRenderer();
- let result = writer.render(ast);
- guide.toc = result;
- }
-
- // Index this guide
- {
- // let walker = guide.ast.walker();
- // let event, node;
- // while ((event = walker.next())) {
- // node = event.node;
- // if (event.entering == true && node.type === 'text') {
- // indexTextForGuide(j, i, node);
- // }
- // }
- }
- }
- }
- }
-
- function indexTextForGuide(section_idx, guide_idx, node) {
- const terms = node.literal.split(" ");
- for (let i = 0; i < terms.length; i += 1) {
- const t = terms[i];
- if (!guidesSearchIndex[t]) guidesSearchIndex[t] = new Set();
- node.guide = { section_idx, guide_idx };
- guidesSearchIndex[t].add(node);
- }
- }
-
-
- function markdown(input, contextType) {
- const parsed = new commonmark.Parser({ smart: true }).parse(input);
-
- // Look for decl references in inline code (`ref`)
- const walker = parsed.walker();
- let event;
- while ((event = walker.next())) {
- const node = event.node;
- if (node.type === "code") {
- const declHash = detectDeclPath(node.literal, contextType);
- if (declHash) {
- const link = new commonmark.Node("link");
- link.destination = declHash;
- node.insertBefore(link);
- link.appendChild(node);
- }
- }
- }
-
- return new commonmark.HtmlRenderer({ safe: true }).render(parsed);
-
- }
-
-
-
- // function detectDeclPath(text, context) {
- // let result = "";
- // let separator = ":";
- // const components = text.split(".");
- // let curDeclOrType = undefined;
-
- // let curContext = context;
- // let limit = 10000;
- // while (curContext) {
- // limit -= 1;
-
- // if (limit == 0) {
- // throw "too many iterations";
- // }
-
- // curDeclOrType = findSubDecl(curContext, components[0]);
-
- // if (!curDeclOrType) {
- // if (curContext.parent_container == null) break;
- // curContext = getType(curContext.parent_container);
- // continue;
- // }
-
- // if (curContext == context) {
- // separator = '.';
- // result = location.hash + separator + components[0];
- // } else {
- // // We had to go up, which means we need a new path!
- // const canonPath = getCanonDeclPath(curDeclOrType.find_subdecl_idx);
- // if (!canonPath) return;
-
- // let lastModName = canonPath.modNames[canonPath.modNames.length - 1];
- // let fullPath = lastModName + ":" + canonPath.declNames.join(".");
-
- // separator = '.';
- // result = "#A;" + fullPath;
- // }
-
- // break;
- // }
-
- // if (!curDeclOrType) {
- // for (let i = 0; i < zigAnalysis.modules.length; i += 1) {
- // const p = zigAnalysis.modules[i];
- // if (p.name == components[0]) {
- // curDeclOrType = getType(p.main);
- // result += "#A;" + components[0];
- // break;
- // }
- // }
- // }
-
- // if (!curDeclOrType) return null;
-
- // for (let i = 1; i < components.length; i += 1) {
- // curDeclOrType = findSubDecl(curDeclOrType, components[i]);
- // if (!curDeclOrType) return null;
- // result += separator + components[i];
- // separator = '.';
- // }
-
- // return result;
-
- // }
-
- function activateSelectedResult() {
- if (domSectSearchResults.classList.contains("hidden")) {
- return;
- }
-
- const searchResults = domListSearchResults.getElementsByTagName("li");
- let liDom = searchResults[curSearchIndex];
- if (liDom == null && searchResults.length !== 0) {
- liDom = searchResults[0];
- }
- if (liDom != null) {
- let aDom = liDom.children[0];
- location.href = aDom.getAttribute("href");
- curSearchIndex = -1;
- }
- domSearch.blur();
- }
-
- // hide the modal if it's visible or return to the previous result page and unfocus the search
- function onEscape(ev) {
- if (isModalVisible(domHelpModal)) {
- hideModal(domHelpModal);
- ev.preventDefault();
- ev.stopPropagation();
- } else if (isModalVisible(domPrefsModal)) {
- hideModal(domPrefsModal);
- ev.preventDefault();
- ev.stopPropagation();
- } else {
- domSearch.value = "";
- domSearch.blur();
- domSearchPlaceholder.classList.remove("hidden");
- curSearchIndex = -1;
- ev.preventDefault();
- ev.stopPropagation();
- startSearch();
- }
- }
-
-
- function onSearchKeyDown(ev) {
- switch (getKeyString(ev)) {
- case "Enter":
- // detect if this search changes anything
- let terms1 = getSearchTerms();
- startSearch();
- updateCurNav();
- let terms2 = getSearchTerms();
- // we might have to wait for onHashChange to trigger
- imFeelingLucky = terms1.join(" ") !== terms2.join(" ");
- if (!imFeelingLucky) activateSelectedResult();
-
- ev.preventDefault();
- ev.stopPropagation();
- return;
- case "Esc":
- onEscape(ev);
- return
- case "Up":
- moveSearchCursor(-1);
- ev.preventDefault();
- ev.stopPropagation();
- return;
- case "Down":
- // TODO: make the page scroll down if the search cursor is out of the screen
- moveSearchCursor(1);
- ev.preventDefault();
- ev.stopPropagation();
- return;
- default:
- // Search is triggered via an `input` event handler, not on arbitrary `keydown` events.
- ev.stopPropagation();
- return;
- }
- }
-
- let domDotsToggleTimeout = null;
- function onSearchInput(ev) {
- curSearchIndex = -1;
-
- let replaced = domSearch.value.replaceAll(".", " ")
-
- // Ping red the help text if the user typed a dot.
- if (replaced != domSearch.value) {
- domSearchHelpSummary.classList.remove("normal");
- if (domDotsToggleTimeout != null) {
- clearTimeout(domDotsToggleTimeout);
- domDotsToggleTimeout = null;
- }
- domDotsToggleTimeout = setTimeout(function () {
- domSearchHelpSummary.classList.add("normal");
- }, 1000);
- }
-
- replaced = replaced.replace(/ +/g, ' ');
- if (replaced != domSearch.value) {
- domSearch.value = replaced;
- }
-
- startAsyncSearch();
- }
-
- function moveSearchCursor(dir) {
- const searchResults = domListSearchResults.getElementsByTagName("li");
- if (
- curSearchIndex < 0 ||
- curSearchIndex >= searchResults.length
- ) {
- if (dir > 0) {
- curSearchIndex = -1 + dir;
- } else if (dir < 0) {
- curSearchIndex = searchResults.length + dir;
- }
- } else {
- curSearchIndex += dir;
- }
- if (curSearchIndex < 0) {
- curSearchIndex = 0;
- }
- if (curSearchIndex >= searchResults.length) {
- curSearchIndex = searchResults.length - 1;
- }
- renderSearchCursor();
- }
-
- function getKeyString(ev) {
- let name;
- let ignoreShift = false;
- switch (ev.which) {
- case 13:
- name = "Enter";
- break;
- case 27:
- name = "Esc";
- break;
- case 38:
- name = "Up";
- break;
- case 40:
- name = "Down";
- break;
- default:
- ignoreShift = true;
- name =
- ev.key != null
- ? ev.key
- : String.fromCharCode(ev.charCode || ev.keyCode);
- }
- if (!ignoreShift && ev.shiftKey) name = "Shift+" + name;
- if (ev.altKey) name = "Alt+" + name;
- if (ev.ctrlKey) name = "Ctrl+" + name;
- return name;
- }
-
- function onWindowKeyDown(ev) {
- switch (getKeyString(ev)) {
- case "Esc":
- onEscape(ev);
- break;
- case "/":
- if (!getPrefSlashSearch()) break;
- // fallthrough
- case "s":
- if (!isModalVisible(domHelpModal) && !isModalVisible(domPrefsModal)) {
- if (ev.target == domSearch) break;
-
- domSearch.focus();
- domSearch.select();
- domDocs.scrollTo(0, 0);
- ev.preventDefault();
- ev.stopPropagation();
- startAsyncSearch();
- }
- break;
- case "?":
- if (!canToggleModal) break;
-
- if (isModalVisible(domPrefsModal)) {
- hideModal(domPrefsModal);
- }
-
- // toggle the help modal
- if (isModalVisible(domHelpModal)) {
- hideModal(domHelpModal);
- } else {
- showModal(domHelpModal);
- }
- ev.preventDefault();
- ev.stopPropagation();
- break;
- case "p":
- if (!canToggleModal) break;
-
- if (isModalVisible(domHelpModal)) {
- hideModal(domHelpModal);
- }
-
- // toggle the preferences modal
- if (isModalVisible(domPrefsModal)) {
- hideModal(domPrefsModal);
- } else {
- showModal(domPrefsModal);
- }
- ev.preventDefault();
- ev.stopPropagation();
- }
- }
-
- function isModalVisible(modal) {
- return !modal.classList.contains("hidden");
- }
-
- function showModal(modal) {
- modal.classList.remove("hidden");
- modal.style.left =
- window.innerWidth / 2 - modal.clientWidth / 2 + "px";
- modal.style.top =
- window.innerHeight / 2 - modal.clientHeight / 2 + "px";
- const firstInput = modal.querySelector("input");
- if (firstInput) {
- firstInput.focus();
- } else {
- modal.focus();
- }
- domSearch.blur();
- domBanner.inert = true;
- domMain.inert = true;
- }
-
- function hideModal(modal) {
- modal.classList.add("hidden");
- domBanner.inert = false;
- domMain.inert = false;
- modal.blur();
- }
-
- function clearAsyncSearch() {
- if (searchTimer != null) {
- clearTimeout(searchTimer);
- searchTimer = null;
- }
- }
-
- function startAsyncSearch() {
- clearAsyncSearch();
- searchTimer = setTimeout(startSearch, 100);
- }
- function startSearch() {
- clearAsyncSearch();
- let oldHash = location.hash;
- let parts = oldHash.split("?");
- let newPart2 = domSearch.value === "" ? "" : "?" + domSearch.value;
- location.replace(parts.length === 1 ? oldHash + newPart2 : parts[0] + newPart2);
- }
- function getSearchTerms() {
- let list = curNavSearch.trim().split(/[ \r\n\t]+/);
- return list;
- }
-
- function renderSearchGuides() {
- const searchTrimmed = false;
- let ignoreCase = curNavSearch.toLowerCase() === curNavSearch;
-
- let terms = getSearchTerms();
- let matchedItems = new Set();
-
- for (let i = 0; i < terms.length; i += 1) {
- const nodes = guidesSearchIndex[terms[i]];
- if (nodes) {
- for (const n of nodes) {
- matchedItems.add(n);
- }
- }
- }
-
-
-
- if (matchedItems.size !== 0) {
- // Build up the list of search results
- let matchedItemsHTML = "";
-
- for (const node of matchedItems) {
- const text = node.literal;
- const href = "";
-
- matchedItemsHTML += "
" + text + "";
- }
-
- // Replace the search results using our newly constructed HTML string
- domListSearchResults.innerHTML = matchedItemsHTML;
- if (searchTrimmed) {
- domSectSearchAllResultsLink.classList.remove("hidden");
- }
- renderSearchCursor();
-
- domSectSearchResults.classList.remove("hidden");
- } else {
- domSectSearchNoResults.classList.remove("hidden");
- }
- }
-
- function renderSearchAPI() {
- domSectSearchResults.prepend(
- domSearchHelp.parentElement.removeChild(domSearchHelp)
- );
- if (canonDeclPaths == null) {
- canonDeclPaths = computeCanonDeclPaths();
- }
- let declSet = new Set();
- let otherDeclSet = new Set(); // for low quality results
- let declScores = {};
-
- let ignoreCase = curNavSearch.toLowerCase() === curNavSearch;
- let term_list = getSearchTerms();
- for (let i = 0; i < term_list.length; i += 1) {
- let term = term_list[i];
- let result = declSearchIndex.search(term.toLowerCase());
- if (result == null) {
- domSectSearchNoResults.prepend(
- domSearchHelp.parentElement.removeChild(domSearchHelp)
- );
- domSectSearchNoResults.classList.remove("hidden");
-
- domSectSearchResults.classList.add("hidden");
- return;
- }
-
- let termSet = new Set();
- let termOtherSet = new Set();
-
- for (let list of [result.full, result.partial]) {
- for (let r of list) {
- const d = r.declIndex;
- const decl = getDecl(d);
- const canonPath = getCanonDeclPath(d);
-
- // collect unconditionally for the first term
- if (i == 0) {
- declSet.add(d);
- } else {
- // path intersection for subsequent terms
- let found = false;
- for (let p of canonPath.declIndexes) {
- if (declSet.has(p)) {
- found = true;
- break;
- }
- }
- if (!found) {
- otherDeclSet.add(d);
- } else {
- termSet.add(d);
- }
- }
-
- if (declScores[d] == undefined) declScores[d] = 0;
-
- // scores (lower is better)
- let decl_name = decl.name;
- if (ignoreCase) decl_name = decl_name.toLowerCase();
-
- // shallow path are preferable
- const path_depth = canonPath.declNames.length * 50;
- // matching the start of a decl name is good
- const match_from_start = decl_name.startsWith(term) ? -term.length * (2 - ignoreCase) : (decl_name.length - term.length) + 1;
- // being a perfect match is good
- const is_full_match = (decl_name === term) ? -decl_name.length * (1 - ignoreCase) : Math.abs(decl_name.length - term.length);
- // matching the end of a decl name is good
- const matches_the_end = decl_name.endsWith(term) ? -term.length * (1 - ignoreCase) : (decl_name.length - term.length) + 1;
- // explicitly penalizing scream case decls
- const decl_is_scream_case = decl.name.toUpperCase() != decl.name ? 0 : decl.name.length;
-
- const score = path_depth
- + match_from_start
- + is_full_match
- + matches_the_end
- + decl_is_scream_case;
-
- declScores[d] += score;
- }
- }
- if (i != 0) {
- for (let d of declSet) {
- if (termSet.has(d)) continue;
- let found = false;
- for (let p of getCanonDeclPath(d).declIndexes) {
- if (termSet.has(p) || otherDeclSet.has(p)) {
- found = true;
- break;
- }
- }
- if (found) {
- declScores[d] = declScores[d] / term_list.length;
- }
-
- termOtherSet.add(d);
- }
- declSet = termSet;
- for (let d of termOtherSet) {
- otherDeclSet.add(d);
- }
-
- }
- }
-
- let matchedItems = {
- high_quality: [],
- low_quality: [],
- };
- for (let idx of declSet) {
- matchedItems.high_quality.push({ points: declScores[idx], declIndex: idx })
- }
- for (let idx of otherDeclSet) {
- matchedItems.low_quality.push({ points: declScores[idx], declIndex: idx })
- }
-
- matchedItems.high_quality.sort(function(a, b) {
- let cmp = operatorCompare(a.points, b.points);
- return cmp;
- });
- matchedItems.low_quality.sort(function(a, b) {
- let cmp = operatorCompare(a.points, b.points);
- return cmp;
- });
-
- // Build up the list of search results
- let matchedItemsHTML = "";
-
- for (let list of [matchedItems.high_quality, matchedItems.low_quality]) {
- if (list == matchedItems.low_quality && list.length > 0) {
- matchedItemsHTML += "
"
- }
- for (let result of list) {
- const points = result.points;
- const match = result.declIndex;
-
- let canonPath = getCanonDeclPath(match);
- if (canonPath == null) continue;
-
- let lastModName = canonPath.modNames[canonPath.modNames.length - 1];
- let text = lastModName + "." + canonPath.declNames.join(".");
-
-
- const href = navLink(canonPath.modNames, canonPath.declNames);
-
- matchedItemsHTML += "
" + text + "";
- }
- }
-
- // Replace the search results using our newly constructed HTML string
- domListSearchResults.innerHTML = matchedItemsHTML;
- renderSearchCursor();
-
- domSectSearchResults.classList.remove("hidden");
- }
-
-
-
- function renderSearchCursor() {
- const searchResults = domListSearchResults.getElementsByTagName("li");
- for (let i = 0; i < searchResults.length; i += 1) {
- let liDom = searchResults[i];
- if (curSearchIndex === i) {
- liDom.classList.add("selected");
- } else {
- liDom.classList.remove("selected");
- }
- }
- }
-
- function scrollGuidesTop(ev) {
- document.getElementById("activeGuide").children[0].scrollIntoView({
- behavior: "smooth",
- });
- ev.preventDefault();
- ev.stopPropagation();
- }
- document.scrollGuidesTop = scrollGuidesTop;
-
- function scrollToHeading(id, alreadyThere) {
- // Don't scroll if the current location has a scrolling history.
- if (scrollHistory[location.hash]) return;
-
- const c = document.getElementById(id);
- if (c && alreadyThere) {
- requestAnimationFrame(() => c.scrollIntoView({behavior: "smooth"}));
- } else {
- requestAnimationFrame(() => c.scrollIntoView());
- }
- return;
- }
- // function indexNodesToCalls() {
- // let map = {};
- // for (let i = 0; i < zigAnalysis.calls.length; i += 1) {
- // let call = zigAnalysis.calls[i];
- // let fn = zigAnalysis.fns[call.fn];
- // if (map[fn.src] == null) {
- // map[fn.src] = [i];
- // } else {
- // map[fn.src].push(i);
- // }
- // }
- // return map;
- // }
-
- function byNameProperty(a, b) {
- return operatorCompare(a.name, b.name);
- }
-
-
- function getDecl(idx) {
- const decl = zigAnalysis.decls[idx];
- return {
- name: decl[0],
- kind: decl[1],
- src: decl[2],
- value: decl[3],
- decltest: decl[4],
- is_uns: decl[5],
- parent_container: decl[6],
- };
- }
-
- function getAstNode(idx) {
- const ast = zigAnalysis.astNodes[idx];
- return {
- file: ast[0],
- line: ast[1],
- col: ast[2],
- name: ast[3],
- code: ast[4],
- docs: ast[5],
- fields: ast[6],
- comptime: ast[7],
- };
- }
-
- function getFile(idx) {
- const file = zigAnalysis.files[idx];
- return {
- name: file[0],
- modIndex: file[1],
- };
- }
-
- function getType(idx) {
- const ty = zigAnalysis.types[idx];
- switch (ty[0]) {
- default:
- throw "unhandled type kind!";
- case typeKinds.Unanalyzed:
- throw "unanalyzed type!";
- case typeKinds.Type:
- case typeKinds.Void:
- case typeKinds.Bool:
- case typeKinds.NoReturn:
- case typeKinds.Int:
- case typeKinds.Float:
- return { kind: ty[0], name: ty[1] };
- case typeKinds.Pointer:
- return {
- kind: ty[0],
- size: ty[1],
- child: ty[2],
- sentinel: ty[3],
- align: ty[4],
- address_space: ty[5],
- bit_start: ty[6],
- host_size: ty[7],
- is_ref: ty[8],
- is_allowzero: ty[9],
- is_mutable: ty[10],
- is_volatile: ty[11],
- has_sentinel: ty[12],
- has_align: ty[13],
- has_addrspace: ty[14],
- has_bit_range: ty[15],
- };
- case typeKinds.Array:
- return {
- kind: ty[0],
- len: ty[1],
- child: ty[2],
- sentinel: ty[3],
- };
- case typeKinds.Struct:
- return {
- kind: ty[0],
- name: ty[1],
- src: ty[2],
- privDecls: ty[3],
- pubDecls: ty[4],
- field_types: ty[5],
- field_defaults: ty[6],
- backing_int: ty[7],
- is_tuple: ty[8],
- line_number: ty[9],
- parent_container: ty[10],
- layout: ty[11],
- };
- case typeKinds.ComptimeExpr:
- case typeKinds.ComptimeFloat:
- case typeKinds.ComptimeInt:
- case typeKinds.Undefined:
- case typeKinds.Null:
- return { kind: ty[0], name: ty[1] };
- case typeKinds.Optional:
- return {
- kind: ty[0],
- name: ty[1],
- child: ty[2],
- };
- case typeKinds.ErrorUnion:
- return {
- kind: ty[0],
- lhs: ty[1],
- rhs: ty[2],
- };
- case typeKinds.InferredErrorUnion:
- return {
- kind: ty[0],
- payload: ty[1],
- };
- case typeKinds.ErrorSet:
- return {
- kind: ty[0],
- name: ty[1],
- fields: ty[2],
- };
- case typeKinds.Enum:
- return {
- kind: ty[0],
- name: ty[1],
- src: ty[2],
- privDecls: ty[3],
- pubDecls: ty[4],
- tag: ty[5],
- values: ty[6],
- nonexhaustive: ty[7],
- parent_container: ty[8],
- };
- case typeKinds.Union:
- return {
- kind: ty[0],
- name: ty[1],
- src: ty[2],
- privDecls: ty[3],
- pubDecls: ty[4],
- field_types: ty[5],
- tag: ty[6],
- auto_tag: ty[7],
- parent_container: ty[8],
- layout: ty[9],
- };
- case typeKinds.Fn:
- return {
- kind: ty[0],
- name: ty[1],
- src: ty[2],
- ret: ty[3],
- generic_ret: ty[4],
- params: ty[5],
- lib_name: ty[6],
- is_var_args: ty[7],
- is_inferred_error: ty[8],
- has_lib_name: ty[9],
- has_cc: ty[10],
- cc: ty[11],
- align: ty[12],
- has_align: ty[13],
- is_test: ty[14],
- is_extern: ty[15],
- };
- case typeKinds.Opaque:
- return {
- kind: ty[0],
- name: ty[1],
- src: ty[2],
- privDecls: ty[3],
- pubDecls: ty[4],
- parent_container: ty[5],
- };
- case typeKinds.Frame:
- case typeKinds.AnyFrame:
- case typeKinds.Vector:
- case typeKinds.EnumLiteral:
- return { kind: ty[0], name: ty[1] };
- }
- }
-
- function getLocalStorage() {
- if ("localStorage" in window) {
- try {
- return window.localStorage;
- } catch (ignored) {
- // localStorage may be disabled (SecurityError)
- }
- }
- // If localStorage isn't available, persist preferences only for the current session
- const sessionPrefs = {};
- return {
- getItem(key) {
- return key in sessionPrefs ? sessionPrefs[key] : null;
- },
- setItem(key, value) {
- sessionPrefs[key] = String(value);
- },
- };
- }
-
- function loadPrefs() {
- const storedPrefSlashSearch = prefs.getItem("slashSearch");
- if (storedPrefSlashSearch === null) {
- // Slash search defaults to enabled for all browsers except Firefox
- setPrefSlashSearch(navigator.userAgent.indexOf("Firefox") === -1);
- } else {
- setPrefSlashSearch(storedPrefSlashSearch === "true");
- }
- }
-
- function getPrefSlashSearch() {
- return prefs.getItem("slashSearch") === "true";
- }
-
- function setPrefSlashSearch(enabled) {
- prefs.setItem("slashSearch", String(enabled));
- domPrefSlashSearch.checked = enabled;
- const searchKeys = enabled ? "
/ or
s" : "
s";
- domSearchKeys.innerHTML = searchKeys;
- domSearchPlaceholderText.innerHTML = searchKeys + " to search,
? for more options";
- }
-})();
-
-function toggleExpand(event) {
- const parent = event.target.parentElement;
- parent.toggleAttribute("open");
-
- if (!parent.open && parent.getBoundingClientRect().top < 0) {
- parent.parentElement.parentElement.scrollIntoView(true);
- }
-}
-
-function RadixTree() {
- this.root = null;
-
- RadixTree.prototype.search = function(query) {
- return this.root.search(query);
-
- }
-
- RadixTree.prototype.add = function(declName, value) {
- if (this.root == null) {
- this.root = new Node(declName.toLowerCase(), null, [value]);
- } else {
- this.root.add(declName.toLowerCase(), value);
- }
-
- const not_scream_case = declName.toUpperCase() != declName;
- let found_separator = false;
- for (let i = 1; i < declName.length; i += 1) {
- if (declName[i] == '_' || declName[i] == '.') {
- found_separator = true;
- continue;
- }
-
-
- if (found_separator || (declName[i].toLowerCase() !== declName[i])) {
- if (declName.length > i + 1
- && declName[i + 1].toLowerCase() != declName[i + 1]) continue;
- let suffix = declName.slice(i);
- this.root.add(suffix.toLowerCase(), value);
- found_separator = false;
- }
- }
- }
-
- function Node(labels, next, values) {
- this.labels = labels;
- this.next = next;
- this.values = values;
- }
-
- Node.prototype.isCompressed = function() {
- return !Array.isArray(this.next);
- }
-
- Node.prototype.search = function(word) {
- let full_matches = [];
- let partial_matches = [];
- let subtree_root = null;
-
- let cn = this;
- char_loop: for (let i = 0; i < word.length;) {
- if (cn.isCompressed()) {
- for (let j = 0; j < cn.labels.length; j += 1) {
- let current_idx = i + j;
-
- if (current_idx == word.length) {
- partial_matches = cn.values;
- subtree_root = cn.next;
- break char_loop;
- }
-
- if (word[current_idx] != cn.labels[j]) return null;
- }
-
- // the full label matched
- let new_idx = i + cn.labels.length;
- if (new_idx == word.length) {
- full_matches = cn.values;
- subtree_root = cn.next;
- break char_loop;
- }
-
-
- i = new_idx;
- cn = cn.next;
- continue;
- } else {
- for (let j = 0; j < cn.labels.length; j += 1) {
- if (word[i] == cn.labels[j]) {
- if (i == word.length - 1) {
- full_matches = cn.values[j];
- subtree_root = cn.next[j];
- break char_loop;
- }
-
- let next = cn.next[j];
- if (next == null) return null;
- cn = next;
- i += 1;
- continue char_loop;
- }
- }
-
- // didn't find a match
- return null;
- }
- }
-
- // Match was found, let's collect all other
- // partial matches from the subtree
- let stack = [subtree_root];
- let node;
- while (node = stack.pop()) {
- if (node.isCompressed()) {
- partial_matches = partial_matches.concat(node.values);
- if (node.next != null) {
- stack.push(node.next);
- }
- } else {
- for (let v of node.values) {
- partial_matches = partial_matches.concat(v);
- }
-
- for (let n of node.next) {
- if (n != null) stack.push(n);
- }
- }
- }
-
- return { full: full_matches, partial: partial_matches };
- }
-
- Node.prototype.add = function(word, value) {
- let cn = this;
- char_loop: for (let i = 0; i < word.length;) {
- if (cn.isCompressed()) {
- for (let j = 0; j < cn.labels.length; j += 1) {
- let current_idx = i + j;
-
- if (current_idx == word.length) {
- if (j < cn.labels.length - 1) {
- let node = new Node(cn.labels.slice(j), cn.next, cn.values);
- cn.labels = cn.labels.slice(0, j);
- cn.next = node;
- cn.values = [];
- }
- cn.values.push(value);
- return;
- }
-
- if (word[current_idx] == cn.labels[j]) continue;
-
- // if we're here, a mismatch was found
- if (j != cn.labels.length - 1) {
- // create a suffix node
- const label_suffix = cn.labels.slice(j + 1);
- let node = new Node(label_suffix, cn.next, [...cn.values]);
- cn.next = node;
- cn.values = [];
- }
-
- // turn current node into a split node
- let node = null;
- let word_values = [];
- if (current_idx == word.length - 1) {
- // mismatch happened in the last character of word
- // meaning that the current node should hold its value
- word_values.push(value);
- } else {
- node = new Node(word.slice(current_idx + 1), null, [value]);
- }
-
- cn.labels = cn.labels[j] + word[current_idx];
- cn.next = [cn.next, node];
- cn.values = [cn.values, word_values];
-
- if (j != 0) {
- // current node must be turned into a prefix node
- let splitNode = new Node(cn.labels, cn.next, cn.values);
- cn.labels = word.slice(i, current_idx);
- cn.next = splitNode;
- cn.values = [];
- }
-
- return;
- }
- // label matched fully with word, are there any more chars?
- const new_idx = i + cn.labels.length;
- if (new_idx == word.length) {
- cn.values.push(value);
- return;
- } else {
- if (cn.next == null) {
- let node = new Node(word.slice(new_idx), null, [value]);
- cn.next = node;
- return;
- } else {
- cn = cn.next;
- i = new_idx;
- continue;
- }
- }
- } else { // node is not compressed
- let letter = word[i];
- for (let j = 0; j < cn.labels.length; j += 1) {
- if (letter == cn.labels[j]) {
- if (i == word.length - 1) {
- cn.values[j].push(value);
- return;
- }
- if (cn.next[j] == null) {
- let node = new Node(word.slice(i + 1), null, [value]);
- cn.next[j] = node;
- return;
- } else {
- cn = cn.next[j];
- i += 1;
- continue char_loop;
- }
- }
- }
-
- // if we're here we didn't find a match
- cn.labels += letter;
- if (i == word.length - 1) {
- cn.next.push(null);
- cn.values.push([value]);
- } else {
- let node = new Node(word.slice(i + 1), null, [value]);
- cn.next.push(node);
- cn.values.push([]);
- }
- return;
- }
- }
- }
-}
-
-
-function slugify(str) {
- return str.toLowerCase().trim().replace(/[^\w\s-]/g, '').replace(/[\s_-]+/g, '-').replace(/^-+|-+$/g, '');
-}
-
diff --git a/docs/src/builtin/builtin.zig.html b/docs/src/builtin/builtin.zig.html
deleted file mode 100644
index 8a58070..0000000
--- a/docs/src/builtin/builtin.zig.html
+++ /dev/null
@@ -1,177 +0,0 @@
-
-
-
-
-
builtin.zig - source view
-
-
-
-
-
-
const std = @import("std");
-
-
-pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable;
-pub const zig_version_string = "0.12.0-dev.2858+7230b68b3";
-pub const zig_backend = std.builtin.CompilerBackend.stage2_llvm;
-
-pub const output_mode = std.builtin.OutputMode.Obj;
-pub const link_mode = std.builtin.LinkMode.Static;
-pub const is_test = false;
-pub const single_threaded = false;
-pub const abi = std.Target.Abi.none;
-pub const cpu: std.Target.Cpu = .{
- .arch = .aarch64,
- .model = &std.Target.aarch64.cpu.generic,
- .features = std.Target.aarch64.featureSet(&[_]std.Target.aarch64.Feature{
- .enable_select_opt,
- .ete,
- .fp_armv8,
- .fuse_adrp_add,
- .fuse_aes,
- .neon,
- .trbe,
- .use_postra_scheduler,
- }),
-};
-pub const os = std.Target.Os{
- .tag = .macos,
- .version_range = .{ .semver = .{
- .min = .{
- .major = 14,
- .minor = 3,
- .patch = 1,
- },
- .max = .{
- .major = 14,
- .minor = 3,
- .patch = 1,
- },
- }},
-};
-pub const target: std.Target = .{
- .cpu = cpu,
- .os = os,
- .abi = abi,
- .ofmt = object_format,
- .dynamic_linker = std.Target.DynamicLinker.init("/usr/lib/dyld"),
-};
-pub const object_format = std.Target.ObjectFormat.macho;
-pub const mode = std.builtin.OptimizeMode.Debug;
-pub const link_libc = true;
-pub const link_libcpp = false;
-pub const have_error_return_tracing = true;
-pub const valgrind_support = false;
-pub const sanitize_thread = false;
-pub const position_independent_code = true;
-pub const position_independent_executable = true;
-pub const strip_debug_info = false;
-pub const code_model = std.builtin.CodeModel.default;
-pub const omit_frame_pointer = false;
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/endpoint.zig.html b/docs/src/zap/endpoint.zig.html
deleted file mode 100644
index 9a0f4e2..0000000
--- a/docs/src/zap/endpoint.zig.html
+++ /dev/null
@@ -1,456 +0,0 @@
-
-
-
-
-
endpoint.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const zap = @import("zap.zig");
-const auth = @import("http_auth.zig");
-
-const Endpoint = @This();
-
-
-
-const Request = zap.Request;
-const ListenerSettings = zap.HttpListenerSettings;
-const HttpListener = zap.HttpListener;
-
-
-pub const RequestFn = *const fn (self: *Endpoint, r: Request) void;
-
-
-pub const Settings = struct {
-
- path: []const u8,
-
- get: ?RequestFn = null,
-
- post: ?RequestFn = null,
-
- put: ?RequestFn = null,
-
- delete: ?RequestFn = null,
-
- patch: ?RequestFn = null,
-
- options: ?RequestFn = null,
-
- unauthorized: ?RequestFn = null,
-};
-
-settings: Settings,
-
-
-
-
-pub fn init(s: Settings) Endpoint {
- return .{
- .settings = .{
- .path = s.path,
- .get = s.get orelse &nop,
- .post = s.post orelse &nop,
- .put = s.put orelse &nop,
- .delete = s.delete orelse &nop,
- .patch = s.patch orelse &nop,
- .options = s.options orelse &nop,
- .unauthorized = s.unauthorized orelse &nop,
- },
- };
-}
-
-
-
-fn nop(self: *Endpoint, r: Request) void {
- _ = self;
- _ = r;
-}
-
-
-pub fn onRequest(self: *Endpoint, r: zap.Request) void {
- switch (r.methodAsEnum()) {
- .GET => self.settings.get.?(self, r),
- .POST => self.settings.post.?(self, r),
- .PUT => self.settings.put.?(self, r),
- .DELETE => self.settings.delete.?(self, r),
- .PATCH => self.settings.patch.?(self, r),
- .OPTIONS => self.settings.options.?(self, r),
- else => return,
- }
-}
-
-
-
-pub fn Authenticating(comptime Authenticator: type) type {
- return struct {
- authenticator: *Authenticator,
- ep: *Endpoint,
- auth_endpoint: Endpoint,
- const Self = @This();
-
-
-
-
- pub fn init(e: *Endpoint, authenticator: *Authenticator) Self {
- return .{
- .authenticator = authenticator,
- .ep = e,
- .auth_endpoint = Endpoint.init(.{
- .path = e.settings.path,
-
-
-
-
- .get = if (e.settings.get != null) get else null,
- .post = if (e.settings.post != null) post else null,
- .put = if (e.settings.put != null) put else null,
- .delete = if (e.settings.delete != null) delete else null,
- .patch = if (e.settings.patch != null) patch else null,
- .options = if (e.settings.options != null) options else null,
- .unauthorized = e.settings.unauthorized,
- }),
- };
- }
-
-
-
-
- pub fn endpoint(self: *Self) *Endpoint {
- return &self.auth_endpoint;
- }
-
-
-
- pub fn get(e: *Endpoint, r: zap.Request) void {
- const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
- switch (authEp.authenticator.authenticateRequest(&r)) {
- .AuthFailed => {
- if (e.settings.unauthorized) |unauthorized| {
- unauthorized(authEp.ep, r);
- return;
- } else {
- r.setStatus(.unauthorized);
- r.sendBody("UNAUTHORIZED") catch return;
- return;
- }
- },
- .AuthOK => authEp.ep.settings.get.?(authEp.ep, r),
- .Handled => {},
- }
- }
-
-
-
- pub fn post(e: *Endpoint, r: zap.Request) void {
- const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
- switch (authEp.authenticator.authenticateRequest(&r)) {
- .AuthFailed => {
- if (e.settings.unauthorized) |unauthorized| {
- unauthorized(authEp.ep, r);
- return;
- } else {
- r.setStatus(.unauthorized);
- r.sendBody("UNAUTHORIZED") catch return;
- return;
- }
- },
- .AuthOK => authEp.ep.settings.post.?(authEp.ep, r),
- .Handled => {},
- }
- }
-
-
-
- pub fn put(e: *Endpoint, r: zap.Request) void {
- const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
- switch (authEp.authenticator.authenticateRequest(&r)) {
- .AuthFailed => {
- if (e.settings.unauthorized) |unauthorized| {
- unauthorized(authEp.ep, r);
- return;
- } else {
- r.setStatus(.unauthorized);
- r.sendBody("UNAUTHORIZED") catch return;
- return;
- }
- },
- .AuthOK => authEp.ep.settings.put.?(authEp.ep, r),
- .Handled => {},
- }
- }
-
-
-
- pub fn delete(e: *Endpoint, r: zap.Request) void {
- const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
- switch (authEp.authenticator.authenticateRequest(&r)) {
- .AuthFailed => {
- if (e.settings.unauthorized) |unauthorized| {
- unauthorized(authEp.ep, r);
- return;
- } else {
- r.setStatus(.unauthorized);
- r.sendBody("UNAUTHORIZED") catch return;
- return;
- }
- },
- .AuthOK => authEp.ep.settings.delete.?(authEp.ep, r),
- .Handled => {},
- }
- }
-
-
-
- pub fn patch(e: *Endpoint, r: zap.Request) void {
- const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
- switch (authEp.authenticator.authenticateRequest(&r)) {
- .AuthFailed => {
- if (e.settings.unauthorized) |unauthorized| {
- unauthorized(authEp.ep, r);
- return;
- } else {
- r.setStatus(.unauthorized);
- r.sendBody("UNAUTHORIZED") catch return;
- return;
- }
- },
- .AuthOK => authEp.ep.settings.patch.?(authEp.ep, r),
- .Handled => {},
- }
- }
-
-
-
- pub fn options(e: *Endpoint, r: zap.Request) void {
- const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
- switch (authEp.authenticator.authenticateRequest(&r)) {
- .AuthFailed => {
- if (e.settings.unauthorized) |unauthorized| {
- unauthorized(authEp.ep, r);
- return;
- } else {
- r.setStatus(.unauthorized);
- r.sendBody("UNAUTHORIZED") catch return;
- return;
- }
- },
- .AuthOK => authEp.ep.settings.put.?(authEp.ep, r),
- .Handled => {},
- }
- }
- };
-}
-
-pub const EndpointListenerError = error{
-
-
-
-
- EndpointPathShadowError,
-};
-
-
-
-
-pub const Listener = struct {
- listener: HttpListener,
- allocator: std.mem.Allocator,
-
- const Self = @This();
-
-
- var endpoints: std.ArrayList(*Endpoint) = undefined;
-
-
-
-
- var on_request: ?zap.HttpRequestFn = null;
-
-
-
-
- pub fn init(a: std.mem.Allocator, l: ListenerSettings) Self {
- endpoints = std.ArrayList(*Endpoint).init(a);
-
-
-
- var ls = l;
-
-
-
-
-
- ls.on_request = Listener.onRequest;
-
-
-
- on_request = l.on_request;
- return .{
- .listener = HttpListener.init(ls),
- .allocator = a,
- };
- }
-
-
-
-
- pub fn deinit(self: *Self) void {
- _ = self;
- endpoints.deinit();
- }
-
-
-
- pub fn listen(self: *Self) !void {
- try self.listener.listen();
- }
-
-
-
-
-
- pub fn register(self: *Self, e: *Endpoint) !void {
- _ = self;
- for (endpoints.items) |other| {
- if (std.mem.startsWith(
- u8,
- other.settings.path,
- e.settings.path,
- ) or std.mem.startsWith(
- u8,
- e.settings.path,
- other.settings.path,
- )) {
- return EndpointListenerError.EndpointPathShadowError;
- }
- }
- try endpoints.append(e);
- }
-
- fn onRequest(r: Request) void {
- if (r.path) |p| {
- for (endpoints.items) |e| {
- if (std.mem.startsWith(u8, p, e.settings.path)) {
- e.onRequest(r);
- return;
- }
- }
- }
-
-
- if (on_request) |foo| {
- foo(r);
- }
- }
-};
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/fio.zig.html b/docs/src/zap/fio.zig.html
deleted file mode 100644
index e4e55e4..0000000
--- a/docs/src/zap/fio.zig.html
+++ /dev/null
@@ -1,740 +0,0 @@
-
-
-
-
-
fio.zig - source view
-
-
-
-
-
-
pub const FIOBJ = usize;
-pub extern fn is_invalid(o: FIOBJ) c_int;
-pub const fio_url_s = extern struct {
- scheme: fio_str_info_s,
- user: fio_str_info_s,
- password: fio_str_info_s,
- host: fio_str_info_s,
- port: fio_str_info_s,
- path: fio_str_info_s,
- query: fio_str_info_s,
- target: fio_str_info_s,
-};
-pub extern fn fio_url_parse(url: [*c]const u8, length: usize) fio_url_s;
-pub const struct_fio_start_args = extern struct {
- threads: i16,
- workers: i16,
-};
-pub const fio_start_args = struct_fio_start_args;
-pub extern fn fio_start(args: struct_fio_start_args) void;
-pub extern fn fio_stop() void;
-const struct_unnamed_37 = extern struct {
- vtbl: ?*anyopaque,
- flag: usize,
- out_headers: FIOBJ,
-};
-pub const __time_t = c_long;
-pub const time_t = __time_t;
-pub const __syscall_slong_t = c_long;
-pub const struct_timespec = extern struct {
- tv_sec: __time_t,
- tv_nsec: __syscall_slong_t,
-};
-pub const struct_http_settings_s = extern struct {
- on_request: ?*const fn ([*c]http_s) callconv(.C) void,
- on_upgrade: ?*const fn ([*c]http_s, [*c]u8, usize) callconv(.C) void,
- on_response: ?*const fn ([*c]http_s) callconv(.C) void,
- on_finish: ?*const fn ([*c]struct_http_settings_s) callconv(.C) void,
- udata: ?*anyopaque,
- public_folder: [*c]const u8,
- public_folder_length: usize,
- max_header_size: usize,
- max_body_size: usize,
- max_clients: isize,
- tls: ?*anyopaque,
- reserved1: isize,
- reserved2: isize,
- reserved3: isize,
- ws_max_msg_size: usize,
- timeout: u8,
- ws_timeout: u8,
- log: u8,
- is_client: u8,
-};
-pub const http_settings_s = struct_http_settings_s;
-pub const http_s = extern struct {
- private_data: struct_unnamed_37,
- received_at: struct_timespec,
- method: FIOBJ,
- status_str: FIOBJ,
- version: FIOBJ,
- status: usize,
- path: FIOBJ,
- query: FIOBJ,
- headers: FIOBJ,
- cookies: FIOBJ,
- params: FIOBJ,
- body: FIOBJ,
- udata: ?*anyopaque,
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub const http_cookie_args_s = extern struct {
- name: [*c]u8,
- value: [*c]u8,
- domain: [*c]u8,
- path: [*c]u8,
- name_len: isize,
- value_len: isize,
- domain_len: isize,
- path_len: isize,
-
- max_age: c_int,
- secure: c_uint,
- http_only: c_uint,
-};
-
-pub const struct_fio_str_info_s = extern struct {
- capa: usize,
- len: usize,
- data: [*c]u8,
-};
-pub const fio_str_info_s = struct_fio_str_info_s;
-pub extern fn http_send_body(h: [*c]http_s, data: ?*anyopaque, length: usize) c_int;
-pub fn fiobj_each1(arg_o: FIOBJ, arg_start_at: usize, arg_task: ?*const fn (FIOBJ, ?*anyopaque) callconv(.C) c_int, arg_arg: ?*anyopaque) callconv(.C) usize {
- const o = arg_o;
- const start_at = arg_start_at;
- const task = arg_task;
- const arg = arg_arg;
- if ((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (fiobj_type_vtable(o).*.each != null)) return fiobj_type_vtable(o).*.each.?(o, start_at, task, arg);
- return 0;
-}
-
-pub extern fn fiobj_hash_new() FIOBJ;
-pub extern fn fiobj_hash_set(hash: FIOBJ, key: FIOBJ, obj: FIOBJ) c_int;
-pub extern fn fiobj_hash_get(hash: FIOBJ, key: FIOBJ) FIOBJ;
-pub extern fn fiobj_hash_pop(hash: FIOBJ, key: [*c]FIOBJ) FIOBJ;
-pub extern fn fiobj_hash_count(hash: FIOBJ) usize;
-pub extern fn fiobj_hash_key_in_loop() FIOBJ;
-pub extern fn fiobj_hash_haskey(hash: FIOBJ, key: FIOBJ) c_int;
-pub extern fn fiobj_ary_new() FIOBJ;
-pub extern fn fiobj_ary_new2(capa: usize) FIOBJ;
-pub extern fn fiobj_ary_count(ary: FIOBJ) usize;
-pub extern fn fiobj_ary_capa(ary: FIOBJ) usize;
-pub extern fn fiobj_ary2ptr(ary: FIOBJ) [*c]FIOBJ;
-pub extern fn fiobj_ary_index(ary: FIOBJ, pos: i64) FIOBJ;
-pub extern fn fiobj_ary_set(ary: FIOBJ, obj: FIOBJ, pos: i64) void;
-pub extern fn fiobj_ary_push(ary: FIOBJ, obj: FIOBJ) void;
-pub extern fn fiobj_ary_pop(ary: FIOBJ) FIOBJ;
-pub extern fn fiobj_ary_unshift(ary: FIOBJ, obj: FIOBJ) void;
-pub extern fn fiobj_ary_shift(ary: FIOBJ) FIOBJ;
-pub extern fn fiobj_ary_replace(ary: FIOBJ, obj: FIOBJ, pos: i64) FIOBJ;
-pub extern fn fiobj_ary_find(ary: FIOBJ, data: FIOBJ) i64;
-pub extern fn fiobj_ary_remove(ary: FIOBJ, pos: i64) c_int;
-pub extern fn fiobj_ary_remove2(ary: FIOBJ, data: FIOBJ) c_int;
-pub extern fn fiobj_ary_compact(ary: FIOBJ) void;
-pub extern fn fiobj_float_new(num: f64) FIOBJ;
-pub extern fn fiobj_num_new_bignum(num: isize) FIOBJ;
-
-pub extern fn fiobj_data_newstr() FIOBJ;
-pub extern fn fiobj_data_newstr2(buffer: ?*anyopaque, length: usize, dealloc: ?*const fn (?*anyopaque) callconv(.C) void) FIOBJ;
-pub extern fn fiobj_data_newtmpfile() FIOBJ;
-pub extern fn fiobj_data_newfd(fd: c_int) FIOBJ;
-pub extern fn fiobj_data_slice(parent: FIOBJ, offset: isize, length: usize) FIOBJ;
-pub extern fn fiobj_data_save(io: FIOBJ, filename: [*c]const u8) c_int;
-pub extern fn fiobj_data_read(io: FIOBJ, length: isize) fio_str_info_s;
-pub extern fn fiobj_data_read2ch(io: FIOBJ, token: u8) fio_str_info_s;
-pub extern fn fiobj_data_pos(io: FIOBJ) isize;
-pub extern fn fiobj_data_len(io: FIOBJ) isize;
-pub extern fn fiobj_data_seek(io: FIOBJ, position: isize) void;
-pub extern fn fiobj_data_pread(io: FIOBJ, start_at: isize, length: usize) fio_str_info_s;
-pub extern fn fiobj_data_write(io: FIOBJ, buffer: ?*anyopaque, length: usize) isize;
-pub extern fn fiobj_data_puts(io: FIOBJ, buffer: ?*anyopaque, length: usize) isize;
-pub extern fn fiobj_data_assert_dynamic(io: FIOBJ) void;
-
-
-
-
-
-
-pub extern fn fio_tls_new(
- server_name: ?[*:0]const u8,
- public_certificate_file: ?[*:0]const u8,
- private_key_file: ?[*:0]const u8,
- private_key_password: ?[*:0]const u8,
-) ?*anyopaque;
-
-
-
-pub extern fn fio_tls_dup(tls: ?*anyopaque) void;
-
-
-pub extern fn fio_tls_destroy(tls: ?*anyopaque) void;
-
-
-
-pub extern fn fio_tls_cert_add(
- tls: ?*anyopaque,
- server_name: ?[*:0]const u8,
- public_certificate_file: ?[*:0]const u8,
- private_key_file: ?[*:0]const u8,
- private_key_password: ?[*:0]const u8,
-) c_int;
-
-
-
-
-pub extern fn fio_tls_trust(tls: ?*anyopaque, public_cert_file: ?[*:0]const u8) c_int;
-
-
-
-
-
-pub extern fn fio_tls_accept(uuid: *u32, tls: ?*anyopaque, udata: ?*anyopaque) void;
-
-
-
-
-
-
-pub extern fn fio_tls_connect(uuid: *u32, tls: ?*anyopaque, udata: ?*anyopaque) void;
-
-pub extern fn fiobj_free_wrapped(o: FIOBJ) callconv(.C) void;
-pub fn fiobj_null() callconv(.C) FIOBJ {
- return @as(FIOBJ, @bitCast(@as(c_long, FIOBJ_T_NULL)));
-}
-pub fn fiobj_true() callconv(.C) FIOBJ {
- return @as(FIOBJ, @bitCast(@as(c_long, FIOBJ_T_TRUE)));
-}
-pub fn fiobj_false() callconv(.C) FIOBJ {
- return @as(FIOBJ, @bitCast(@as(c_long, FIOBJ_T_FALSE)));
-}
-pub extern fn fiobj_str_new(str: [*c]const u8, len: usize) FIOBJ;
-pub extern fn fiobj_str_buf(capa: usize) FIOBJ;
-
-pub inline fn FIOBJ_TYPE(obj: anytype) @TypeOf(fiobj_type(obj)) {
- return fiobj_type(obj);
-}
-pub inline fn FIOBJ_TYPE_IS(obj: anytype, @"type": anytype) @TypeOf(fiobj_type_is(obj, @"type")) {
- return fiobj_type_is(obj, @"type");
-}
-pub inline fn FIOBJ_IS_NULL(obj: anytype) @TypeOf(!(obj != 0) or (obj == @import("std").zig.c_translation.cast(FIOBJ, FIOBJ_T_NULL))) {
- return !(obj != 0) or (obj == @import("std").zig.c_translation.cast(FIOBJ, FIOBJ_T_NULL));
-}
-pub const FIOBJ_INVALID = @as(c_int, 0);
-pub const FIOBJECT_NUMBER_FLAG = @as(c_int, 1);
-pub const FIOBJECT_PRIMITIVE_FLAG = @as(c_int, 6);
-pub const FIOBJECT_STRING_FLAG = @as(c_int, 2);
-pub const FIOBJECT_HASH_FLAG = @as(c_int, 4);
-pub const FIOBJECT_TYPE_MASK = ~@import("std").zig.c_translation.cast(usize, @as(c_int, 7));
-pub const FIOBJ_NUMBER_SIGN_MASK = ~@import("std").zig.c_translation.cast(usize, @as(c_int, 0)) >> @as(c_int, 1);
-pub const FIOBJ_NUMBER_SIGN_BIT = ~FIOBJ_NUMBER_SIGN_MASK;
-pub const FIOBJ_NUMBER_SIGN_EXCLUDE_BIT = FIOBJ_NUMBER_SIGN_BIT >> @as(c_int, 1);
-pub inline fn FIOBJ_IS_ALLOCATED(o: anytype) @TypeOf(((o != 0) and ((o & FIOBJECT_NUMBER_FLAG) == @as(c_int, 0))) and ((o & FIOBJECT_PRIMITIVE_FLAG) != FIOBJECT_PRIMITIVE_FLAG)) {
- return ((o != 0) and ((o & FIOBJECT_NUMBER_FLAG) == @as(c_int, 0))) and ((o & FIOBJECT_PRIMITIVE_FLAG) != FIOBJECT_PRIMITIVE_FLAG);
-}
-pub inline fn FIOBJ2PTR(o: anytype) ?*anyopaque {
- return @import("std").zig.c_translation.cast(?*anyopaque, o & FIOBJECT_TYPE_MASK);
-}
-pub inline fn FIOBJECT2VTBL(o: anytype) @TypeOf(fiobj_type_vtable(o)) {
- return fiobj_type_vtable(o);
-}
-pub inline fn FIOBJECT2HEAD(o: anytype) [*c]fiobj_object_header_s {
- return @import("std").zig.c_translation.cast([*c]fiobj_object_header_s, FIOBJ2PTR(o));
-}
-pub inline fn fiobj_ary_entry(a: anytype, p: anytype) @TypeOf(fiobj_ary_index(a, p)) {
- return fiobj_ary_index(a, p);
-}
-pub const FIOBJ_T_NUMBER: c_int = 1;
-pub const FIOBJ_T_NULL: c_int = 6;
-pub const FIOBJ_T_TRUE: c_int = 22;
-pub const FIOBJ_T_FALSE: c_int = 38;
-pub const FIOBJ_T_FLOAT: c_int = 39;
-pub const FIOBJ_T_STRING: c_int = 40;
-pub const FIOBJ_T_ARRAY: c_int = 41;
-pub const FIOBJ_T_HASH: c_int = 42;
-pub const FIOBJ_T_DATA: c_int = 43;
-pub const FIOBJ_T_UNKNOWN: c_int = 44;
-pub const fiobj_type_enum = u8;
-pub const fiobj_object_vtable_s = extern struct {
- class_name: [*c]const u8,
- dealloc: ?*const fn (FIOBJ, ?*const fn (FIOBJ, ?*anyopaque) callconv(.C) void, ?*anyopaque) callconv(.C) void,
- count: ?*const fn (FIOBJ) callconv(.C) usize,
- is_true: ?*const fn (FIOBJ) callconv(.C) usize,
- is_eq: ?*const fn (FIOBJ, FIOBJ) callconv(.C) usize,
- each: ?*const fn (FIOBJ, usize, ?*const fn (FIOBJ, ?*anyopaque) callconv(.C) c_int, ?*anyopaque) callconv(.C) usize,
- to_str: ?*const fn (FIOBJ) callconv(.C) fio_str_info_s,
- to_i: ?*const fn (FIOBJ) callconv(.C) isize,
- to_f: ?*const fn (FIOBJ) callconv(.C) f64,
-};
-pub const fiobj_object_header_s = extern struct {
- type: fiobj_type_enum,
- ref: u32,
-};
-pub fn fiobj_type_is(arg_o: FIOBJ, arg_type: fiobj_type_enum) callconv(.C) usize {
- const o = arg_o;
- const @"type" = arg_type;
- while (true) {
- switch (@as(c_int, @bitCast(@as(c_uint, @"type")))) {
- @as(c_int, 1) => return @as(usize, @bitCast(@as(c_long, @intFromBool(((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) or (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrFromInt(o))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == FIOBJ_T_NUMBER))))),
- @as(c_int, 6) => return @as(usize, @bitCast(@as(c_long, @intFromBool(!(o != 0) or (o == fiobj_null()))))),
- @as(c_int, 22) => return @as(usize, @bitCast(@as(c_long, @intFromBool(o == fiobj_true())))),
- @as(c_int, 38) => return @as(usize, @bitCast(@as(c_long, @intFromBool(o == fiobj_false())))),
- @as(c_int, 40) => return @as(usize, @bitCast(@as(c_long, @intFromBool(((true and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 2)))))) or (((@as(c_int, 2) == @as(c_int, 0)) and (((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))))) and (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrCast(@alignCast(@as(?*anyopaque, @ptrFromInt(o & ~@as(usize, @bitCast(@as(c_long, @as(c_int, 7)))))))))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == FIOBJ_T_STRING)))))),
- @as(c_int, 42) => {
- if (true) {
- return @as(usize, @bitCast(@as(c_long, @intFromBool(((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 4)))))))));
- }
- return @as(usize, @bitCast(@as(c_long, @intFromBool((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrCast(@alignCast(@as(?*anyopaque, @ptrFromInt(o & ~@as(usize, @bitCast(@as(c_long, @as(c_int, 7)))))))))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == @as(c_int, @bitCast(@as(c_uint, @"type"))))))));
- },
- @as(c_int, 39), @as(c_int, 41), @as(c_int, 43), @as(c_int, 44) => return @as(usize, @bitCast(@as(c_long, @intFromBool((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrCast(@alignCast(@as(?*anyopaque, @ptrFromInt(o & ~@as(usize, @bitCast(@as(c_long, @as(c_int, 7)))))))))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == @as(c_int, @bitCast(@as(c_uint, @"type")))))))),
- else => {},
- }
- break;
- }
- return @as(usize, @bitCast(@as(c_long, @intFromBool((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrCast(@alignCast(@as(?*anyopaque, @ptrFromInt(o & ~@as(usize, @bitCast(@as(c_long, @as(c_int, 7)))))))))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == @as(c_int, @bitCast(@as(c_uint, @"type"))))))));
-}
-pub fn fiobj_type(arg_o: FIOBJ) callconv(.C) fiobj_type_enum {
- const o = arg_o;
- if (!(o != 0)) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_NULL))));
- if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_NUMBER))));
- if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) return @as(u8, @bitCast(@as(u8, @truncate(o))));
- if (true and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 2)))))) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_STRING))));
- if (true and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 4)))))) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_HASH))));
- return @as([*c]fiobj_type_enum, @ptrCast(@alignCast(@as(?*anyopaque, @ptrFromInt(o & ~@as(usize, @bitCast(@as(c_long, @as(c_int, 7)))))))))[@as(c_uint, @intCast(@as(c_int, 0)))];
-}
-pub extern const FIOBJECT_VTABLE_NUMBER: fiobj_object_vtable_s;
-pub extern const FIOBJECT_VTABLE_FLOAT: fiobj_object_vtable_s;
-pub extern const FIOBJECT_VTABLE_STRING: fiobj_object_vtable_s;
-pub extern const FIOBJECT_VTABLE_ARRAY: fiobj_object_vtable_s;
-pub extern const FIOBJECT_VTABLE_HASH: fiobj_object_vtable_s;
-pub extern const FIOBJECT_VTABLE_DATA: fiobj_object_vtable_s;
-pub fn fiobj_type_vtable(arg_o: FIOBJ) callconv(.C) [*c]const fiobj_object_vtable_s {
- const o = arg_o;
- while (true) {
- switch (@as(c_int, @bitCast(@as(c_uint, fiobj_type(o))))) {
- @as(c_int, 1) => return &FIOBJECT_VTABLE_NUMBER,
- @as(c_int, 39) => return &FIOBJECT_VTABLE_FLOAT,
- @as(c_int, 40) => return &FIOBJECT_VTABLE_STRING,
- @as(c_int, 41) => return &FIOBJECT_VTABLE_ARRAY,
- @as(c_int, 42) => return &FIOBJECT_VTABLE_HASH,
- @as(c_int, 43) => return &FIOBJECT_VTABLE_DATA,
- @as(c_int, 6), @as(c_int, 22), @as(c_int, 38), @as(c_int, 44) => return null,
- else => {},
- }
- break;
- }
- return null;
-}
-
-pub fn fiobj_obj2num(o: FIOBJ) callconv(.C) isize {
- if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) {
- const sign: usize = if ((o & ~(~@as(usize, @bitCast(@as(c_long, @as(c_int, 0)))) >> @as(@import("std").math.Log2Int(usize), @intCast(1)))) != 0) ~(~@as(usize, @bitCast(@as(c_long, @as(c_int, 0)))) >> @as(@import("std").math.Log2Int(usize), @intCast(1))) | (~(~@as(usize, @bitCast(@as(c_long, @as(c_int, 0)))) >> @as(@import("std").math.Log2Int(usize), @intCast(1))) >> @as(@import("std").math.Log2Int(usize), @intCast(1))) else @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0))));
- return @as(isize, @bitCast(((o & (~@as(usize, @bitCast(@as(c_long, @as(c_int, 0)))) >> @as(@import("std").math.Log2Int(usize), @intCast(1)))) >> @as(@import("std").math.Log2Int(c_ulong), @intCast(1))) | sign));
- }
- if (!(o != 0) or !(((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))))) return @as(isize, @bitCast(@as(c_long, @intFromBool(o == @as(c_ulong, @bitCast(@as(c_long, FIOBJ_T_TRUE)))))));
- return fiobj_type_vtable(o).*.to_i.?(o);
-}
-pub fn fiobj_obj2float(o: FIOBJ) callconv(.C) f64 {
- if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) return @as(f64, @floatFromInt(fiobj_obj2num(o)));
-
-
-
-
- return fiobj_type_vtable(o).*.to_f.?(o);
-}
-
-pub extern fn fio_ltocstr(c_long) fio_str_info_s;
-pub fn fiobj_obj2cstr(o: FIOBJ) callconv(.C) fio_str_info_s {
- if (!(o != 0)) {
- const ret: fio_str_info_s = fio_str_info_s{
- .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
- .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))),
- .data = @as([*c]u8, @ptrFromInt(@intFromPtr("null"))),
- };
- return ret;
- }
- if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) return fio_ltocstr(@as(isize, @bitCast(o)) >> @as(@import("std").math.Log2Int(isize), @intCast(1)));
- if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) {
- while (true) {
- switch (@as(c_int, @bitCast(@as(c_uint, @as(u8, @bitCast(@as(u8, @truncate(o)))))))) {
- @as(c_int, 6) => {
- {
- const ret: fio_str_info_s = fio_str_info_s{
- .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
- .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))),
- .data = @as([*c]u8, @ptrFromInt(@intFromPtr("null"))),
- };
- return ret;
- }
- },
- @as(c_int, 38) => {
- {
- const ret: fio_str_info_s = fio_str_info_s{
- .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
- .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 5)))),
- .data = @as([*c]u8, @ptrFromInt(@intFromPtr("false"))),
- };
- return ret;
- }
- },
- @as(c_int, 22) => {
- {
- const ret: fio_str_info_s = fio_str_info_s{
- .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
- .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))),
- .data = @as([*c]u8, @ptrFromInt(@intFromPtr("true"))),
- };
- return ret;
- }
- },
- else => break,
- }
- break;
- }
- }
- return fiobj_type_vtable(o).*.to_str.?(o);
-}
-
-
-
-pub extern fn http_set_header(h: [*c]http_s, name: FIOBJ, value: FIOBJ) c_int;
-pub extern fn http_set_header2(h: [*c]http_s, name: fio_str_info_s, value: fio_str_info_s) c_int;
-pub extern fn http_set_cookie(h: [*c]http_s, http_cookie_args_s) c_int;
-pub extern fn http_sendfile(h: [*c]http_s, fd: c_int, length: usize, offset: usize) c_int;
-pub extern fn http_sendfile2(h: [*c]http_s, prefix: [*c]const u8, prefix_len: usize, encoded: [*c]const u8, encoded_len: usize) c_int;
-pub extern fn http_send_error(h: [*c]http_s, error_code: usize) c_int;
-pub extern fn http_finish(h: [*c]http_s) void;
-pub extern fn http_push_data(h: [*c]http_s, data: ?*anyopaque, length: usize, mime_type: FIOBJ) c_int;
-pub extern fn http_push_file(h: [*c]http_s, filename: FIOBJ, mime_type: FIOBJ) c_int;
-pub const struct_http_pause_handle_s = opaque {};
-pub const http_pause_handle_s = struct_http_pause_handle_s;
-pub extern fn http_pause(h: [*c]http_s, task: ?*const fn (?*http_pause_handle_s) callconv(.C) void) void;
-pub extern fn http_resume(http: ?*http_pause_handle_s, task: ?*const fn ([*c]http_s) callconv(.C) void, fallback: ?*const fn (?*anyopaque) callconv(.C) void) void;
-pub extern fn http_paused_udata_get(http: ?*http_pause_handle_s) ?*anyopaque;
-pub extern fn http_paused_udata_set(http: ?*http_pause_handle_s, udata: ?*anyopaque) ?*anyopaque;
-pub extern fn http_listen(port: [*c]const u8, binding: [*c]const u8, struct_http_settings_s) isize;
-pub extern fn http_connect(url: [*c]const u8, unix_address: [*c]const u8, struct_http_settings_s) isize;
-pub extern fn http_settings(h: [*c]http_s) [*c]struct_http_settings_s;
-pub extern fn http_peer_addr(h: [*c]http_s) fio_str_info_s;
-pub extern fn http_hijack(h: [*c]http_s, leftover: [*c]fio_str_info_s) isize;
-pub const struct_ws_s = opaque {};
-pub const ws_s = struct_ws_s;
-pub const websocket_settings_s = extern struct {
- on_message: ?*const fn (?*ws_s, fio_str_info_s, u8) callconv(.C) void,
- on_open: ?*const fn (?*ws_s) callconv(.C) void,
- on_ready: ?*const fn (?*ws_s) callconv(.C) void,
- on_shutdown: ?*const fn (?*ws_s) callconv(.C) void,
- on_close: ?*const fn (isize, ?*anyopaque) callconv(.C) void,
- udata: ?*anyopaque,
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub const websocket_subscribe_s_zigcompat = extern struct {
- ws: ?*ws_s,
- channel: fio_str_info_s,
- on_message: ?*const fn (?*ws_s, fio_str_info_s, fio_str_info_s, ?*anyopaque) callconv(.C) void,
- on_unsubscribe: ?*const fn (?*anyopaque) callconv(.C) void,
- udata: ?*anyopaque,
- match: fio_match_fn,
- force_binary: u8,
- force_text: u8,
-};
-
-
-pub extern fn websocket_subscribe_zigcompat(websocket_subscribe_s_zigcompat) callconv(.C) usize;
-
-pub extern fn http_upgrade2ws(http: [*c]http_s, websocket_settings_s) c_int;
-pub extern fn websocket_connect(url: [*c]const u8, settings: websocket_settings_s) c_int;
-pub extern fn websocket_attach(uuid: isize, http_settings: [*c]http_settings_s, args: [*c]websocket_settings_s, data: ?*anyopaque, length: usize) void;
-pub extern fn websocket_udata_get(ws: ?*ws_s) ?*anyopaque;
-pub extern fn websocket_udata_set(ws: ?*ws_s, udata: ?*anyopaque) ?*anyopaque;
-pub extern fn websocket_uuid(ws: ?*ws_s) isize;
-pub extern fn websocket_is_client(ws: ?*ws_s) u8;
-pub extern fn websocket_write(ws: ?*ws_s, msg: fio_str_info_s, is_text: u8) c_int;
-pub extern fn websocket_close(ws: ?*ws_s) void;
-
-pub const struct_websocket_subscribe_s = opaque {};
-pub extern fn websocket_subscribe(args: struct_websocket_subscribe_s) usize;
-pub extern fn websocket_unsubscribe(ws: ?*ws_s, subscription_id: usize) void;
-pub extern fn websocket_optimize4broadcasts(@"type": isize, enable: c_int) void;
-
-pub extern fn fio_publish(args: fio_publish_args_s) void;
-pub const fio_publish_args_s = struct_fio_publish_args_s;
-pub const struct_fio_publish_args_s = extern struct {
- engine: ?*anyopaque = null,
-
-
-
-
- filter: i32 = 0,
- channel: fio_str_info_s,
- message: fio_str_info_s,
- is_json: u8,
-};
-
-pub const http_sse_s = struct_http_sse_s;
-pub const struct_http_sse_s = extern struct {
- on_open: ?*const fn ([*c]http_sse_s) callconv(.C) void,
- on_ready: ?*const fn ([*c]http_sse_s) callconv(.C) void,
- on_shutdown: ?*const fn ([*c]http_sse_s) callconv(.C) void,
- on_close: ?*const fn ([*c]http_sse_s) callconv(.C) void,
- udata: ?*anyopaque,
-};
-pub extern fn http_upgrade2sse(h: [*c]http_s, http_sse_s) c_int;
-pub extern fn http_sse_set_timout(sse: [*c]http_sse_s, timeout: u8) void;
-pub const fio_match_fn = ?*const fn (fio_str_info_s, fio_str_info_s) callconv(.C) c_int;
-pub const struct_http_sse_subscribe_args = extern struct {
- channel: fio_str_info_s,
- on_message: ?*const fn ([*c]http_sse_s, fio_str_info_s, fio_str_info_s, ?*anyopaque) callconv(.C) void,
- on_unsubscribe: ?*const fn (?*anyopaque) callconv(.C) void,
- udata: ?*anyopaque,
- match: fio_match_fn,
-};
-pub extern fn http_sse_subscribe(sse: [*c]http_sse_s, args: struct_http_sse_subscribe_args) usize;
-pub extern fn http_sse_unsubscribe(sse: [*c]http_sse_s, subscription: usize) void;
-pub const struct_http_sse_write_args = extern struct {
- id: fio_str_info_s,
- event: fio_str_info_s,
- data: fio_str_info_s,
- retry: isize,
-};
-pub extern fn http_sse_write(sse: [*c]http_sse_s, struct_http_sse_write_args) c_int;
-pub extern fn http_sse2uuid(sse: [*c]http_sse_s) isize;
-pub extern fn http_sse_close(sse: [*c]http_sse_s) c_int;
-pub extern fn http_sse_dup(sse: [*c]http_sse_s) [*c]http_sse_s;
-pub extern fn http_sse_free(sse: [*c]http_sse_s) void;
-pub extern fn http_parse_body(h: [*c]http_s) c_int;
-pub extern fn http_parse_query(h: [*c]http_s) void;
-pub extern fn http_parse_cookies(h: [*c]http_s, is_url_encoded: u8) void;
-pub extern fn http_add2hash(dest: FIOBJ, name: [*c]u8, name_len: usize, value: [*c]u8, value_len: usize, encoded: u8) c_int;
-pub extern fn http_add2hash2(dest: FIOBJ, name: [*c]u8, name_len: usize, value: FIOBJ, encoded: u8) c_int;
-pub extern fn http_status2str(status: usize) fio_str_info_s;
-pub extern fn http_mimetype_register(file_ext: [*c]u8, file_ext_len: usize, mime_type_str: FIOBJ) void;
-pub extern fn http_mimetype_find(file_ext: [*c]u8, file_ext_len: usize) FIOBJ;
-pub extern fn http_mimetype_find2(url: FIOBJ) FIOBJ;
-pub extern fn http_mimetype_clear() void;
-pub extern var HTTP_HEADER_ACCEPT: FIOBJ;
-pub extern var HTTP_HEADER_CACHE_CONTROL: FIOBJ;
-pub extern var HTTP_HEADER_CONNECTION: FIOBJ;
-pub extern var HTTP_HEADER_CONTENT_ENCODING: FIOBJ;
-pub extern var HTTP_HEADER_CONTENT_LENGTH: FIOBJ;
-pub extern var HTTP_HEADER_CONTENT_RANGE: FIOBJ;
-pub extern var HTTP_HEADER_CONTENT_TYPE: FIOBJ;
-pub extern var HTTP_HEADER_COOKIE: FIOBJ;
-pub extern var HTTP_HEADER_DATE: FIOBJ;
-pub extern var HTTP_HEADER_ETAG: FIOBJ;
-pub extern var HTTP_HEADER_HOST: FIOBJ;
-pub extern var HTTP_HEADER_LAST_MODIFIED: FIOBJ;
-pub extern var HTTP_HEADER_ORIGIN: FIOBJ;
-pub extern var HTTP_HEADER_SET_COOKIE: FIOBJ;
-pub extern var HTTP_HEADER_UPGRADE: FIOBJ;
-pub extern fn http_req2str(h: [*c]http_s) FIOBJ;
-pub extern fn http_write_log(h: [*c]http_s) void;
-pub extern fn http_gmtime(timer: time_t, tmbuf: [*c]struct_tm) [*c]struct_tm;
-pub extern fn http_date2rfc7231(target: [*c]u8, tmbuf: [*c]struct_tm) usize;
-pub extern fn http_date2rfc2109(target: [*c]u8, tmbuf: [*c]struct_tm) usize;
-pub extern fn http_date2rfc2822(target: [*c]u8, tmbuf: [*c]struct_tm) usize;
-pub fn http_date2str(arg_target: [*c]u8, arg_tmbuf: [*c]struct_tm) callconv(.C) usize {
- const target = arg_target;
- const tmbuf = arg_tmbuf;
- return http_date2rfc7231(target, tmbuf);
-}
-pub extern fn http_time2str(target: [*c]u8, t: time_t) usize;
-pub extern fn http_decode_url_unsafe(dest: [*c]u8, url_data: [*c]const u8) isize;
-pub extern fn http_decode_url(dest: [*c]u8, url_data: [*c]const u8, length: usize) isize;
-pub extern fn http_decode_path_unsafe(dest: [*c]u8, url_data: [*c]const u8) isize;
-pub extern fn http_decode_path(dest: [*c]u8, url_data: [*c]const u8, length: usize) isize;
-pub const http_url_s = fio_url_s;
-
-pub const struct_tm = extern struct {
- tm_sec: c_int,
- tm_min: c_int,
- tm_hour: c_int,
- tm_mday: c_int,
- tm_mon: c_int,
- tm_year: c_int,
- tm_wday: c_int,
- tm_yday: c_int,
- tm_isdst: c_int,
- tm_gmtoff: c_long,
- tm_zone: [*c]const u8,
-};
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/http.zig.html b/docs/src/zap/http.zig.html
deleted file mode 100644
index 9fbfa1a..0000000
--- a/docs/src/zap/http.zig.html
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
http.zig - source view
-
-
-
-
-
-
const std = @import("std");
-
-
-
-
-pub const StatusCode = enum(u16) {
-
-
- @"continue" = 100,
-
-
- switching_protocols = 101,
- ok = 200,
- created = 201,
- accepted = 202,
- non_authoritative_information = 203,
- no_content = 204,
- reset_content = 205,
-
-
- partial_content = 206,
- multiple_choices = 300,
- moved_permanently = 301,
- found = 302,
- see_other = 303,
- not_modified = 304,
- use_proxy = 305,
- temporary_redirect = 307,
-
-
- bad_request = 400,
- unauthorized = 401,
- payment_required = 402,
- forbidden = 403,
- not_found = 404,
- method_not_allowed = 405,
- not_acceptable = 406,
- proxy_authentication_required = 407,
- request_timeout = 408,
- conflict = 409,
- gone = 410,
- length_required = 411,
- precondition_failed = 412,
- request_entity_too_large = 413,
- request_uri_too_long = 414,
- unsupported_mediatype = 415,
- requested_range_not_satisfiable = 416,
- expectation_failed = 417,
-
- teapot = 418,
- upgrade_required = 426,
-
- request_header_fields_too_large = 431,
-
-
- internal_server_error = 500,
- not_implemented = 501,
- bad_gateway = 502,
- service_unavailable = 503,
- gateway_timeout = 504,
- http_version_not_supported = 505,
- _,
-
-
-
- pub fn toString(self: StatusCode) []const u8 {
- return switch (self) {
- .@"continue" => "Continue",
- .switching_protocols => "Switching Protocols",
- .ok => "Ok",
- .created => "Created",
- .accepted => "Accepted",
- .non_authoritative_information => "Non Authoritative Information",
- .no_content => "No Content",
- .reset_content => "Reset Content",
- .partial_content => "Partial Content",
- .multiple_choices => "Multiple Choices",
- .moved_permanently => "Moved Permanently",
- .found => "Found",
- .see_other => "See Other",
- .not_modified => "Not Modified",
- .use_proxy => "Use Proxy",
- .temporary_redirect => "Temporary Redirect",
- .bad_request => "Bad Request",
- .unauthorized => "Unauthorized",
- .payment_required => "Payment Required",
- .forbidden => "Forbidden",
- .not_found => "Not Found",
- .method_not_allowed => "Method Not Allowed",
- .not_acceptable => "Not Acceptable",
- .proxy_authentication_required => "Proxy Authentication Required",
- .request_timeout => "Request Timeout",
- .conflict => "Conflict",
- .gone => "Gone",
- .length_required => "Length Required",
- .precondition_failed => "Precondition Failed",
- .request_entity_too_large => "Request Entity Too Large",
- .request_uri_too_long => "Request-URI Too Long",
- .unsupported_mediatype => "Unsupported Media Type",
- .requested_range_not_satisfiable => "Requested Range Not Satisfiable",
- .teapot => "I'm a Teapot",
- .upgrade_required => "Upgrade Required",
- .request_header_fields_too_large => "Request Header Fields Too Large",
- .expectation_failed => "Expectation Failed",
- .internal_server_error => "Internal Server Error",
- .not_implemented => "Not Implemented",
- .bad_gateway => "Bad Gateway",
- .service_unavailable => "Service Unavailable",
- .gateway_timeout => "Gateway Timeout",
- .http_version_not_supported => "HTTP Version Not Supported",
- _ => "",
- };
- }
-};
-
-pub const Method = enum {
- GET,
- POST,
- PUT,
- DELETE,
- PATCH,
- OPTIONS,
- UNKNOWN,
-};
-
-pub fn methodToEnum(method: ?[]const u8) Method {
- {
- if (method) |m| {
- return std.meta.stringToEnum(Method, m) orelse .UNKNOWN;
- }
- return Method.UNKNOWN;
- }
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/http_auth.zig.html b/docs/src/zap/http_auth.zig.html
deleted file mode 100644
index 1b6a185..0000000
--- a/docs/src/zap/http_auth.zig.html
+++ /dev/null
@@ -1,766 +0,0 @@
-
-
-
-
-
http_auth.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const zap = @import("zap.zig");
-
-
-pub const AuthScheme = enum {
- Basic,
- Bearer,
-
- pub fn str(self: AuthScheme) []const u8 {
- return switch (self) {
- .Basic => "Basic ",
- .Bearer => "Bearer ",
- };
- }
-
- pub fn headerFieldStrFio(self: AuthScheme) []const u8 {
- return switch (self) {
- .Basic => "authentication",
- .Bearer => "authorization",
- };
- }
-
- pub fn headerFieldStrHeader(self: AuthScheme) [:0]const u8 {
- return switch (self) {
- .Basic => "Authentication",
- .Bearer => "Authorization",
- };
- }
-};
-
-
-pub fn checkAuthHeader(scheme: AuthScheme, auth_header: []const u8) bool {
- return switch (scheme) {
- .Basic => |b| std.mem.startsWith(u8, auth_header, b.str()) and auth_header.len > b.str().len,
- .Bearer => |b| std.mem.startsWith(u8, auth_header, b.str()) and auth_header.len > b.str().len,
- };
-}
-
-
-pub fn extractAuthHeader(scheme: AuthScheme, r: *const zap.Request) ?[]const u8 {
- return switch (scheme) {
- .Basic => |b| r.getHeader(b.headerFieldStrFio()),
- .Bearer => |b| r.getHeader(b.headerFieldStrFio()),
- };
-}
-
-
-const BasicAuthStrategy = enum {
-
- UserPass,
-
- Token68,
-};
-
-
-pub const AuthResult = enum {
-
- AuthOK,
-
- AuthFailed,
-
-
-
-
-
- Handled,
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub fn Basic(comptime Lookup: type, comptime kind: BasicAuthStrategy) type {
- return struct {
- allocator: std.mem.Allocator,
- realm: ?[]const u8,
- lookup: *Lookup,
-
- const Self = @This();
-
-
-
-
-
-
- pub fn init(allocator: std.mem.Allocator, lookup: *Lookup, realm: ?[]const u8) !Self {
- return .{
- .allocator = allocator,
- .lookup = lookup,
- .realm = if (realm) |the_realm| try allocator.dupe(u8, the_realm) else null,
- };
- }
-
-
- pub fn deinit(self: *Self) void {
- if (self.realm) |the_realm| {
- self.allocator.free(the_realm);
- }
- }
-
-
-
- pub fn authenticateUserPass(self: *Self, auth_header: []const u8) AuthResult {
- zap.debug("AuthenticateUserPass\n", .{});
- const encoded = auth_header[AuthScheme.Basic.str().len..];
- const decoder = std.base64.standard.Decoder;
- var buffer: [0x100]u8 = undefined;
- if (decoder.calcSizeForSlice(encoded)) |decoded_size| {
- if (decoded_size >= buffer.len) {
- zap.debug(
- "ERROR: UserPassAuth: decoded_size {d} >= buffer.len {d}\n",
- .{ decoded_size, buffer.len },
- );
- return .AuthFailed;
- }
- const decoded = buffer[0..decoded_size];
- decoder.decode(decoded, encoded) catch |err| {
- zap.debug(
- "ERROR: UserPassAuth: unable to decode `{s}`: {any}\n",
- .{ encoded, err },
- );
- return .AuthFailed;
- };
-
-
-
-
- var it = std.mem.split(u8, decoded, ":");
- const user = it.next();
- const pass = it.next();
- if (user == null or pass == null) {
- zap.debug(
- "ERROR: UserPassAuth: user {any} or pass {any} is null\n",
- .{ user, pass },
- );
- return .AuthFailed;
- }
-
-
- const actual_pw = self.lookup.*.get(user.?);
- if (actual_pw) |pw| {
- const ret = std.mem.eql(u8, pass.?, pw);
- zap.debug(
- "INFO: UserPassAuth for user `{s}`: `{s}` == pass `{s}` = {}\n",
- .{ user.?, pw, pass.?, ret },
- );
- return if (ret) .AuthOK else .AuthFailed;
- } else {
- zap.debug(
- "ERROR: UserPassAuth: user `{s}` not found in map of size {d}!\n",
- .{ user.?, self.lookup.*.count() },
- );
- return .AuthFailed;
- }
- } else |err| {
-
-
- zap.debug(
- "ERROR: UserPassAuth: cannot calc slize size for encoded `{s}`: {any} \n",
- .{ encoded, err },
- );
- return .AuthFailed;
- }
- zap.debug("UNREACHABLE\n", .{});
- return .AuthFailed;
- }
-
-
-
- pub fn authenticateToken68(self: *Self, auth_header: []const u8) AuthResult {
- const token = auth_header[AuthScheme.Basic.str().len..];
- return if (self.lookup.*.contains(token)) .AuthOK else .AuthFailed;
- }
-
-
-
- pub fn authenticate(self: *Self, auth_header: []const u8) AuthResult {
- zap.debug("AUTHENTICATE\n", .{});
- switch (kind) {
- .UserPass => return self.authenticateUserPass(auth_header),
- .Token68 => return self.authenticateToken68(auth_header),
- }
- }
-
-
-
-
-
- pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult {
- zap.debug("AUTHENTICATE REQUEST\n", .{});
- if (extractAuthHeader(.Basic, r)) |auth_header| {
- zap.debug("Authentication Header found!\n", .{});
- return self.authenticate(auth_header);
- } else {
-
-
- if (extractAuthHeader(.Bearer, r)) |auth_header| {
- zap.debug("Authorization Header found!\n", .{});
- return self.authenticate(auth_header);
- }
- }
- zap.debug("NO fitting Auth Header found!\n", .{});
- return .AuthFailed;
- }
- };
-}
-
-
-
-
-
-
-
-
-
-
-
-pub const BearerSingle = struct {
- allocator: std.mem.Allocator,
- token: []const u8,
- realm: ?[]const u8,
-
- const Self = @This();
-
-
-
-
- pub fn init(allocator: std.mem.Allocator, token: []const u8, realm: ?[]const u8) !Self {
- return .{
- .allocator = allocator,
- .token = try allocator.dupe(u8, token),
- .realm = if (realm) |the_realm| try allocator.dupe(u8, the_realm) else null,
- };
- }
-
-
-
- pub fn authenticate(self: *Self, auth_header: []const u8) AuthResult {
- if (checkAuthHeader(.Bearer, auth_header) == false) {
- return .AuthFailed;
- }
- const token = auth_header[AuthScheme.Bearer.str().len..];
- return if (std.mem.eql(u8, token, self.token)) .AuthOK else .AuthFailed;
- }
-
-
-
-
- pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult {
- if (extractAuthHeader(.Bearer, r)) |auth_header| {
- return self.authenticate(auth_header);
- }
- return .AuthFailed;
- }
-
-
- pub fn deinit(self: *Self) void {
- if (self.realm) |the_realm| {
- self.allocator.free(the_realm);
- }
- self.allocator.free(self.token);
- }
-};
-
-
-
-
-
-
-
-
-
-
-
-pub fn BearerMulti(comptime Lookup: type) type {
- return struct {
- allocator: std.mem.Allocator,
- lookup: *Lookup,
- realm: ?[]const u8,
-
- const Self = @This();
-
-
-
-
- pub fn init(allocator: std.mem.Allocator, lookup: *Lookup, realm: ?[]const u8) !Self {
- return .{
- .allocator = allocator,
- .lookup = lookup,
- .realm = if (realm) |the_realm| try allocator.dupe(u8, the_realm) else null,
- };
- }
-
-
-
- pub fn deinit(self: *Self) void {
- if (self.realm) |the_realm| {
- self.allocator.free(the_realm);
- }
- }
-
-
-
- pub fn authenticate(self: *Self, auth_header: []const u8) AuthResult {
- if (checkAuthHeader(.Bearer, auth_header) == false) {
- return .AuthFailed;
- }
- const token = auth_header[AuthScheme.Bearer.str().len..];
- return if (self.lookup.*.contains(token)) .AuthOK else .AuthFailed;
- }
-
-
-
-
- pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult {
- if (extractAuthHeader(.Bearer, r)) |auth_header| {
- return self.authenticate(auth_header);
- }
- return .AuthFailed;
- }
- };
-}
-
-
-pub const UserPassSessionArgs = struct {
-
- usernameParam: []const u8,
-
- passwordParam: []const u8,
-
- loginPage: []const u8,
-
- cookieName: []const u8,
-
- cookieMaxAge: u8 = 0,
-
- redirectCode: zap.StatusCode = .found,
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub fn UserPassSession(comptime Lookup: type, comptime lockedPwLookups: bool) type {
- return struct {
- allocator: std.mem.Allocator,
- lookup: *Lookup,
- settings: UserPassSessionArgs,
-
-
-
- sessionTokens: SessionTokenMap,
- passwordLookupLock: std.Thread.Mutex = .{},
- tokenLookupLock: std.Thread.Mutex = .{},
-
- const Self = @This();
- const SessionTokenMap = std.StringHashMap(void);
- const Hash = std.crypto.hash.sha2.Sha256;
-
- const Token = [Hash.digest_length * 2]u8;
-
-
-
- pub fn init(
- allocator: std.mem.Allocator,
- lookup: *Lookup,
- args: UserPassSessionArgs,
- ) !Self {
- const ret: Self = .{
- .allocator = allocator,
- .settings = .{
- .usernameParam = try allocator.dupe(u8, args.usernameParam),
- .passwordParam = try allocator.dupe(u8, args.passwordParam),
- .loginPage = try allocator.dupe(u8, args.loginPage),
- .cookieName = try allocator.dupe(u8, args.cookieName),
- .cookieMaxAge = args.cookieMaxAge,
- .redirectCode = args.redirectCode,
- },
- .lookup = lookup,
- .sessionTokens = SessionTokenMap.init(allocator),
- };
-
- return ret;
- }
-
-
- pub fn deinit(self: *Self) void {
- self.allocator.free(self.settings.usernameParam);
- self.allocator.free(self.settings.passwordParam);
- self.allocator.free(self.settings.loginPage);
- self.allocator.free(self.settings.cookieName);
-
-
-
- var key_it = self.sessionTokens.keyIterator();
- while (key_it.next()) |key_ptr| {
- self.allocator.free(key_ptr.*);
- }
- self.sessionTokens.deinit();
- }
-
-
- pub fn logout(self: *Self, r: *const zap.Request) void {
-
-
-
-
- if (r.setCookie(.{
- .name = self.settings.cookieName,
- .value = "invalid",
- .max_age_s = -1,
- })) {
- zap.debug("logout ok\n", .{});
- } else |err| {
- zap.debug("logout cookie setting failed: {any}\n", .{err});
- }
-
- r.parseCookies(false);
-
-
-
- if (r.getCookieStr(self.allocator, self.settings.cookieName, false)) |maybe_cookie| {
- if (maybe_cookie) |cookie| {
- defer cookie.deinit();
- self.tokenLookupLock.lock();
- defer self.tokenLookupLock.unlock();
- if (self.sessionTokens.getKeyPtr(cookie.str)) |keyPtr| {
- const keySlice = keyPtr.*;
-
-
- _ = self.sessionTokens.remove(cookie.str);
-
-
-
-
- self.allocator.free(keySlice);
- }
- }
- } else |err| {
- zap.debug("unreachable: UserPassSession.logout: {any}", .{err});
- }
- }
-
- fn _internal_authenticateRequest(self: *Self, r: *const zap.Request) AuthResult {
-
-
- if (r.path) |p| {
- if (std.mem.startsWith(u8, p, self.settings.loginPage)) {
- return .AuthOK;
- }
- }
-
-
-
- r.parseBody() catch {
-
-
-
-
- };
-
- r.parseCookies(false);
-
-
-
- if (r.getCookieStr(self.allocator, self.settings.cookieName, false)) |maybe_cookie| {
- if (maybe_cookie) |cookie| {
- defer cookie.deinit();
-
-
- self.tokenLookupLock.lock();
- defer self.tokenLookupLock.unlock();
- if (self.sessionTokens.contains(cookie.str)) {
-
-
- zap.debug("Auth: COOKIE IS OK!!!!: {s}\n", .{cookie.str});
- return .AuthOK;
- } else {
- zap.debug("Auth: COOKIE IS BAD!!!!: {s}\n", .{cookie.str});
-
-
-
-
-
-
- }
- }
- } else |err| {
- zap.debug("unreachable: could not check for cookie in UserPassSession: {any}", .{err});
- }
-
-
-
- if (r.getParamStr(self.allocator, self.settings.usernameParam, false)) |maybe_username| {
- if (maybe_username) |*username| {
- defer username.deinit();
- if (r.getParamStr(self.allocator, self.settings.passwordParam, false)) |maybe_pw| {
- if (maybe_pw) |*pw| {
- defer pw.deinit();
-
-
-
- const correct_pw_optional = brk: {
- if (lockedPwLookups) {
- self.passwordLookupLock.lock();
- defer self.passwordLookupLock.unlock();
- break :brk self.lookup.*.get(username.str);
- } else {
- break :brk self.lookup.*.get(username.str);
- }
- };
- if (correct_pw_optional) |correct_pw| {
- if (std.mem.eql(u8, pw.str, correct_pw)) {
-
-
- if (self.createAndStoreSessionToken(username.str, pw.str)) |token| {
- defer self.allocator.free(token);
-
-
- if (r.setCookie(.{
- .name = self.settings.cookieName,
- .value = token,
- .max_age_s = self.settings.cookieMaxAge,
- })) {
- return .AuthOK;
- } else |err| {
- zap.debug("could not set session token: {any}", .{err});
- }
- } else |err| {
- zap.debug("could not create session token: {any}", .{err});
- }
-
-
- return .AuthOK;
- }
- }
- }
- } else |err| {
- zap.debug("getParamSt() for password failed in UserPassSession: {any}", .{err});
- return .AuthFailed;
- }
- }
- } else |err| {
- zap.debug("getParamSt() for user failed in UserPassSession: {any}", .{err});
- return .AuthFailed;
- }
- return .AuthFailed;
- }
-
-
-
-
- pub fn authenticateRequest(self: *Self, r: *const zap.Request) AuthResult {
- switch (self._internal_authenticateRequest(r)) {
- .AuthOK => {
-
-
- return .AuthOK;
- },
-
-
- .Handled => return .Handled,
-
-
- .AuthFailed => {
-
-
- self.redirect(r) catch |err| {
-
-
- zap.debug("redirect() failed in UserPassSession: {any}", .{err});
- };
- return .Handled;
- },
- }
- }
-
- fn redirect(self: *Self, r: *const zap.Request) !void {
- try r.redirectTo(self.settings.loginPage, self.settings.redirectCode);
- }
-
- fn createSessionToken(self: *Self, username: []const u8, password: []const u8) ![]const u8 {
- var hasher = Hash.init(.{});
- hasher.update(username);
- hasher.update(password);
- var buf: [16]u8 = undefined;
- const time_nano = std.time.nanoTimestamp();
- const timestampHex = try std.fmt.bufPrint(&buf, "{0x}", .{time_nano});
- hasher.update(timestampHex);
-
- var digest: [Hash.digest_length]u8 = undefined;
- hasher.final(&digest);
- const token: Token = std.fmt.bytesToHex(digest, .lower);
- const token_str = try self.allocator.dupe(u8, token[0..token.len]);
- return token_str;
- }
-
- fn createAndStoreSessionToken(self: *Self, username: []const u8, password: []const u8) ![]const u8 {
- const token = try self.createSessionToken(username, password);
- self.tokenLookupLock.lock();
- defer self.tokenLookupLock.unlock();
-
- if (!self.sessionTokens.contains(token)) {
- try self.sessionTokens.put(try self.allocator.dupe(u8, token), {});
- }
- return token;
- }
- };
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/log.zig.html b/docs/src/zap/log.zig.html
deleted file mode 100644
index 695bcbd..0000000
--- a/docs/src/zap/log.zig.html
+++ /dev/null
@@ -1,172 +0,0 @@
-
-
-
-
-
log.zig - source view
-
-
-
-
-
-
const std = @import("std");
-
-
-
-
-debugOn: bool,
-
-
-const Self = @This();
-
-pub fn init(comptime debug: bool) Self {
- return .{
- .debugOn = debug,
- };
-}
-
-pub fn log(self: *const Self, comptime fmt: []const u8, args: anytype) void {
- if (self.debugOn) {
- std.debug.print("[zap] - " ++ fmt, args);
- }
-}
-
-pub extern const fio_log_level_none: c_int;
-pub extern const fio_log_level_fatal: c_int;
-pub extern const fio_log_level_error: c_int;
-pub extern const fio_log_level_warning: c_int;
-pub extern const fio_log_level_info: c_int;
-pub extern const fio_log_level_debug: c_int;
-pub extern fn fio_set_log_level(level: c_int) void;
-pub extern fn fio_get_log_level() c_int;
-pub extern fn fio_log_print(level: c_int, msg: [*c]const u8) void;
-pub extern fn fio_log_info(msg: [*c]const u8) void;
-pub extern fn fio_log_warning(msg: [*c]const u8) void;
-pub extern fn fio_log_error(msg: [*c]const u8) void;
-pub extern fn fio_log_fatal(msg: [*c]const u8) void;
-pub extern fn fio_log_debug(msg: [*c]const u8) void;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/middleware.zig.html b/docs/src/zap/middleware.zig.html
deleted file mode 100644
index be09098..0000000
--- a/docs/src/zap/middleware.zig.html
+++ /dev/null
@@ -1,307 +0,0 @@
-
-
-
-
-
middleware.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const zap = @import("zap.zig");
-
-
-
-
-
-
-
-
-
-pub fn Handler(comptime ContextType: anytype) type {
- return struct {
- other_handler: ?*Self = null,
- on_request: ?RequestFn = null,
-
-
-
- allocator: ?std.mem.Allocator = null,
-
- pub const RequestFn = *const fn (*Self, zap.Request, *ContextType) bool;
- const Self = @This();
-
- pub fn init(on_request: RequestFn, other: ?*Self) Self {
- return .{
- .other_handler = other,
- .on_request = on_request,
- };
- }
-
-
-
-
-
-
-
- pub fn handleOther(self: *Self, r: zap.Request, context: *ContextType) bool {
-
-
-
-
-
-
-
-
-
-
-
-
- var other_handler_finished = false;
- if (self.other_handler) |other_handler| {
- if (other_handler.on_request) |on_request| {
- other_handler_finished = on_request(other_handler, r, context);
- }
- }
-
-
-
- return other_handler_finished;
- }
- };
-}
-
-
-pub fn EndpointHandler(comptime HandlerType: anytype, comptime ContextType: anytype) type {
- return struct {
- handler: HandlerType,
- endpoint: *zap.Endpoint,
- breakOnFinish: bool,
-
- const Self = @This();
-
-
-
-
- pub fn init(endpoint: *zap.Endpoint, other: ?*HandlerType, breakOnFinish: bool) Self {
- return .{
- .handler = HandlerType.init(onRequest, other),
- .endpoint = endpoint,
- .breakOnFinish = breakOnFinish,
- };
- }
-
-
- pub fn getHandler(self: *Self) *HandlerType {
- return &self.handler;
- }
-
-
-
-
-
-
- pub fn onRequest(handler: *HandlerType, r: zap.Request, context: *ContextType) bool {
- var self = @fieldParentPtr(Self, "handler", handler);
- r.setUserContext(context);
- self.endpoint.onRequest(r);
-
-
-
- if (r.isFinished() and self.breakOnFinish) {
- return true;
- }
- return self.handler.handleOther(r, context);
- }
- };
-}
-
-pub const Error = error{
-
-
- InitOnRequestIsNotNull,
-};
-
-pub const RequestAllocatorFn = *const fn () std.mem.Allocator;
-
-
-pub fn Listener(comptime ContextType: anytype) type {
- return struct {
- listener: zap.HttpListener = undefined,
- settings: zap.HttpListenerSettings,
-
-
-
- var handler: ?*Handler(ContextType) = undefined;
-
-
- var requestAllocator: ?RequestAllocatorFn = null;
-
- const Self = @This();
-
-
-
-
- pub fn init(settings: zap.HttpListenerSettings, initial_handler: *Handler(ContextType), request_alloc: ?RequestAllocatorFn) Error!Self {
-
-
- if (settings.on_request != null) {
- return Error.InitOnRequestIsNotNull;
- }
- requestAllocator = request_alloc;
- std.debug.assert(requestAllocator != null);
-
- var ret: Self = .{
- .settings = settings,
- };
-
- ret.settings.on_request = onRequest;
- ret.listener = zap.HttpListener.init(ret.settings);
- handler = initial_handler;
- return ret;
- }
-
-
- pub fn listen(self: *Self) !void {
- try self.listener.listen();
- }
-
-
-
-
-
-
-
-
- pub fn onRequest(r: zap.Request) void {
-
-
- var context: ContextType = .{};
-
-
-
-
-
- var allocator: ?std.mem.Allocator = null;
- if (requestAllocator) |foo| {
- allocator = foo();
- }
-
- if (handler) |initial_handler| {
- initial_handler.allocator = allocator;
- if (initial_handler.on_request) |on_request| {
-
-
- _ = on_request(initial_handler, r, &context);
- }
- }
- }
- };
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/mustache.zig.html b/docs/src/zap/mustache.zig.html
deleted file mode 100644
index 7a28907..0000000
--- a/docs/src/zap/mustache.zig.html
+++ /dev/null
@@ -1,383 +0,0 @@
-
-
-
-
-
mustache.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const fio = @import("fio.zig");
-const util = @import("util.zig");
-
-const Self = @This();
-
-const struct_mustache_s = opaque {};
-const mustache_s = struct_mustache_s;
-const enum_mustache_error_en = c_uint;
-const mustache_error_en = enum_mustache_error_en;
-
-extern fn fiobj_mustache_new(args: MustacheLoadArgsFio) ?*mustache_s;
-extern fn fiobj_mustache_build(mustache: ?*mustache_s, data: fio.FIOBJ) fio.FIOBJ;
-extern fn fiobj_mustache_build2(dest: fio.FIOBJ, mustache: ?*mustache_s, data: fio.FIOBJ) fio.FIOBJ;
-extern fn fiobj_mustache_free(mustache: ?*mustache_s) void;
-
-
-pub const MustacheLoadArgs = struct {
-
- filename: ?[]const u8 = null,
-
-
- data: ?[]const u8 = null,
-};
-
-
-const MustacheLoadArgsFio = extern struct {
- filename: [*c]const u8,
- filename_len: usize,
- data: [*c]const u8,
- data_len: usize,
- err: [*c]mustache_error_en,
-};
-
-
-handle: *mustache_s,
-
-pub const Error = error{
- MUSTACHE_ERR_TOO_DEEP,
- MUSTACHE_ERR_CLOSURE_MISMATCH,
- MUSTACHE_ERR_FILE_NOT_FOUND,
- MUSTACHE_ERR_FILE_TOO_BIG,
- MUSTACHE_ERR_FILE_NAME_TOO_LONG,
- MUSTACHE_ERR_FILE_NAME_TOO_SHORT,
- MUSTACHE_ERR_EMPTY_TEMPLATE,
- MUSTACHE_ERR_DELIMITER_TOO_LONG,
- MUSTACHE_ERR_NAME_TOO_LONG,
- MUSTACHE_ERR_UNKNOWN,
- MUSTACHE_ERR_USER_ERROR,
-};
-
-
-
-pub fn init(load_args: MustacheLoadArgs) Error!Self {
- var err: mustache_error_en = undefined;
-
- const args: MustacheLoadArgsFio = .{
- .filename = filn: {
- if (load_args.filename) |filn| break :filn filn.ptr else break :filn null;
- },
- .filename_len = filn_len: {
- if (load_args.filename) |filn| break :filn_len filn.len else break :filn_len 0;
- },
- .data = data: {
- if (load_args.data) |data| break :data data.ptr else break :data null;
- },
- .data_len = data_len: {
- if (load_args.data) |data| break :data_len data.len else break :data_len 0;
- },
- .err = &err,
- };
-
- const ret = fiobj_mustache_new(args);
- switch (err) {
- 0 => return Self{
- .handle = ret.?,
- },
- 1 => return Error.MUSTACHE_ERR_TOO_DEEP,
- 2 => return Error.MUSTACHE_ERR_CLOSURE_MISMATCH,
- 3 => return Error.MUSTACHE_ERR_FILE_NOT_FOUND,
- 4 => return Error.MUSTACHE_ERR_FILE_TOO_BIG,
- 5 => return Error.MUSTACHE_ERR_FILE_NAME_TOO_LONG,
- 6 => return Error.MUSTACHE_ERR_FILE_NAME_TOO_SHORT,
- 7 => return Error.MUSTACHE_ERR_EMPTY_TEMPLATE,
- 8 => return Error.MUSTACHE_ERR_DELIMITER_TOO_LONG,
- 9 => return Error.MUSTACHE_ERR_NAME_TOO_LONG,
- 10 => return Error.MUSTACHE_ERR_UNKNOWN,
- 11 => return Error.MUSTACHE_ERR_USER_ERROR,
- else => return Error.MUSTACHE_ERR_UNKNOWN,
- }
- unreachable;
-}
-
-
-
-pub fn fromData(data: []const u8) Error!Self {
- return Self.init(.{ .data = data });
-}
-
-
-
-pub fn fromFile(filename: []const u8) Error!Self {
- return Self.init(.{ .filename = filename });
-}
-
-
-pub fn deinit(self: *Self) void {
- fiobj_mustache_free(self.handle);
-}
-
-
-
-
-
-
-
-
-
-const MustacheBuildResult = struct {
- fiobj_result: fio.FIOBJ = 0,
-
-
-
- fiobj_context: fio.FIOBJ = 0,
-
-
- pub fn deinit(m: *const MustacheBuildResult) void {
- fio.fiobj_free_wrapped(m.fiobj_result);
- fio.fiobj_free_wrapped(m.fiobj_context);
- }
-
-
- pub fn str(m: *const MustacheBuildResult) ?[]const u8 {
- return util.fio2str(m.fiobj_result);
- }
-};
-
-
-
-
-
-
-
-
-
-pub fn build(self: *Self, data: anytype) MustacheBuildResult {
- const T = @TypeOf(data);
- if (@typeInfo(T) != .Struct) {
- @compileError("No struct: '" ++ @typeName(T) ++ "'");
- }
-
- var result: MustacheBuildResult = .{};
-
- result.fiobj_context = fiobjectify(data);
- result.fiobj_result = fiobj_mustache_build(self.handle, result.fiobj_context);
- return result;
-}
-
-
-
-fn fiobjectify(
- value: anytype,
-) fio.FIOBJ {
- const T = @TypeOf(value);
- switch (@typeInfo(T)) {
- .Float, .ComptimeFloat => {
- return fio.fiobj_float_new(value);
- },
- .Int, .ComptimeInt => {
- return fio.fiobj_num_new_bignum(value);
- },
- .Bool => {
- return if (value) fio.fiobj_true() else fio.fiobj_false();
- },
- .Null => {
- return 0;
- },
- .Optional => {
- if (value) |payload| {
- return fiobjectify(payload);
- } else {
- return fiobjectify(null);
- }
- },
- .Enum => {
- return fio.fiobj_num_new_bignum(@intFromEnum(value));
- },
- .Union => {
- const info = @typeInfo(T).Union;
- if (info.tag_type) |UnionTagType| {
- inline for (info.fields) |u_field| {
- if (value == @field(UnionTagType, u_field.name)) {
- return fiobjectify(@field(value, u_field.name));
- }
- }
- } else {
- @compileError("Unable to fiobjectify untagged union '" ++ @typeName(T) ++ "'");
- }
- },
- .Struct => |S| {
-
-
- const m = fio.fiobj_hash_new();
-
-
- inline for (S.fields) |Field| {
-
-
- if (Field.type == void) continue;
-
-
-
- const fname = fio.fiobj_str_new(util.toCharPtr(Field.name), Field.name.len);
-
-
- const v = @field(value, Field.name);
-
-
- const fvalue = fiobjectify(v);
-
-
- _ = fio.fiobj_hash_set(m, fname, fvalue);
- fio.fiobj_free_wrapped(fname);
- }
- return m;
- },
- .ErrorSet => return fiobjectify(@as([]const u8, @errorName(value))),
- .Pointer => |ptr_info| switch (ptr_info.size) {
- .One => switch (@typeInfo(ptr_info.child)) {
- .Array => {
- const Slice = []const std.meta.Elem(ptr_info.child);
- return fiobjectify(@as(Slice, value));
- },
- else => {
-
-
- return fiobjectify(value.*);
- },
- },
-
-
- .Slice => {
-
-
- if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
- return fio.fiobj_str_new(util.toCharPtr(value), value.len);
- }
-
- const arr = fio.fiobj_ary_new2(value.len);
- for (value) |x| {
- const v = fiobjectify(x);
- fio.fiobj_ary_push(arr, v);
- }
- return arr;
- },
- else => @compileError("Unable to fiobjectify type '" ++ @typeName(T) ++ "'"),
- },
- .Array => return fiobjectify(&value),
- .Vector => |info| {
- const array: [info.len]info.child = value;
- return fiobjectify(&array);
- },
- else => @compileError("Unable to fiobjectify type '" ++ @typeName(T) ++ "'"),
- }
- unreachable;
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/request.zig.html b/docs/src/zap/request.zig.html
deleted file mode 100644
index c5a9b08..0000000
--- a/docs/src/zap/request.zig.html
+++ /dev/null
@@ -1,942 +0,0 @@
-
-
-
-
-
request.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const Log = @import("log.zig");
-const http = @import("http.zig");
-const fio = @import("fio.zig");
-
-const util = @import("util.zig");
-const zap = @import("zap.zig");
-
-pub const HttpError = error{
- HttpSendBody,
- HttpSetContentType,
- HttpSetHeader,
- HttpParseBody,
- HttpIterParams,
- SetCookie,
- SendFile,
-};
-
-
-
-pub const ContentType = enum {
- TEXT,
- HTML,
- JSON,
-
-
-};
-
-
-pub const HttpParamStrKV = struct {
- key: util.FreeOrNot,
- value: util.FreeOrNot,
- pub fn deinit(self: *@This()) void {
- self.key.deinit();
- self.value.deinit();
- }
-};
-
-
-pub const HttpParamStrKVList = struct {
- items: []HttpParamStrKV,
- allocator: std.mem.Allocator,
- pub fn deinit(self: *@This()) void {
- for (self.items) |*item| {
- item.deinit();
- }
- self.allocator.free(self.items);
- }
-};
-
-
-pub const HttpParamKVList = struct {
- items: []HttpParamKV,
- allocator: std.mem.Allocator,
- pub fn deinit(self: *const @This()) void {
- for (self.items) |*item| {
- item.deinit();
- }
- self.allocator.free(self.items);
- }
-};
-
-
-pub const HttpParamValueType = enum {
-
-
- Bool,
- Int,
- Float,
- String,
- Unsupported,
- Hash_Binfile,
- Array_Binfile,
-};
-
-
-pub const HttpParam = union(HttpParamValueType) {
- Bool: bool,
- Int: isize,
- Float: f64,
-
- String: util.FreeOrNot,
-
- Unsupported: ?void,
-
- Hash_Binfile: HttpParamBinaryFile,
-
- Array_Binfile: std.ArrayList(HttpParamBinaryFile),
-};
-
-
-pub const HttpParamKV = struct {
- key: util.FreeOrNot,
- value: ?HttpParam,
- pub fn deinit(self: *@This()) void {
- self.key.deinit();
- if (self.value) |p| {
- switch (p) {
- .String => |*s| s.deinit(),
- else => {},
- }
- }
- }
-};
-
-
-pub const HttpParamBinaryFile = struct {
-
- data: ?[]const u8 = null,
-
- mimetype: ?[]const u8 = null,
-
- filename: ?[]const u8 = null,
-
-
- pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
- const d = value.data orelse "\\0";
- const m = value.mimetype orelse "null";
- const f = value.filename orelse "null";
- return writer.print("<{s} ({s}): {any}>", .{ f, m, d });
- }
-};
-
-fn parseBinfilesFrom(a: std.mem.Allocator, o: fio.FIOBJ) !HttpParam {
- const key_name = fio.fiobj_str_new("name", 4);
- const key_data = fio.fiobj_str_new("data", 4);
- const key_type = fio.fiobj_str_new("type", 4);
- defer {
- fio.fiobj_free_wrapped(key_name);
- fio.fiobj_free_wrapped(key_data);
- fio.fiobj_free_wrapped(key_type);
- }
-
- if (fio.fiobj_hash_haskey(o, key_data) == 1 and fio.fiobj_hash_haskey(o, key_type) == 1 and fio.fiobj_hash_haskey(o, key_name) == 1) {
- const filename = fio.fiobj_obj2cstr(fio.fiobj_hash_get(o, key_name));
- const mimetype = fio.fiobj_obj2cstr(fio.fiobj_hash_get(o, key_type));
- const data = fio.fiobj_hash_get(o, key_data);
-
- var data_slice: ?[]const u8 = null;
-
- switch (fio.fiobj_type(data)) {
- fio.FIOBJ_T_DATA => {
- if (fio.is_invalid(data) == 1) {
- data_slice = "(zap: invalid data)";
- std.log.warn("WARNING: HTTP param binary file is not a data object\n", .{});
- } else {
-
-
- const data_len = fio.fiobj_data_len(data);
- var data_buf = fio.fiobj_data_read(data, data_len);
-
- if (data_len < 0) {
- std.log.warn("WARNING: HTTP param binary file size negative: {d}\n", .{data_len});
- std.log.warn("FIOBJ_TYPE of data is: {d}\n", .{fio.fiobj_type(data)});
- } else {
- if (data_buf.len != data_len) {
- std.log.warn("WARNING: HTTP param binary file size mismatch: should {d}, is: {d}\n", .{ data_len, data_buf.len });
- }
-
- if (data_buf.len > 0) {
- data_slice = data_buf.data[0..data_buf.len];
- } else {
- std.log.warn("WARNING: HTTP param binary file buffer size negative: {d}\n", .{data_buf.len});
- data_slice = "(zap: invalid data: negative BUFFER size)";
- }
- }
- }
- },
- fio.FIOBJ_T_STRING => {
- const fiostr = fio.fiobj_obj2cstr(data);
- if (fiostr.len == 0) {
- data_slice = "(zap: empty string data)";
- std.log.warn("WARNING: HTTP param binary file has empty string object\n", .{});
- } else {
- data_slice = fiostr.data[0..fiostr.len];
- }
- },
- fio.FIOBJ_T_ARRAY => {
-
-
- const len = fio.fiobj_ary_count(data);
- const fn_ary = fio.fiobj_hash_get(o, key_name);
- const mt_ary = fio.fiobj_hash_get(o, key_type);
-
- if (fio.fiobj_ary_count(fn_ary) == len and fio.fiobj_ary_count(mt_ary) == len) {
- var i: isize = 0;
- var ret = std.ArrayList(HttpParamBinaryFile).init(a);
- while (i < len) : (i += 1) {
- const file_data_obj = fio.fiobj_ary_entry(data, i);
- const file_name_obj = fio.fiobj_ary_entry(fn_ary, i);
- const file_mimetype_obj = fio.fiobj_ary_entry(mt_ary, i);
- var has_error: bool = false;
- if (fio.is_invalid(file_data_obj) == 1) {
- std.log.debug("file data invalid in array", .{});
- has_error = true;
- }
- if (fio.is_invalid(file_name_obj) == 1) {
- std.log.debug("file name invalid in array", .{});
- has_error = true;
- }
- if (fio.is_invalid(file_mimetype_obj) == 1) {
- std.log.debug("file mimetype invalid in array", .{});
- has_error = true;
- }
- if (has_error) {
- return error.Invalid;
- }
-
- const file_data = fio.fiobj_obj2cstr(file_data_obj);
- const file_name = fio.fiobj_obj2cstr(file_name_obj);
- const file_mimetype = fio.fiobj_obj2cstr(file_mimetype_obj);
- try ret.append(.{
- .data = file_data.data[0..file_data.len],
- .mimetype = file_mimetype.data[0..file_mimetype.len],
- .filename = file_name.data[0..file_name.len],
- });
- }
- return .{ .Array_Binfile = ret };
- } else {
- return error.ArrayLenMismatch;
- }
- },
- else => {
-
-
- return error.Unsupported;
- },
- }
-
- return .{ .Hash_Binfile = .{
- .filename = filename.data[0..filename.len],
- .mimetype = mimetype.data[0..mimetype.len],
- .data = data_slice,
- } };
- } else {
- return .{ .Hash_Binfile = .{} };
- }
-}
-
-
-pub fn Fiobj2HttpParam(a: std.mem.Allocator, o: fio.FIOBJ, dupe_string: bool) !?HttpParam {
- return switch (fio.fiobj_type(o)) {
- fio.FIOBJ_T_NULL => null,
- fio.FIOBJ_T_TRUE => .{ .Bool = true },
- fio.FIOBJ_T_FALSE => .{ .Bool = false },
- fio.FIOBJ_T_NUMBER => .{ .Int = fio.fiobj_obj2num(o) },
- fio.FIOBJ_T_FLOAT => .{ .Float = fio.fiobj_obj2float(o) },
- fio.FIOBJ_T_STRING => .{ .String = try util.fio2strAllocOrNot(a, o, dupe_string) },
- fio.FIOBJ_T_ARRAY => {
- return .{ .Unsupported = null };
- },
- fio.FIOBJ_T_HASH => {
- const file = try parseBinfilesFrom(a, o);
- return file;
- },
- else => .{ .Unsupported = null },
- };
-}
-
-
-pub const CookieArgs = struct {
- name: []const u8,
- value: []const u8,
- domain: ?[]const u8 = null,
- path: ?[]const u8 = null,
-
- max_age_s: c_int = 0,
- secure: bool = true,
- http_only: bool = true,
-};
-
-path: ?[]const u8,
-query: ?[]const u8,
-body: ?[]const u8,
-method: ?[]const u8,
-h: [*c]fio.http_s,
-
-
-
-
-_user_context: *UserContext,
-
-
-
-
-
-_is_finished_request_global: bool,
-
-
-_is_finished: *bool = undefined,
-
-pub const UserContext = struct {
- user_context: ?*anyopaque = null,
-};
-
-const Self = @This();
-
-
-
-pub fn markAsFinished(self: *const Self, finished: bool) void {
-
-
- self._is_finished.* = finished;
-}
-
-
-
-pub fn isFinished(self: *const Self) bool {
-
-
- return self._is_finished.*;
-}
-
-
-
-
-pub fn setUserContext(self: *const Self, context: *anyopaque) void {
- self._user_context.*.user_context = context;
-}
-
-
-pub fn getUserContext(self: *const Self, comptime Context: type) ?*Context {
- if (self._user_context.*.user_context) |ptr| {
- return @as(*Context, @ptrCast(@alignCast(ptr)));
- } else {
- return null;
- }
-}
-
-
-pub fn sendError(self: *const Self, err: anyerror, errorcode_num: usize) void {
-
-
- if (self._internal_sendError(err, errorcode_num)) {
- return;
- } else |_| {
- self.sendBody(@errorName(err)) catch return;
- }
-}
-
-
-pub fn _internal_sendError(self: *const Self, err: anyerror, errorcode_num: usize) !void {
-
-
-
-
- self.h.*.status = errorcode_num;
- var buf: [20 * 1024]u8 = undefined;
- var fba = std.heap.FixedBufferAllocator.init(&buf);
- var string = std.ArrayList(u8).init(fba.allocator());
- var writer = string.writer();
- try writer.print("ERROR: {any}\n\n", .{err});
-
- const debugInfo = try std.debug.getSelfDebugInfo();
- const ttyConfig: std.io.tty.Config = .no_color;
- try std.debug.writeCurrentStackTrace(writer, debugInfo, ttyConfig, null);
- try self.sendBody(string.items);
-}
-
-
-pub fn sendBody(self: *const Self, body: []const u8) HttpError!void {
- const ret = fio.http_send_body(self.h, @as(
- *anyopaque,
- @ptrFromInt(@intFromPtr(body.ptr)),
- ), body.len);
- zap.debug("Request.sendBody(): ret = {}\n", .{ret});
- if (ret == -1) return error.HttpSendBody;
- self.markAsFinished(true);
-}
-
-
-pub fn sendJson(self: *const Self, json: []const u8) HttpError!void {
- if (self.setContentType(.JSON)) {
- if (fio.http_send_body(self.h, @as(
- *anyopaque,
- @ptrFromInt(@intFromPtr(json.ptr)),
- ), json.len) != 0) return error.HttpSendBody;
- self.markAsFinished(true);
- } else |err| return err;
-}
-
-
-pub fn setContentType(self: *const Self, c: ContentType) HttpError!void {
- const s = switch (c) {
- .TEXT => "text/plain",
- .JSON => "application/json",
- else => "text/html",
- };
- zap.debug("setting content-type to {s}\n", .{s});
- return self.setHeader("content-type", s);
-}
-
-
-pub fn redirectTo(self: *const Self, path: []const u8, code: ?http.StatusCode) HttpError!void {
- self.setStatus(if (code) |status| status else .found);
- try self.setHeader("Location", path);
- try self.sendBody("moved");
- self.markAsFinished(true);
-}
-
-
-pub fn setContentTypeWithLogger(
- self: *const Self,
- c: ContentType,
- logger: *const Log,
-) HttpError!void {
- const s = switch (c) {
- .TEXT => "text/plain",
- .JSON => "application/json",
- else => "text/html",
- };
- logger.log("setting content-type to {s}\n", .{s});
- return self.setHeader("content-type", s);
-}
-
-
-pub fn setContentTypeFromPath(self: *const Self) !void {
- const t = fio.http_mimetype_find2(self.h.*.path);
- if (fio.is_invalid(t) == 1) return error.HttpSetContentType;
- const ret = fio.fiobj_hash_set(
- self.h.*.private_data.out_headers,
- fio.HTTP_HEADER_CONTENT_TYPE,
- t,
- );
- if (ret == -1) return error.HttpSetContentType;
-}
-
-
-
-
-pub fn setContentTypeFromFilename(self: *const Self, filename: []const u8) !void {
- const ext = std.fs.path.extension(filename);
-
- if (ext.len > 1) {
- const e = ext[1..];
- const obj = fio.http_mimetype_find(@constCast(e.ptr), e.len);
-
- if (util.fio2str(obj)) |mime_str| {
- try self.setHeader("content-type", mime_str);
- }
- } else {
- return error.NoExtensionInFilename;
- }
-}
-
-
-
-pub fn getHeader(self: *const Self, name: []const u8) ?[]const u8 {
- const hname = fio.fiobj_str_new(util.toCharPtr(name), name.len);
- defer fio.fiobj_free_wrapped(hname);
- return util.fio2str(fio.fiobj_hash_get(self.h.*.headers, hname));
-}
-
-
-pub fn setHeader(self: *const Self, name: []const u8, value: []const u8) HttpError!void {
- const hname: fio.fio_str_info_s = .{
- .data = util.toCharPtr(name),
- .len = name.len,
- .capa = name.len,
- };
-
- zap.debug("setHeader: hname = {s}\n", .{name});
- const vname: fio.fio_str_info_s = .{
- .data = util.toCharPtr(value),
- .len = value.len,
- .capa = value.len,
- };
- zap.debug("setHeader: vname = {s}\n", .{value});
- const ret = fio.http_set_header2(self.h, hname, vname);
-
-
-
-
-
- if (ret == -1) {
- std.debug.print("***************** zap.zig:274\n", .{});
- }
- zap.debug("setHeader: ret = {}\n", .{ret});
-
- if (ret == 0) return;
- return error.HttpSetHeader;
-}
-
-
-pub fn setStatusNumeric(self: *const Self, status: usize) void {
- self.h.*.status = status;
-}
-
-
-pub fn setStatus(self: *const Self, status: http.StatusCode) void {
- self.h.*.status = @as(usize, @intCast(@intFromEnum(status)));
-}
-
-
-
-
-
-
-
-
-
-
-
-
-pub fn sendFile(self: *const Self, file_path: []const u8) !void {
- if (fio.http_sendfile2(self.h, util.toCharPtr(file_path), file_path.len, null, 0) != 0)
- return error.SendFile;
- self.markAsFinished(true);
-}
-
-
-
-
-
-
-
-
-
-pub fn parseBody(self: *const Self) HttpError!void {
- if (fio.http_parse_body(self.h) == -1) return error.HttpParseBody;
-}
-
-
-
-
-
-
-pub fn parseQuery(self: *const Self) void {
- fio.http_parse_query(self.h);
-}
-
-
-pub fn parseCookies(self: *const Self, url_encoded: bool) void {
- fio.http_parse_cookies(self.h, if (url_encoded) 1 else 0);
-}
-
-
-pub fn setCookie(self: *const Self, args: CookieArgs) HttpError!void {
- const c: fio.http_cookie_args_s = .{
- .name = util.toCharPtr(args.name),
- .name_len = @as(isize, @intCast(args.name.len)),
- .value = util.toCharPtr(args.value),
- .value_len = @as(isize, @intCast(args.value.len)),
- .domain = if (args.domain) |p| util.toCharPtr(p) else null,
- .domain_len = if (args.domain) |p| @as(isize, @intCast(p.len)) else 0,
- .path = if (args.path) |p| util.toCharPtr(p) else null,
- .path_len = if (args.path) |p| @as(isize, @intCast(p.len)) else 0,
- .max_age = args.max_age_s,
- .secure = if (args.secure) 1 else 0,
- .http_only = if (args.http_only) 1 else 0,
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
- const ret = fio.http_set_cookie(self.h, c);
- if (ret == -1) {
- std.log.err("fio.http_set_cookie returned: {}\n", .{ret});
- return error.SetCookie;
- }
-}
-
-
-pub fn getCookieStr(self: *const Self, a: std.mem.Allocator, name: []const u8, always_alloc: bool) !?util.FreeOrNot {
- if (self.h.*.cookies == 0) return null;
- const key = fio.fiobj_str_new(name.ptr, name.len);
- defer fio.fiobj_free_wrapped(key);
- const value = fio.fiobj_hash_get(self.h.*.cookies, key);
- if (value == fio.FIOBJ_INVALID) {
- return null;
- }
- return try util.fio2strAllocOrNot(a, value, always_alloc);
-}
-
-
-
-
-pub fn getCookiesCount(self: *const Self) isize {
- if (self.h.*.cookies == 0) return 0;
- return fio.fiobj_obj2num(self.h.*.cookies);
-}
-
-
-
-
-pub fn getParamCount(self: *const Self) isize {
- if (self.h.*.params == 0) return 0;
- return fio.fiobj_obj2num(self.h.*.params);
-}
-
-
-pub fn cookiesToOwnedStrList(self: *const Self, a: std.mem.Allocator, always_alloc: bool) anyerror!HttpParamStrKVList {
- var params = try std.ArrayList(HttpParamStrKV).initCapacity(a, @as(usize, @intCast(self.getCookiesCount())));
- var context: _parametersToOwnedStrSliceContext = .{
- .params = ¶ms,
- .allocator = a,
- .always_alloc = always_alloc,
- };
- const howmany = fio.fiobj_each1(self.h.*.cookies, 0, _each_nextParamStr, &context);
- if (howmany != self.getCookiesCount()) {
- return error.HttpIterParams;
- }
- return .{ .items = try params.toOwnedSlice(), .allocator = a };
-}
-
-
-pub fn cookiesToOwnedList(self: *const Self, a: std.mem.Allocator, dupe_strings: bool) !HttpParamKVList {
- var params = try std.ArrayList(HttpParamKV).initCapacity(a, @as(usize, @intCast(self.getCookiesCount())));
- var context: _parametersToOwnedSliceContext = .{ .params = ¶ms, .allocator = a, .dupe_strings = dupe_strings };
- const howmany = fio.fiobj_each1(self.h.*.cookies, 0, _each_nextParam, &context);
- if (howmany != self.getCookiesCount()) {
- return error.HttpIterParams;
- }
- return .{ .items = try params.toOwnedSlice(), .allocator = a };
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub fn parametersToOwnedStrList(self: *const Self, a: std.mem.Allocator, always_alloc: bool) anyerror!HttpParamStrKVList {
- var params = try std.ArrayList(HttpParamStrKV).initCapacity(a, @as(usize, @intCast(self.getParamCount())));
- var context: _parametersToOwnedStrSliceContext = .{
- .params = ¶ms,
- .allocator = a,
- .always_alloc = always_alloc,
- };
- const howmany = fio.fiobj_each1(self.h.*.params, 0, _each_nextParamStr, &context);
- if (howmany != self.getParamCount()) {
- return error.HttpIterParams;
- }
- return .{ .items = try params.toOwnedSlice(), .allocator = a };
-}
-
-const _parametersToOwnedStrSliceContext = struct {
- allocator: std.mem.Allocator,
- params: *std.ArrayList(HttpParamStrKV),
- last_error: ?anyerror = null,
- always_alloc: bool,
-};
-
-fn _each_nextParamStr(fiobj_value: fio.FIOBJ, context: ?*anyopaque) callconv(.C) c_int {
- const ctx: *_parametersToOwnedStrSliceContext = @as(*_parametersToOwnedStrSliceContext, @ptrCast(@alignCast(context)));
-
-
- const fiobj_key: fio.FIOBJ = fio.fiobj_hash_key_in_loop();
- ctx.params.append(.{
- .key = util.fio2strAllocOrNot(ctx.allocator, fiobj_key, ctx.always_alloc) catch |err| {
- ctx.last_error = err;
- return -1;
- },
- .value = util.fio2strAllocOrNot(ctx.allocator, fiobj_value, ctx.always_alloc) catch |err| {
- ctx.last_error = err;
- return -1;
- },
- }) catch |err| {
-
-
-
-
-
-
- ctx.last_error = err;
- return -1;
- };
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub fn parametersToOwnedList(self: *const Self, a: std.mem.Allocator, dupe_strings: bool) !HttpParamKVList {
- var params = try std.ArrayList(HttpParamKV).initCapacity(a, @as(usize, @intCast(self.getParamCount())));
- var context: _parametersToOwnedSliceContext = .{ .params = ¶ms, .allocator = a, .dupe_strings = dupe_strings };
- const howmany = fio.fiobj_each1(self.h.*.params, 0, _each_nextParam, &context);
- if (howmany != self.getParamCount()) {
- return error.HttpIterParams;
- }
- return .{ .items = try params.toOwnedSlice(), .allocator = a };
-}
-
-const _parametersToOwnedSliceContext = struct {
- params: *std.ArrayList(HttpParamKV),
- last_error: ?anyerror = null,
- allocator: std.mem.Allocator,
- dupe_strings: bool,
-};
-
-fn _each_nextParam(fiobj_value: fio.FIOBJ, context: ?*anyopaque) callconv(.C) c_int {
- const ctx: *_parametersToOwnedSliceContext = @as(*_parametersToOwnedSliceContext, @ptrCast(@alignCast(context)));
-
-
- const fiobj_key: fio.FIOBJ = fio.fiobj_hash_key_in_loop();
- ctx.params.append(.{
- .key = util.fio2strAllocOrNot(ctx.allocator, fiobj_key, ctx.dupe_strings) catch |err| {
- ctx.last_error = err;
- return -1;
- },
- .value = Fiobj2HttpParam(ctx.allocator, fiobj_value, ctx.dupe_strings) catch |err| {
- ctx.last_error = err;
- return -1;
- },
- }) catch |err| {
-
-
-
-
-
-
- ctx.last_error = err;
- return -1;
- };
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub fn getParamStr(self: *const Self, a: std.mem.Allocator, name: []const u8, always_alloc: bool) !?util.FreeOrNot {
- if (self.h.*.params == 0) return null;
- const key = fio.fiobj_str_new(name.ptr, name.len);
- defer fio.fiobj_free_wrapped(key);
- const value = fio.fiobj_hash_get(self.h.*.params, key);
- if (value == fio.FIOBJ_INVALID) {
- return null;
- }
- return try util.fio2strAllocOrNot(a, value, always_alloc);
-}
-
-
-
-
-
-pub fn getParamSlice(self: *const Self, name: []const u8) ?[]const u8 {
- if (self.query) |query| {
- var amp_it = std.mem.tokenizeScalar(u8, query, '&');
- while (amp_it.next()) |maybe_pair| {
- if (std.mem.indexOfScalar(u8, maybe_pair, '=')) |pos_of_eq| {
- const pname = maybe_pair[0..pos_of_eq];
- if (std.mem.eql(u8, pname, name)) {
- if (maybe_pair.len > pos_of_eq) {
- const pval = maybe_pair[pos_of_eq + 1 ..];
- return pval;
- }
- }
- }
- }
- }
- return null;
-}
-
-pub const ParameterSlices = struct { name: []const u8, value: []const u8 };
-
-pub const ParamSliceIterator = struct {
- amp_it: std.mem.TokenIterator(u8, .scalar),
-
- pub fn init(query: []const u8) @This() {
- return .{
- .amp_it = std.mem.tokenizeScalar(u8, query, '&'),
- };
- }
-
- pub fn next(self: *@This()) ?ParameterSlices {
- while (self.amp_it.next()) |maybe_pair| {
- if (std.mem.indexOfScalar(u8, maybe_pair, '=')) |pos_of_eq| {
- const pname = maybe_pair[0..pos_of_eq];
- if (maybe_pair.len > pos_of_eq) {
- const pval = maybe_pair[pos_of_eq + 1 ..];
- return .{ .name = pname, .value = pval };
- }
- }
- }
- return null;
- }
-};
-
-
-
-
-pub fn getParamSlices(self: *const Self) ParamSliceIterator {
- const query = self.query orelse "";
- return ParamSliceIterator.init(query);
-}
-
-pub fn methodAsEnum(self: *const Self) http.Method {
- return http.methodToEnum(self.method);
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/router.zig.html b/docs/src/zap/router.zig.html
deleted file mode 100644
index 907992a..0000000
--- a/docs/src/zap/router.zig.html
+++ /dev/null
@@ -1,179 +0,0 @@
-
-
-
-
-
router.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const zap = @import("zap.zig");
-
-const Allocator = std.mem.Allocator;
-const RouterError = error{
- AlreadyExists,
- EmptyPath,
-};
-
-const Self = @This();
-
-pub const Options = struct {
- not_found: ?zap.HttpRequestFn = null,
-};
-
-routes: std.StringHashMap(zap.HttpRequestFn),
-not_found: ?zap.HttpRequestFn,
-
-pub fn init(allocator: Allocator, options: Options) Self {
- return .{
- .routes = std.StringHashMap(zap.HttpRequestFn).init(allocator),
-
- .not_found = options.not_found,
- };
-}
-
-pub fn deinit(self: *Self) void {
- self.routes.deinit();
-}
-
-pub fn handle_func(self: *Self, path: []const u8, h: zap.HttpRequestFn) !void {
- if (path.len == 0) {
- return RouterError.EmptyPath;
- }
-
- const route = self.routes.get(path);
-
- if (route != null) {
- return RouterError.AlreadyExists;
- }
-
- try self.routes.put(path, h);
-}
-
-pub fn serve(self: *Self, r: zap.Request) void {
- const path = if (r.path) |p| p else "/";
-
- const route = self.routes.get(path);
-
- if (route) |handler| {
- handler(r);
- } else if (self.not_found) |handler| {
-
-
- handler(r);
- } else {
-
-
- r.setStatus(.not_found);
- r.sendBody("404 Not Found") catch return;
- }
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/tls.zig.html b/docs/src/zap/tls.zig.html
deleted file mode 100644
index 7bc80ba..0000000
--- a/docs/src/zap/tls.zig.html
+++ /dev/null
@@ -1,202 +0,0 @@
-
-
-
-
-
tls.zig - source view
-
-
-
-
-
-
const fio = @import("fio.zig");
-
-
-const Tls = @This();
-
-fio_tls: ?*anyopaque = null,
-
-
-
-
-pub const TlsSettings = struct {
-
-
- server_name: ?[*:0]const u8 = null,
- public_certificate_file: ?[*:0]const u8 = null,
- private_key_file: ?[*:0]const u8 = null,
-
- private_key_password: ?[*:0]const u8 = null,
-};
-
-
-
-
-
-
-pub fn init(settings: TlsSettings) !Tls {
- const ret = fio.fio_tls_new(
- settings.server_name,
- settings.public_certificate_file,
- settings.private_key_file,
- settings.private_key_password,
- );
- if (ret == null) return error.FileNotFound;
- return Tls{ .fio_tls = ret };
-}
-
-
-pub fn deinit(tls: *const Tls) void {
- fio.fio_tls_destroy(tls.fio_tls);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub fn addCertificate(tls: *Tls, settings: TlsSettings) !void {
- if (tls.fio_tls == null) {
- return error.Uninitialized;
- }
-
- const ret = fio.fio_tls_cert_add(
- tls.fio_tls,
- settings.server_name,
- settings.public_certificate_file,
- settings.private_key_file,
- settings.private_key_password,
- );
-
- if (ret != 0) return error.FileNotFound;
- return;
-}
-
-
-
-
-pub fn trust(tls: *Tls, public_cert_file: [*:0]const u8) !void {
- if (tls.fio_tls == null) {
- return error.Uninitialized;
- }
-
- const ret = fio.fio_tls_trust(tls.fio_tls, public_cert_file);
- if (ret != 0) return error.FileNotFound;
- return;
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/util.zig.html b/docs/src/zap/util.zig.html
deleted file mode 100644
index 06309e5..0000000
--- a/docs/src/zap/util.zig.html
+++ /dev/null
@@ -1,226 +0,0 @@
-
-
-
-
-
util.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const fio = @import("fio.zig");
-const zap = @import("zap.zig");
-
-
-pub inline fn RequestHandler(self: anytype, func: *const fn (@TypeOf(self), zap.Request) void) *const fn (zap.Request) void {
- return (opaque {
- var hidden_self: @TypeOf(self) = undefined;
- var hidden_func: *const fn (@TypeOf(self), zap.Request) void = undefined;
- pub fn init(h_self: @TypeOf(self), h_func: *const fn (@TypeOf(self), zap.Request) void) *const @TypeOf(run) {
- hidden_self = h_self;
- hidden_func = h_func;
- return &run;
- }
-
- fn run(req: zap.Request) void {
- hidden_func(hidden_self, req);
- }
- }).init(self, func);
-}
-
-
-
-
-
-pub fn fio2str(o: fio.FIOBJ) ?[]const u8 {
- if (o == 0) return null;
- const x: fio.fio_str_info_s = fio.fiobj_obj2cstr(o);
- if (x.data == 0)
- return null;
-
- return x.data[0..x.len];
-}
-
-
-
-
-
-
-
-pub const FreeOrNot = struct {
- str: []const u8,
- freeme: bool,
- allocator: ?std.mem.Allocator = null,
-
- pub fn deinit(self: *const @This()) void {
- if (self.freeme) {
- self.allocator.?.free(self.str);
- }
- }
-};
-
-
-
-
-pub fn fio2strAllocOrNot(a: std.mem.Allocator, o: fio.FIOBJ, always_alloc: bool) !FreeOrNot {
- if (o == 0) return .{ .str = "null", .freeme = false };
- if (o == fio.FIOBJ_INVALID) return .{ .str = "invalid", .freeme = false };
- return switch (fio.fiobj_type(o)) {
- fio.FIOBJ_T_TRUE => .{ .str = "true", .freeme = false },
- fio.FIOBJ_T_FALSE => .{ .str = "false", .freeme = false },
-
-
- fio.FIOBJ_T_NUMBER => .{ .str = try a.dupe(u8, fio2str(o) orelse "null"), .freeme = true, .allocator = a },
- fio.FIOBJ_T_FLOAT => .{ .str = try a.dupe(u8, fio2str(o) orelse "null"), .freeme = true, .allocator = a },
-
-
- fio.FIOBJ_T_STRING => .{ .str = if (always_alloc) try a.dupe(u8, fio2str(o) orelse "") else fio2str(o) orelse "", .freeme = if (always_alloc) true else false, .allocator = a },
- else => .{ .str = "unknown_type", .freeme = false },
- };
-}
-
-
-pub fn str2fio(s: []const u8) fio.fio_str_info_s {
- return .{
- .data = toCharPtr(s),
- .len = s.len,
- .capa = s.len,
- };
-}
-
-
-pub fn toCharPtr(s: []const u8) [*c]u8 {
- return @as([*c]u8, @ptrFromInt(@intFromPtr(s.ptr)));
-}
-
-
-
-
-
-
-
-
-
-
-pub fn stringifyBuf(
- buffer: []u8,
- value: anytype,
- options: std.json.StringifyOptions,
-) ?[]const u8 {
- var fba = std.heap.FixedBufferAllocator.init(buffer);
- var string = std.ArrayList(u8).init(fba.allocator());
- if (std.json.stringify(value, options, string.writer())) {
- return string.items;
- } else |_| {
-
- return null;
- }
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/websockets.zig.html b/docs/src/zap/websockets.zig.html
deleted file mode 100644
index de0db91..0000000
--- a/docs/src/zap/websockets.zig.html
+++ /dev/null
@@ -1,346 +0,0 @@
-
-
-
-
-
websockets.zig - source view
-
-
-
-
-
-
const std = @import("std");
-const zap = @import("zap.zig");
-const fio = @import("fio.zig");
-const util = @import("util.zig");
-
-
-pub const WsHandle = ?*fio.ws_s;
-
-
-
-
-pub fn Handler(comptime ContextType: type) type {
- return struct {
-
- pub const WsOnMessageFn = *const fn (
-
- context: ?*ContextType,
-
- handle: WsHandle,
-
- message: []const u8,
-
- is_text: bool,
- ) void;
-
-
-
- pub const WsOnCloseFn = *const fn (context: ?*ContextType, uuid: isize) void;
-
-
-
- pub const WsFn = *const fn (context: ?*ContextType, handle: WsHandle) void;
-
-
-
- pub const WebSocketSettings = struct {
-
- on_message: ?WsOnMessageFn = null,
-
- on_open: ?WsFn = null,
-
- on_ready: ?WsFn = null,
-
- on_shutdown: ?WsFn = null,
-
- on_close: ?WsOnCloseFn = null,
-
- context: ?*ContextType = null,
- };
-
-
- pub fn upgrade(h: [*c]fio.http_s, settings: *WebSocketSettings) WebSocketError!void {
- const fio_settings: fio.websocket_settings_s = .{
- .on_message = internal_on_message,
- .on_open = internal_on_open,
- .on_ready = internal_on_ready,
- .on_shutdown = internal_on_shutdown,
- .on_close = internal_on_close,
- .udata = settings,
- };
- if (fio.http_upgrade2ws(h, fio_settings) != 0) {
- return error.UpgradeError;
- }
- }
-
- fn internal_on_message(handle: WsHandle, msg: fio.fio_str_info_s, is_text: u8) callconv(.C) void {
- const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
- const message = msg.data[0..msg.len];
- if (user_provided_settings) |settings| {
- if (settings.on_message) |on_message| {
- on_message(settings.context, handle, message, is_text == 1);
- }
- }
- }
-
- fn internal_on_open(handle: WsHandle) callconv(.C) void {
- const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
- if (user_provided_settings) |settings| {
- if (settings.on_open) |on_open| {
- on_open(settings.context, handle);
- }
- }
- }
-
- fn internal_on_ready(handle: WsHandle) callconv(.C) void {
- const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
- if (user_provided_settings) |settings| {
- if (settings.on_ready) |on_ready| {
- on_ready(settings.context, handle);
- }
- }
- }
-
- fn internal_on_shutdown(handle: WsHandle) callconv(.C) void {
- const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
- if (user_provided_settings) |settings| {
- if (settings.on_shutdown) |on_shutdown| {
- on_shutdown(settings.context, handle);
- }
- }
- }
-
- fn internal_on_close(uuid: isize, udata: ?*anyopaque) callconv(.C) void {
- const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(udata)));
- if (user_provided_settings) |settings| {
- if (settings.on_close) |on_close| {
- on_close(settings.context, uuid);
- }
- }
- }
-
- pub const WebSocketError = error{
- WriteError,
- UpgradeError,
- SubscribeError,
- };
-
-
- pub inline fn write(handle: WsHandle, message: []const u8, is_text: bool) WebSocketError!void {
- if (fio.websocket_write(
- handle,
- fio.str2fio(message),
- if (is_text) 1 else 0,
- ) != 0) {
- return error.WriteError;
- }
- }
-
-
-
-
- pub fn udataToContext(udata: *anyopaque) *ContextType {
- return @as(*ContextType, @ptrCast(@alignCast(udata)));
- }
-
-
- pub inline fn close(handle: WsHandle) void {
- fio.websocket_close(handle);
- }
-
-
- const PublishArgs = struct {
- channel: []const u8,
- message: []const u8,
- is_json: bool = false,
- };
-
-
- pub inline fn publish(args: PublishArgs) void {
- fio.fio_publish(.{
- .channel = util.str2fio(args.channel),
- .message = util.str2fio(args.message),
- .is_json = if (args.is_json) 1 else 0,
- });
- }
-
-
- pub const SubscriptionOnMessageFn = *const fn (context: ?*ContextType, handle: WsHandle, channel: []const u8, message: []const u8) void;
-
-
- pub const SubscriptionOnUnsubscribeFn = *const fn (context: ?*ContextType) void;
-
-
- pub const SubscribeArgs = struct {
-
- channel: []const u8,
-
- on_message: ?SubscriptionOnMessageFn = null,
-
- on_unsubscribe: ?SubscriptionOnUnsubscribeFn = null,
-
- match: fio.fio_match_fn = null,
-
-
-
-
-
- force_binary: bool = false,
-
-
-
-
-
- force_text: bool = false,
-
- context: ?*ContextType = null,
- };
-
-
-
-
-
- pub inline fn subscribe(handle: WsHandle, args: *SubscribeArgs) WebSocketError!usize {
- if (handle == null) return error.SubscribeError;
- const fio_args: fio.websocket_subscribe_s_zigcompat = .{
- .ws = handle.?,
- .channel = util.str2fio(args.channel),
- .on_message = if (args.on_message) |_| internal_subscription_on_message else null,
- .on_unsubscribe = if (args.on_unsubscribe) |_| internal_subscription_on_unsubscribe else null,
- .match = args.match,
- .force_binary = if (args.force_binary) 1 else 0,
- .force_text = if (args.force_text) 1 else 0,
- .udata = args,
- };
- const ret = fio.websocket_subscribe_zigcompat(fio_args);
- if (ret == 0) {
- return error.SubscribeError;
- }
- return ret;
- }
-
- pub fn internal_subscription_on_message(handle: WsHandle, channel: fio.fio_str_info_s, message: fio.fio_str_info_s, udata: ?*anyopaque) callconv(.C) void {
- if (udata) |p| {
- const args = @as(*SubscribeArgs, @ptrCast(@alignCast(p)));
- if (args.on_message) |on_message| {
- on_message(args.context, handle, channel.data[0..channel.len], message.data[0..message.len]);
- }
- }
- }
- pub fn internal_subscription_on_unsubscribe(udata: ?*anyopaque) callconv(.C) void {
- if (udata) |p| {
- const args = @as(*SubscribeArgs, @ptrCast(@alignCast(p)));
- if (args.on_unsubscribe) |on_unsubscribe| {
- on_unsubscribe(args.context);
- }
- }
- }
- };
-}
-
-
-
\ No newline at end of file
diff --git a/docs/src/zap/zap.zig.html b/docs/src/zap/zap.zig.html
deleted file mode 100644
index f5bfdd2..0000000
--- a/docs/src/zap/zap.zig.html
+++ /dev/null
@@ -1,550 +0,0 @@
-
-
-
-
-
zap.zig - source view
-
-
-
-
-
-
-
-
-
-
-const std = @import("std");
-
-
-pub const fio = @import("fio.zig");
-
-
-pub const Tls = @import("tls.zig");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-pub const Endpoint = @import("endpoint.zig");
-
-pub const Router = @import("router.zig");
-
-pub usingnamespace @import("util.zig");
-pub usingnamespace @import("http.zig");
-
-
-
-
-
-pub const Mustache = @import("mustache.zig");
-
-
-pub const Auth = @import("http_auth.zig");
-
-
-pub const Request = @import("request.zig");
-
-
-
-
-
-
-pub const Middleware = @import("middleware.zig");
-
-
-pub const WebSockets = @import("websockets.zig");
-
-pub const Log = @import("log.zig");
-const http = @import("http.zig");
-
-const util = @import("util.zig");
-
-
-
-var _debug: bool = false;
-
-
-
-
-pub fn start(args: fio.fio_start_args) void {
- fio.fio_start(args);
-}
-
-
-
-
-
-
-pub fn stop() void {
- fio.fio_stop();
-}
-
-
-
-pub fn debug(comptime fmt: []const u8, args: anytype) void {
- if (_debug) {
- std.debug.print("[zap] - " ++ fmt, args);
- }
-}
-
-
-pub fn enableDebugLog() void {
- _debug = true;
-}
-
-
-pub fn startWithLogging(args: fio.fio_start_args) void {
- debug = true;
- fio.fio_start(args);
-}
-
-pub const ListenError = error{
- AlreadyListening,
- ListenError,
-};
-
-pub const HttpError = error{
- HttpSendBody,
- HttpSetContentType,
- HttpSetHeader,
- HttpParseBody,
- HttpIterParams,
- SetCookie,
- SendFile,
-};
-
-
-
-pub const ContentType = enum {
- TEXT,
- HTML,
- JSON,
-
-
-};
-
-
-pub const FioHttpRequestFn = *const fn (r: [*c]fio.http_s) callconv(.C) void;
-
-
-pub const HttpRequestFn = *const fn (Request) void;
-
-
-
-pub const HttpUpgradeFn = *const fn (r: Request, target_protocol: []const u8) void;
-
-
-
-pub const HttpFinishSettings = [*c]fio.struct_http_settings_s;
-
-
-pub const HttpFinishFn = *const fn (HttpFinishSettings) void;
-
-
-pub const HttpListenerSettings = struct {
- port: usize,
- interface: [*c]const u8 = null,
- on_request: ?HttpRequestFn,
- on_response: ?HttpRequestFn = null,
- on_upgrade: ?HttpUpgradeFn = null,
- on_finish: ?HttpFinishFn = null,
-
-
-
-
- udata: ?*anyopaque = null,
- public_folder: ?[]const u8 = null,
- max_clients: ?isize = null,
- max_body_size: ?usize = null,
- timeout: ?u8 = null,
- log: bool = false,
- ws_timeout: u8 = 40,
- ws_max_msg_size: usize = 262144,
- tls: ?Tls = null,
-};
-
-
-pub const HttpListener = struct {
- settings: HttpListenerSettings,
-
- const Self = @This();
- var the_one_and_only_listener: ?*HttpListener = null;
-
-
- pub fn init(settings: HttpListenerSettings) Self {
- std.debug.assert(settings.on_request != null);
- return .{
- .settings = settings,
- };
- }
-
-
-
-
- pub fn theOneAndOnlyRequestCallBack(r: [*c]fio.http_s) callconv(.C) void {
- if (the_one_and_only_listener) |l| {
- var req: Request = .{
- .path = util.fio2str(r.*.path),
- .query = util.fio2str(r.*.query),
- .body = util.fio2str(r.*.body),
- .method = util.fio2str(r.*.method),
- .h = r,
- ._is_finished_request_global = false,
- ._user_context = undefined,
- };
- req._is_finished = &req._is_finished_request_global;
-
- var user_context: Request.UserContext = .{};
- req._user_context = &user_context;
-
- req.markAsFinished(false);
- std.debug.assert(l.settings.on_request != null);
- if (l.settings.on_request) |on_request| {
-
-
- on_request(req);
- }
- }
- }
-
-
- pub fn theOneAndOnlyResponseCallBack(r: [*c]fio.http_s) callconv(.C) void {
- if (the_one_and_only_listener) |l| {
- var req: Request = .{
- .path = util.fio2str(r.*.path),
- .query = util.fio2str(r.*.query),
- .body = util.fio2str(r.*.body),
- .method = util.fio2str(r.*.method),
- .h = r,
- ._is_finished_request_global = false,
- ._user_context = undefined,
- };
- req._is_finished = &req._is_finished_request_global;
-
- var user_context: Request.UserContext = .{};
- req._user_context = &user_context;
-
- l.settings.on_response.?(req);
- }
- }
-
-
- pub fn theOneAndOnlyUpgradeCallBack(r: [*c]fio.http_s, target: [*c]u8, target_len: usize) callconv(.C) void {
- if (the_one_and_only_listener) |l| {
- var req: Request = .{
- .path = util.fio2str(r.*.path),
- .query = util.fio2str(r.*.query),
- .body = util.fio2str(r.*.body),
- .method = util.fio2str(r.*.method),
- .h = r,
- ._is_finished_request_global = false,
- ._user_context = undefined,
- };
- const zigtarget: []u8 = target[0..target_len];
- req._is_finished = &req._is_finished_request_global;
-
- var user_context: Request.UserContext = .{};
- req._user_context = &user_context;
-
- l.settings.on_upgrade.?(req, zigtarget);
- }
- }
-
-
- pub fn theOneAndOnlyFinishCallBack(s: [*c]fio.struct_http_settings_s) callconv(.C) void {
- if (the_one_and_only_listener) |l| {
- l.settings.on_finish.?(s);
- }
- }
-
-
- pub fn listen(self: *Self) !void {
- var pfolder: [*c]const u8 = null;
- var pfolder_len: usize = 0;
-
- if (self.settings.public_folder) |pf| {
- debug("HttpListener.listen(): public folder is {s}\n", .{pf});
- pfolder_len = pf.len;
- pfolder = pf.ptr;
- }
-
- const x: fio.http_settings_s = .{
- .on_request = if (self.settings.on_request) |_| Self.theOneAndOnlyRequestCallBack else null,
- .on_upgrade = if (self.settings.on_upgrade) |_| Self.theOneAndOnlyUpgradeCallBack else null,
- .on_response = if (self.settings.on_response) |_| Self.theOneAndOnlyResponseCallBack else null,
- .on_finish = if (self.settings.on_finish) |_| Self.theOneAndOnlyFinishCallBack else null,
- .udata = null,
- .public_folder = pfolder,
- .public_folder_length = pfolder_len,
- .max_header_size = 32 * 1024,
- .max_body_size = self.settings.max_body_size orelse 50 * 1024 * 1024,
-
-
- .max_clients = self.settings.max_clients orelse 0,
- .tls = if (self.settings.tls) |tls| tls.fio_tls else null,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- .ws_max_msg_size = 0,
- .timeout = self.settings.timeout orelse 5,
- .ws_timeout = self.settings.ws_timeout,
- .log = if (self.settings.log) 1 else 0,
- .is_client = 0,
- };
-
-
-
-
-
-
-
-
- std.time.sleep(500 * std.time.ns_per_ms);
-
- var portbuf: [100]u8 = undefined;
- const printed_port = try std.fmt.bufPrintZ(&portbuf, "{d}", .{self.settings.port});
-
- const ret = fio.http_listen(printed_port.ptr, self.settings.interface, x);
- if (ret == -1) {
- return error.ListenError;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- Self.the_one_and_only_listener = self;
- }
-};
-
-
-pub const LowLevel = struct {
-
-
- pub const ListenSettings = struct {
- on_request: ?FioHttpRequestFn = null,
- on_upgrade: ?FioHttpRequestFn = null,
- on_response: ?FioHttpRequestFn = null,
- on_finish: ?FioHttpRequestFn = null,
- public_folder: ?[]const u8 = null,
- max_header_size: usize = 32 * 1024,
- max_body_size: usize = 50 * 1024 * 1024,
- max_clients: isize = 100,
- keepalive_timeout_s: u8 = 5,
- log: bool = false,
-
- const Self = @This();
-
-
- pub fn init() Self {
- return .{};
- }
- };
-
-
- pub fn listen(port: [*c]const u8, interface: [*c]const u8, settings: ListenSettings) ListenError!void {
- var pfolder: [*c]const u8 = null;
- var pfolder_len: usize = 0;
-
- if (settings.public_folder) |pf| {
- pfolder_len = pf.len;
- pfolder = pf.ptr;
- }
- const x: fio.http_settings_s = .{
- .on_request = settings.on_request,
- .on_upgrade = settings.on_upgrade,
- .on_response = settings.on_response,
- .on_finish = settings.on_finish,
- .udata = null,
- .public_folder = pfolder,
- .public_folder_length = pfolder_len,
- .max_header_size = settings.max_header_size,
- .max_body_size = settings.max_body_size,
- .max_clients = settings.max_clients,
- .tls = null,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- .ws_max_msg_size = settings.ws_max_msg_size,
- .timeout = settings.keepalive_timeout_s,
- .ws_timeout = 0,
- .log = if (settings.log) 1 else 0,
- .is_client = 0,
- };
-
-
-
-
-
-
-
-
- std.time.sleep(500 * std.time.ns_per_ms);
-
- if (fio.http_listen(port, interface, x) == -1) {
- return error.ListenError;
- }
- }
-
-
- pub fn sendBody(request: [*c]fio.http_s, body: []const u8) HttpError!void {
- const ret = fio.http_send_body(request, @as(
- *anyopaque,
- @ptrFromInt(@intFromPtr(body.ptr)),
- ), body.len);
- debug("sendBody(): ret = {}\n", .{ret});
- if (ret != -1) return error.HttpSendBody;
- }
-};
-
-
-
\ No newline at end of file
diff --git a/docs/ziglexer.js b/docs/ziglexer.js
deleted file mode 100644
index fdd94be..0000000
--- a/docs/ziglexer.js
+++ /dev/null
@@ -1,2147 +0,0 @@
-'use strict';
-
-const Tag = {
- whitespace: "whitespace",
- invalid: "invalid",
- identifier: "identifier",
- string_literal: "string_literal",
- multiline_string_literal_line: "multiline_string_literal_line",
- char_literal: "char_literal",
- eof: "eof",
- builtin: "builtin",
- number_literal: "number_literal",
- doc_comment: "doc_comment",
- container_doc_comment: "container_doc_comment",
- line_comment: "line_comment",
- invalid_periodasterisks: "invalid_periodasterisks",
- bang: "bang",
- pipe: "pipe",
- pipe_pipe: "pipe_pipe",
- pipe_equal: "pipe_equal",
- equal: "equal",
- equal_equal: "equal_equal",
- equal_angle_bracket_right: "equal_angle_bracket_right",
- bang_equal: "bang_equal",
- l_paren: "l_paren",
- r_paren: "r_paren",
- semicolon: "semicolon",
- percent: "percent",
- percent_equal: "percent_equal",
- l_brace: "l_brace",
- r_brace: "r_brace",
- l_bracket: "l_bracket",
- r_bracket: "r_bracket",
- period: "period",
- period_asterisk: "period_asterisk",
- ellipsis2: "ellipsis2",
- ellipsis3: "ellipsis3",
- caret: "caret",
- caret_equal: "caret_equal",
- plus: "plus",
- plus_plus: "plus_plus",
- plus_equal: "plus_equal",
- plus_percent: "plus_percent",
- plus_percent_equal: "plus_percent_equal",
- plus_pipe: "plus_pipe",
- plus_pipe_equal: "plus_pipe_equal",
- minus: "minus",
- minus_equal: "minus_equal",
- minus_percent: "minus_percent",
- minus_percent_equal: "minus_percent_equal",
- minus_pipe: "minus_pipe",
- minus_pipe_equal: "minus_pipe_equal",
- asterisk: "asterisk",
- asterisk_equal: "asterisk_equal",
- asterisk_asterisk: "asterisk_asterisk",
- asterisk_percent: "asterisk_percent",
- asterisk_percent_equal: "asterisk_percent_equal",
- asterisk_pipe: "asterisk_pipe",
- asterisk_pipe_equal: "asterisk_pipe_equal",
- arrow: "arrow",
- colon: "colon",
- slash: "slash",
- slash_equal: "slash_equal",
- comma: "comma",
- ampersand: "ampersand",
- ampersand_equal: "ampersand_equal",
- question_mark: "question_mark",
- angle_bracket_left: "angle_bracket_left",
- angle_bracket_left_equal: "angle_bracket_left_equal",
- angle_bracket_angle_bracket_left: "angle_bracket_angle_bracket_left",
- angle_bracket_angle_bracket_left_equal: "angle_bracket_angle_bracket_left_equal",
- angle_bracket_angle_bracket_left_pipe: "angle_bracket_angle_bracket_left_pipe",
- angle_bracket_angle_bracket_left_pipe_equal: "angle_bracket_angle_bracket_left_pipe_equal",
- angle_bracket_right: "angle_bracket_right",
- angle_bracket_right_equal: "angle_bracket_right_equal",
- angle_bracket_angle_bracket_right: "angle_bracket_angle_bracket_right",
- angle_bracket_angle_bracket_right_equal: "angle_bracket_angle_bracket_right_equal",
- tilde: "tilde",
- keyword_addrspace: "keyword_addrspace",
- keyword_align: "keyword_align",
- keyword_allowzero: "keyword_allowzero",
- keyword_and: "keyword_and",
- keyword_anyframe: "keyword_anyframe",
- keyword_anytype: "keyword_anytype",
- keyword_asm: "keyword_asm",
- keyword_async: "keyword_async",
- keyword_await: "keyword_await",
- keyword_break: "keyword_break",
- keyword_callconv: "keyword_callconv",
- keyword_catch: "keyword_catch",
- keyword_comptime: "keyword_comptime",
- keyword_const: "keyword_const",
- keyword_continue: "keyword_continue",
- keyword_defer: "keyword_defer",
- keyword_else: "keyword_else",
- keyword_enum: "keyword_enum",
- keyword_errdefer: "keyword_errdefer",
- keyword_error: "keyword_error",
- keyword_export: "keyword_export",
- keyword_extern: "keyword_extern",
- keyword_fn: "keyword_fn",
- keyword_for: "keyword_for",
- keyword_if: "keyword_if",
- keyword_inline: "keyword_inline",
- keyword_noalias: "keyword_noalias",
- keyword_noinline: "keyword_noinline",
- keyword_nosuspend: "keyword_nosuspend",
- keyword_opaque: "keyword_opaque",
- keyword_or: "keyword_or",
- keyword_orelse: "keyword_orelse",
- keyword_packed: "keyword_packed",
- keyword_pub: "keyword_pub",
- keyword_resume: "keyword_resume",
- keyword_return: "keyword_return",
- keyword_linksection: "keyword_linksection",
- keyword_struct: "keyword_struct",
- keyword_suspend: "keyword_suspend",
- keyword_switch: "keyword_switch",
- keyword_test: "keyword_test",
- keyword_threadlocal: "keyword_threadlocal",
- keyword_try: "keyword_try",
- keyword_union: "keyword_union",
- keyword_unreachable: "keyword_unreachable",
- keyword_usingnamespace: "keyword_usingnamespace",
- keyword_var: "keyword_var",
- keyword_volatile: "keyword_volatile",
- keyword_while: "keyword_while"
-}
-
-const Tok = {
- const: { src: "const", tag: Tag.keyword_const },
- var: { src: "var", tag: Tag.keyword_var },
- colon: { src: ":", tag: Tag.colon },
- eql: { src: "=", tag: Tag.equals },
- space: { src: " ", tag: Tag.whitespace },
- tab: { src: " ", tag: Tag.whitespace },
- enter: { src: "\n", tag: Tag.whitespace },
- semi: { src: ";", tag: Tag.semicolon },
- l_bracket: { src: "[", tag: Tag.l_bracket },
- r_bracket: { src: "]", tag: Tag.r_bracket },
- l_brace: { src: "{", tag: Tag.l_brace },
- r_brace: { src: "}", tag: Tag.r_brace },
- l_paren: { src: "(", tag: Tag.l_paren },
- r_paren: { src: ")", tag: Tag.r_paren },
- period: { src: ".", tag: Tag.period },
- comma: { src: ",", tag: Tag.comma },
- question_mark: { src: "?", tag: Tag.question_mark },
- asterisk: { src: "*", tag: Tag.asterisk },
- identifier: (name) => { return { src: name, tag: Tag.identifier } },
-};
-
-
-const State = {
- start: 0,
- identifier: 1,
- builtin: 2,
- string_literal: 3,
- string_literal_backslash: 4,
- multiline_string_literal_line: 5,
- char_literal: 6,
- char_literal_backslash: 7,
- char_literal_hex_escape: 8,
- char_literal_unicode_escape_saw_u: 9,
- char_literal_unicode_escape: 10,
- char_literal_unicode_invalid: 11,
- char_literal_unicode: 12,
- char_literal_end: 13,
- backslash: 14,
- equal: 15,
- bang: 16,
- pipe: 17,
- minus: 18,
- minus_percent: 19,
- minus_pipe: 20,
- asterisk: 21,
- asterisk_percent: 22,
- asterisk_pipe: 23,
- slash: 24,
- line_comment_start: 25,
- line_comment: 26,
- doc_comment_start: 27,
- doc_comment: 28,
- int: 29,
- int_exponent: 30,
- int_period: 31,
- float: 32,
- float_exponent: 33,
- ampersand: 34,
- caret: 35,
- percent: 36,
- plus: 37,
- plus_percent: 38,
- plus_pipe: 39,
- angle_bracket_left: 40,
- angle_bracket_angle_bracket_left: 41,
- angle_bracket_angle_bracket_left_pipe: 42,
- angle_bracket_right: 43,
- angle_bracket_angle_bracket_right: 44,
- period: 45,
- period_2: 46,
- period_asterisk: 47,
- saw_at_sign: 48,
- whitespace: 49,
-}
-
-const keywords = {
- "addrspace": Tag.keyword_addrspace,
- "align": Tag.keyword_align,
- "allowzero": Tag.keyword_allowzero,
- "and": Tag.keyword_and,
- "anyframe": Tag.keyword_anyframe,
- "anytype": Tag.keyword_anytype,
- "asm": Tag.keyword_asm,
- "async": Tag.keyword_async,
- "await": Tag.keyword_await,
- "break": Tag.keyword_break,
- "callconv": Tag.keyword_callconv,
- "catch": Tag.keyword_catch,
- "comptime": Tag.keyword_comptime,
- "const": Tag.keyword_const,
- "continue": Tag.keyword_continue,
- "defer": Tag.keyword_defer,
- "else": Tag.keyword_else,
- "enum": Tag.keyword_enum,
- "errdefer": Tag.keyword_errdefer,
- "error": Tag.keyword_error,
- "export": Tag.keyword_export,
- "extern": Tag.keyword_extern,
- "fn": Tag.keyword_fn,
- "for": Tag.keyword_for,
- "if": Tag.keyword_if,
- "inline": Tag.keyword_inline,
- "noalias": Tag.keyword_noalias,
- "noinline": Tag.keyword_noinline,
- "nosuspend": Tag.keyword_nosuspend,
- "opaque": Tag.keyword_opaque,
- "or": Tag.keyword_or,
- "orelse": Tag.keyword_orelse,
- "packed": Tag.keyword_packed,
- "pub": Tag.keyword_pub,
- "resume": Tag.keyword_resume,
- "return": Tag.keyword_return,
- "linksection": Tag.keyword_linksection,
- "struct": Tag.keyword_struct,
- "suspend": Tag.keyword_suspend,
- "switch": Tag.keyword_switch,
- "test": Tag.keyword_test,
- "threadlocal": Tag.keyword_threadlocal,
- "try": Tag.keyword_try,
- "union": Tag.keyword_union,
- "unreachable": Tag.keyword_unreachable,
- "usingnamespace": Tag.keyword_usingnamespace,
- "var": Tag.keyword_var,
- "volatile": Tag.keyword_volatile,
- "while": Tag.keyword_while,
-};
-
-function make_token(tag, start, end) {
- return {
- tag: tag,
- loc: {
- start: start,
- end: end
- }
- }
-
-}
-
-function dump_tokens(tokens, raw_source) {
-
- //TODO: this is not very fast
- function find_tag_key(tag) {
- for (const [key, value] of Object.entries(Tag)) {
- if (value == tag) return key;
- }
- }
-
- for (let i = 0; i < tokens.length; i++) {
- const tok = tokens[i];
- const z = raw_source.substring(tok.loc.start, tok.loc.end).toLowerCase();
- console.log(`${find_tag_key(tok.tag)} "${tok.tag}" '${z}'`)
- }
-}
-
-function* Tokenizer(raw_source) {
- let tokenizer = new InnerTokenizer(raw_source);
- while (true) {
- let t = tokenizer.next();
- if (t.tag == Tag.eof)
- return;
-
- t.src = raw_source.slice(t.loc.start, t.loc.end);
-
- yield t;
- }
-
-}
-function InnerTokenizer(raw_source) {
- this.index = 0;
- this.flag = false;
-
- this.seen_escape_digits = undefined;
- this.remaining_code_units = undefined;
-
- this.next = () => {
- let state = State.start;
-
- var result = {
- tag: -1,
- loc: {
- start: this.index,
- end: undefined,
- },
- src: undefined,
- };
-
- //having a while (true) loop seems like a bad idea the loop should never
- //take more iterations than twice the length of the source code
- const MAX_ITERATIONS = raw_source.length * 2;
- let iterations = 0;
-
- while (iterations <= MAX_ITERATIONS) {
-
- if (this.flag) {
- return make_token(Tag.eof, this.index - 2, this.index - 2);
- }
- iterations += 1; // avoid death loops
-
- var c = raw_source[this.index];
-
- if (c === undefined) {
- c = ' '; // push the last token
- this.flag = true;
- }
-
- switch (state) {
- case State.start:
- switch (c) {
- case 0: {
- if (this.index != raw_source.length) {
- result.tag = Tag.invalid;
- result.loc.start = this.index;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- result.loc.end = this.index;
- return result;
- }
- case ' ':
- case '\n':
- case '\t':
- case '\r': {
- state = State.whitespace;
- result.tag = Tag.whitespace;
- result.loc.start = this.index;
- break;
- }
- case '"': {
- state = State.string_literal;
- result.tag = Tag.string_literal;
- break;
- }
- case '\'': {
- state = State.char_literal;
- break;
- }
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_': {
- state = State.identifier;
- result.tag = Tag.identifier;
- break;
- }
- case '@': {
- state = State.saw_at_sign;
- break;
- }
- case '=': {
- state = State.equal;
- break;
- }
- case '!': {
- state = State.bang;
- break;
- }
- case '|': {
- state = State.pipe;
- break;
- }
- case '(': {
- result.tag = Tag.l_paren;
- this.index += 1;
- result.loc.end = this.index;
-
- return result;
-
- }
- case ')': {
- result.tag = Tag.r_paren;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case '[': {
- result.tag = Tag.l_bracket;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case ']': {
- result.tag = Tag.r_bracket;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case ';': {
- result.tag = Tag.semicolon;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case ',': {
- result.tag = Tag.comma;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case '?': {
- result.tag = Tag.question_mark;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case ':': {
- result.tag = Tag.colon;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case '%': {
- state = State.percent; break;
- }
- case '*': {
- state = State.asterisk; break;
- }
- case '+': {
- state = State.plus; break;
- }
- case '<': {
- state = State.angle_bracket_left; break;
- }
- case '>': {
- state = State.angle_bracket_right; break;
- }
- case '^': {
- state = State.caret; break;
- }
- case '\\': {
- state = State.backslash;
- result.tag = Tag.multiline_string_literal_line; break;
- }
- case '{': {
- result.tag = Tag.l_brace;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case '}': {
- result.tag = Tag.r_brace;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case '~': {
- result.tag = Tag.tilde;
- this.index += 1; result.loc.end = this.index;
- return result;
-
- }
- case '.': {
- state = State.period; break;
- }
- case '-': {
- state = State.minus; break;
- }
- case '/': {
- state = State.slash; break;
- }
- case '&': {
- state = State.ampersand; break;
- }
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- state = State.int;
- result.tag = Tag.number_literal; break;
- }
- default: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- this.index += 1;
- return result;
- }
- }
- break;
- case State.saw_at_sign:
- switch (c) {
- case '"': {
- result.tag = Tag.identifier;
- state = State.string_literal; break;
- }
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_': {
- state = State.builtin;
- result.tag = Tag.builtin;
- break;
- }
- default: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.ampersand:
- switch (c) {
- case '=': {
- result.tag = Tag.ampersand_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.ampersand; result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.asterisk: switch (c) {
- case '=': {
- result.tag = Tag.asterisk_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- case '*': {
- result.tag = Tag.asterisk_asterisk;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- case '%': {
- state = State.asterisk_percent; break;
- }
- case '|': {
- state = State.asterisk_pipe; break;
- }
- default: {
- result.tag = Tag.asterisk;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.asterisk_percent:
- switch (c) {
- case '=': {
- result.tag = Tag.asterisk_percent_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.asterisk_percent;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.asterisk_pipe:
- switch (c) {
- case '=': {
- result.tag = Tag.asterisk_pipe_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.asterisk_pipe; result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.percent:
- switch (c) {
- case '=': {
- result.tag = Tag.percent_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.percent; result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.plus:
- switch (c) {
- case '=': {
- result.tag = Tag.plus_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- case '+': {
- result.tag = Tag.plus_plus;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- case '%': {
- state = State.plus_percent; break;
- }
- case '|': {
- state = State.plus_pipe; break;
- }
- default: {
- result.tag = Tag.plus; result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.plus_percent:
- switch (c) {
- case '=': {
- result.tag = Tag.plus_percent_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.plus_percent; result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.plus_pipe:
- switch (c) {
- case '=': {
- result.tag = Tag.plus_pipe_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.plus_pipe; result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.caret:
- switch (c) {
- case '=': {
- result.tag = Tag.caret_equal;
- this.index += 1; result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.caret; result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.identifier:
- switch (c) {
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': break;
- default: {
- // if (Token.getKeyword(buffer[result.loc.start..this.index])) | tag | {
- const z = raw_source.substring(result.loc.start, this.index);
- if (z in keywords) {
- result.tag = keywords[z];
- }
- result.loc.end = this.index;
- return result;
- }
-
-
- }
- break;
- case State.builtin: switch (c) {
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': break;
- default: result.loc.end = this.index;
- return result;
- }
- break;
- case State.backslash:
- switch (c) {
- case '\\': {
- state = State.multiline_string_literal_line;
- break;
- }
- default: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.string_literal:
- switch (c) {
- case '\\': {
- state = State.string_literal_backslash; break;
- }
- case '"': {
- this.index += 1;
- result.loc.end = this.index;
-
- return result;
- }
- case 0: {
- //TODO: PORT
- // if (this.index == buffer.len) {
- // result.tag = .invalid;
- // break;
- // } else {
- // checkLiteralCharacter();
- // }
- result.loc.end = this.index;
- return result;
- }
- case '\n': {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- //TODO: PORT
- //default: checkLiteralCharacter(),
- }
- break;
- case State.string_literal_backslash:
- switch (c) {
- case 0:
- case '\n': {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- default: {
- state = State.string_literal; break;
- }
- }
- break;
- case State.char_literal: switch (c) {
- case 0: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- case '\\': {
- state = State.char_literal_backslash;
- break;
- }
- //TODO: PORT
- // '\'', 0x80...0xbf, 0xf8...0xff => {
- // result.tag = .invalid;
- // break;
- // },
- // 0xc0...0xdf => { // 110xxxxx
- // this.remaining_code_units = 1;
- // state = .char_literal_unicode;
- // },
- // 0xe0...0xef => { // 1110xxxx
- // this.remaining_code_units = 2;
- // state = .char_literal_unicode;
- // },
- // 0xf0...0xf7 => { // 11110xxx
- // this.remaining_code_units = 3;
- // state = .char_literal_unicode;
- // },
-
- // case 0x80:
- // case 0x81:
- // case 0x82:
- // case 0x83:
- // case 0x84:
- // case 0x85:
- // case 0x86:
- // case 0x87:
- // case 0x88:
- // case 0x89:
- // case 0x8a:
- // case 0x8b:
- // case 0x8c:
- // case 0x8d:
- // case 0x8e:
- // case 0x8f:
- // case 0x90:
- // case 0x91:
- // case 0x92:
- // case 0x93:
- // case 0x94:
- // case 0x95:
- // case 0x96:
- // case 0x97:
- // case 0x98:
- // case 0x99:
- // case 0x9a:
- // case 0x9b:
- // case 0x9c:
- // case 0x9d:
- // case 0x9e:
- // case 0x9f:
- // case 0xa0:
- // case 0xa1:
- // case 0xa2:
- // case 0xa3:
- // case 0xa4:
- // case 0xa5:
- // case 0xa6:
- // case 0xa7:
- // case 0xa8:
- // case 0xa9:
- // case 0xaa:
- // case 0xab:
- // case 0xac:
- // case 0xad:
- // case 0xae:
- // case 0xaf:
- // case 0xb0:
- // case 0xb1:
- // case 0xb2:
- // case 0xb3:
- // case 0xb4:
- // case 0xb5:
- // case 0xb6:
- // case 0xb7:
- // case 0xb8:
- // case 0xb9:
- // case 0xba:
- // case 0xbb:
- // case 0xbc:
- // case 0xbd:
- // case 0xbe:
- // case 0xbf:
- // case 0xf8:
- // case 0xf9:
- // case 0xfa:
- // case 0xfb:
- // case 0xfc:
- // case 0xfd:
- // case 0xfe:
- // case 0xff:
- // result.tag = .invalid;
- // break;
- // case 0xc0:
- // case 0xc1:
- // case 0xc2:
- // case 0xc3:
- // case 0xc4:
- // case 0xc5:
- // case 0xc6:
- // case 0xc7:
- // case 0xc8:
- // case 0xc9:
- // case 0xca:
- // case 0xcb:
- // case 0xcc:
- // case 0xcd:
- // case 0xce:
- // case 0xcf:
- // case 0xd0:
- // case 0xd1:
- // case 0xd2:
- // case 0xd3:
- // case 0xd4:
- // case 0xd5:
- // case 0xd6:
- // case 0xd7:
- // case 0xd8:
- // case 0xd9:
- // case 0xda:
- // case 0xdb:
- // case 0xdc:
- // case 0xdd:
- // case 0xde:
- // case 0xdf:
- // this.remaining_code_units = 1;
- // state = .char_literal_unicode;
- // case 0xe0:
- // case 0xe1:
- // case 0xe2:
- // case 0xe3:
- // case 0xe4:
- // case 0xe5:
- // case 0xe6:
- // case 0xe7:
- // case 0xe8:
- // case 0xe9:
- // case 0xea:
- // case 0xeb:
- // case 0xec:
- // case 0xed:
- // case 0xee:
- // case 0xef:
- // this.remaining_code_units = 2;
- // state = .char_literal_unicode;
- // case 0xf0:
- // case 0xf1:
- // case 0xf2:
- // case 0xf3:
- // case 0xf4:
- // case 0xf5:
- // case 0xf6:
- // case 0xf7:
- // this.remaining_code_units = 3;
- // state = .char_literal_unicode;
-
- case '\n': {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- default: {
- state = State.char_literal_end; break;
- }
- }
- break;
- case State.char_literal_backslash:
- switch (c) {
- case 0:
- case '\n': {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- case 'x': {
- state = State.char_literal_hex_escape;
- this.seen_escape_digits = 0; break;
- }
- case 'u': {
- state = State.char_literal_unicode_escape_saw_u; break;
- }
- default: {
- state = State.char_literal_end; break;
- }
- }
- break;
- case State.char_literal_hex_escape:
- switch (c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F': {
- this.seen_escape_digits += 1;
- if (this.seen_escape_digits == 2) {
- state = State.char_literal_end;
- } break;
- }
- default: {
- result.tag = Tag.invalid;
- esult.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.char_literal_unicode_escape_saw_u:
- switch (c) {
- case 0: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- case '{': {
- state = State.char_literal_unicode_escape; break;
- }
- default: {
- result.tag = Tag.invalid;
- state = State.char_literal_unicode_invalid; break;
- }
- }
- break;
- case State.char_literal_unicode_escape:
- switch (c) {
- case 0: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F': break;
- case '}': {
- state = State.char_literal_end; // too many/few digits handled later
- break;
- }
- default: {
- result.tag = Tag.invalid;
- state = State.char_literal_unicode_invalid; break;
- }
- }
- break;
- case State.char_literal_unicode_invalid:
- switch (c) {
- // Keep consuming characters until an obvious stopping point.
- // This consolidates e.g. `u{0ab1Q}` into a single invalid token
- // instead of creating the tokens `u{0ab1`, `Q`, `}`
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '}':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': break;
- default: break;
- }
- break;
- case State.char_literal_end:
- switch (c) {
- case '\'': {
- result.tag = Tag.char_literal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.char_literal_unicode:
- switch (c) {
- // 0x80...0xbf => {
- // this.remaining_code_units -= 1;
- // if (this.remaining_code_units == 0) {
- // state = .char_literal_end;
- // }
- // },
- default: {
- result.tag = Tag.invalid;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.multiline_string_literal_line:
- switch (c) {
- case 0:
- result.loc.end = this.index;
- return result;
- case '\n': {
-
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- case '\t': break;
- //TODO: PORT
- //default: checkLiteralCharacter(),
-
- }
- break;
- case State.bang:
- switch (c) {
- case '=': {
- result.tag = Tag.bang_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.bang;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.pipe:
- switch (c) {
- case '=': {
- result.tag = Tag.pipe_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- case '|': {
- result.tag = Tag.pipe_pipe;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.pipe;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.equal: switch (c) {
- case '=': {
- result.tag = Tag.equal_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- case '>': {
- result.tag = Tag.equal_angle_bracket_right;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.equal;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.minus: switch (c) {
- case '>': {
- result.tag = Tag.arrow;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- case '=': {
- result.tag = Tag.minus_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- case '%': {
- state = State.minus_percent; break;
- }
- case '|': {
- state = State.minus_pipe; break;
- }
- default: {
- result.tag = Tag.minus;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.minus_percent:
- switch (c) {
- case '=': {
- result.tag = Tag.minus_percent_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.minus_percent;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.minus_pipe:
- switch (c) {
- case '=': {
- result.tag = Tag.minus_pipe_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.minus_pipe;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.angle_bracket_left:
- switch (c) {
- case '<': {
- state = State.angle_bracket_angle_bracket_left; break;
- }
- case '=': {
- result.tag = Tag.angle_bracket_left_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.angle_bracket_left;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.angle_bracket_angle_bracket_left:
- switch (c) {
- case '=': {
- result.tag = Tag.angle_bracket_angle_bracket_left_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- case '|': {
- state = State.angle_bracket_angle_bracket_left_pipe;
- }
- default: {
- result.tag = Tag.angle_bracket_angle_bracket_left;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.angle_bracket_angle_bracket_left_pipe:
- switch (c) {
- case '=': {
- result.tag = Tag.angle_bracket_angle_bracket_left_pipe_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.angle_bracket_angle_bracket_left_pipe;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.angle_bracket_right:
- switch (c) {
- case '>': {
- state = State.angle_bracket_angle_bracket_right; break;
- }
- case '=': {
- result.tag = Tag.angle_bracket_right_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.angle_bracket_right;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.angle_bracket_angle_bracket_right:
- switch (c) {
- case '=': {
- result.tag = Tag.angle_bracket_angle_bracket_right_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.angle_bracket_angle_bracket_right;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.period:
- switch (c) {
- case '.': {
- state = State.period_2; break;
- }
- case '*': {
- state = State.period_asterisk; break;
- }
- default: {
- result.tag = Tag.period;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.period_2:
- switch (c) {
- case '.': {
- result.tag = Tag.ellipsis3;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.ellipsis2;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.period_asterisk:
- switch (c) {
- case '*': {
- result.tag = Tag.invalid_periodasterisks;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.period_asterisk;
- result.loc.end = this.index;
- return result;
- }
- }
- break;
- case State.slash:
- switch (c) {
- case '/': {
- state = State.line_comment_start;
- break;
- }
- case '=': {
- result.tag = Tag.slash_equal;
- this.index += 1;
- result.loc.end = this.index;
- return result;
- }
- default: {
- result.tag = Tag.slash;
- result.loc.end = this.index;
- return result;
- }
- } break;
- case State.line_comment_start:
- switch (c) {
- case 0: {
- if (this.index != raw_source.length) {
- result.tag = Tag.invalid;
- this.index += 1;
- }
- result.loc.end = this.index;
- return result;
- }
- case '/': {
- state = State.doc_comment_start; break;
- }
- case '!': {
- result.tag = Tag.container_doc_comment;
- state = State.doc_comment; break;
- }
- case '\n': {
- state = State.start;
- result.loc.start = this.index + 1; break;
- }
- case '\t':
- state = State.line_comment; break;
- default: {
- state = State.line_comment;
- //TODO: PORT
- //checkLiteralCharacter();
- break;
- }
- } break;
- case State.doc_comment_start:
- switch (c) {
- case '/': {
- state = State.line_comment; break;
- }
- case 0:
- case '\n':
- {
- result.tag = Tag.doc_comment;
- result.loc.end = this.index;
- return result;
- }
- case '\t': {
- state = State.doc_comment;
- result.tag = Tag.doc_comment; break;
- }
- default: {
- state = State.doc_comment;
- result.tag = Tag.doc_comment;
- //TODO: PORT
- //checkLiteralCharacter();
- break;
- }
- } break;
- case State.line_comment:
- switch (c) {
- case 0: {
- if (this.index != raw_source.length) {
- result.tag = Tag.invalid;
- this.index += 1;
- }
- result.loc.end = this.index;
- return result;
- }
- case '\n': {
- result.tag = Tag.line_comment;
- result.loc.end = this.index;
- return result;
- }
- case '\t': break;
- //TODO: PORT
- //default: checkLiteralCharacter(),
- } break;
- case State.doc_comment:
- switch (c) {
- case 0://
- case '\n':
- result.loc.end = this.index;
- return result;
- case '\t': break;
- //TODOL PORT
- // default: checkLiteralCharacter(),
- default:
- break;
- } break;
- case State.int:
- switch (c) {
- case '.':
- state = State.int_period;
- break;
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break;
- case 'e':
- case 'E':
- case 'p':
- case 'P':
- state = State.int_exponent;
- break;
- default: result.loc.end = this.index;
- return result;
- } break;
- case State.int_exponent:
- switch (c) {
- case '-':
- case '+':
- {
- ``
- state = State.float; break;
- }
- default: {
- this.index -= 1;
- state = State.int; break;
- }
- } break;
- case State.int_period: switch (c) {
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- state = State.float; break;
- }
- case 'e':
- case 'E':
- case 'p':
- case 'P':
- state = State.float_exponent; break;
- default: {
- this.index -= 1;
- result.loc.end = this.index;
- return result;
- }
- } break;
- case State.float:
- switch (c) {
- case '_':
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break;
-
- case 'e':
- case 'E':
- case 'p':
- case 'P':
- state = State.float_exponent; break;
- default: result.loc.end = this.index;
- return result;
- } break;
- case State.float_exponent:
- switch (c) {
- case '-':
- case '+':
- state = State.float; break;
- default: {
- this.index -= 1;
- state = State.float; break;
- }
- }
- break;
-
- case State.whitespace:
- switch(c) {
- case ' ':
- case '\n':
- case '\t':
- case '\r': {
- break;
- }
- default: {
- result.loc.end = this.index;
- return result;
- }
- }
- }
- this.index += 1;
- }
-
- //TODO: PORT
- // if (result.tag == Tag.eof) {
- // if (pending_invalid_token) | token | {
- // pending_invalid_token = null;
- // return token;
- // }
- // result.loc.start = sindex;
- // }
-
- result.loc.end = this.index;
- return result;
-
- }
-}
-
-
-const builtin_types = [
- "f16", "f32", "f64", "f80", "f128",
- "c_longdouble", "c_short", "c_ushort", "c_int", "c_uint",
- "c_long", "c_ulong", "c_longlong", "c_ulonglong", "c_char",
- "anyopaque", "void", "bool", "isize", "usize",
- "noreturn", "type", "anyerror", "comptime_int", "comptime_float",
-];
-
-function isSimpleType(typeName) {
- return builtin_types.includes(typeName) || isIntType(typeName);
-}
-
-function isIntType(typeName) {
- if (typeName[0] != 'u' && typeName[0] != 'i') return false;
- let i = 1;
- if (i == typeName.length) return false;
- for (; i < typeName.length; i += 1) {
- if (typeName[i] < '0' || typeName[i] > '9') return false;
- }
- return true;
-}
-
-function isSpecialIndentifier(identifier) {
- return ["null", "true", "false", ,"undefined"].includes(identifier);
-}
-
-//const fs = require('fs');
-//const src = fs.readFileSync("../std/c.zig", 'utf8');
-//console.log(generate_html_for_src(src));
-
-
-// gist for zig_lexer_test code: https://gist.github.com/Myvar/2684ba4fb86b975274629d6f21eddc7b
-// // Just for testing not to commit in pr
-// var isNode = new Function("try {return this===global;}catch(e){return false;}");
-// if (isNode()) {
-
-
-// //const s = "const std = @import(\"std\");";
-// //const toksa = tokenize_zig_source(s);
-// //dump_tokens(toksa, s);
-// //console.log(JSON.stringify(toksa));
-
-// const fs = require('fs');
-
-// function testFile(fileName) {
-// //console.log(fileName);
-// var exec = require('child_process').execFileSync;
-// var passed = true;
-// const zig_data = exec('./zig_lexer_test', [fileName]);
-// const data = fs.readFileSync(fileName, 'utf8');
-
-// const toks = tokenize_zig_source(data);
-// const a_json = toks;
-
-// // dump_tokens(a_json, data);
-// // return;
-
-// const b_json = JSON.parse(zig_data.toString());
-
-// if (a_json.length !== b_json.length) {
-// console.log("FAILED a and be is not the same length");
-// passed = false;
-// //return;
-// }
-
-// let len = a_json.length;
-// if (len >= b_json.length) len = b_json.length;
-
-// for (let i = 0; i < len; i++) {
-// const a = a_json[i];
-// const b = b_json[i];
-
-// // console.log(a.tag + " == " + b.tag);
-
-// if (a.tag !== b.tag) {
-
-// // console.log("Around here:");
-// // console.log(
-// // data.substring(b_json[i - 2].loc.start, b_json[i - 2].loc.end),
-// // data.substring(b_json[i - 1].loc.start, b_json[i - 1].loc.end),
-// // data.substring(b_json[i].loc.start, b_json[i].loc.end),
-// // data.substring(b_json[i + 1].loc.start, b_json[i + 1].loc.end),
-// // data.substring(b_json[i + 2].loc.start, b_json[i + 2].loc.end),
-// // );
-
-// console.log("TAG: a != b");
-// console.log("js", a.tag);
-// console.log("zig", b.tag);
-// passed = false;
-// return;
-// }
-
-// if (a.tag !== Tag.eof && a.loc.start !== b.loc.start) {
-// console.log("START: a != b");
-
-// console.log("js", "\"" + data.substring(a_json[i ].loc.start, a_json[i].loc.end) + "\"");
-// console.log("zig", "\"" + data.substring(b_json[i ].loc.start, b_json[i].loc.end) + "\"");
-
-
-// passed = false;
-// return;
-// }
-
-// // if (a.tag !== Tag.eof && a.loc.end !== b.loc.end) {
-// // console.log("END: a != b");
-// // // console.log("Around here:");
-// // // console.log(
-// // // // data.substring(b_json[i - 2].loc.start, b_json[i - 2].loc.end),
-// // // // data.substring(b_json[i - 1].loc.start, b_json[i - 1].loc.end),
-// // // data.substring(b_json[i ].loc.start, b_json[i].loc.end),
-// // // // data.substring(b_json[i + 1].loc.start, b_json[i + 1].loc.end),
-// // // // data.substring(b_json[i + 2].loc.start, b_json[i + 2].loc.end),
-// // // );
-// // console.log("js", "\"" + data.substring(a_json[i ].loc.start, a_json[i].loc.end) + "\"");
-// // console.log("zig", "\"" + data.substring(b_json[i ].loc.start, b_json[i].loc.end) + "\"");
-// // passed = false;
-// // return;
-// // }
-// }
-// return passed;
-// }
-// var path = require('path');
-// function fromDir(startPath, filter) {
-// if (!fs.existsSync(startPath)) {
-// console.log("no dir ", startPath);
-// return;
-// }
-// var files = fs.readdirSync(startPath);
-// for (var i = 0; i < files.length; i++) {
-// var filename = path.join(startPath, files[i]);
-// var stat = fs.lstatSync(filename);
-// if (stat.isDirectory()) {
-// fromDir(filename, filter); //recurse
-// } else if (filename.endsWith(filter)) {
-// try {
-// console.log('-- TESTING: ', filename);
-// console.log("\t\t", testFile(filename));
-// }
-// catch {
-// }
-// };
-// };
-// };
-// fromDir('../std', '.zig');
-// //console.log(testFile("/home/myvar/code/zig/lib/std/fmt/errol.zig"));
-// //console.log(testFile("test.zig"));
-// }
\ No newline at end of file
diff --git a/examples/endpoint/userweb.zig b/examples/endpoint/userweb.zig
index 495a586..6c6775f 100644
--- a/examples/endpoint/userweb.zig
+++ b/examples/endpoint/userweb.zig
@@ -55,6 +55,7 @@ fn userIdFromPath(self: *Self, path: []const u8) ?usize {
fn getUser(e: *zap.Endpoint, r: zap.Request) void {
const self: *Self = @fieldParentPtr("ep", e);
+
if (r.path) |path| {
// /users
if (path.len == e.settings.path.len) {
diff --git a/examples/https/https.zig b/examples/https/https.zig
index 88c53a7..aeb7930 100644
--- a/examples/https/https.zig
+++ b/examples/https/https.zig
@@ -30,7 +30,7 @@ fn help_and_exit(filename: []const u8, err: anyerror) void {
,
.{ filename, err },
);
- std.os.exit(1);
+ std.process.exit(1);
}
pub fn main() !void {
const CERT_FILE = "mycert.pem";
diff --git a/examples/simple_router/simple_router.zig b/examples/simple_router/simple_router.zig
index acff407..eb58839 100644
--- a/examples/simple_router/simple_router.zig
+++ b/examples/simple_router/simple_router.zig
@@ -82,17 +82,17 @@ pub fn main() !void {
var somePackage = SomePackage.init(allocator, 1, 2);
- try simpleRouter.handle_func("/", on_request_verbose);
+ try simpleRouter.handle_func_unbound("/", on_request_verbose);
- try simpleRouter.handle_func("/geta", zap.RequestHandler(&somePackage, SomePackage.getA));
+ try simpleRouter.handle_func("/geta", &somePackage, &SomePackage.getA);
- try simpleRouter.handle_func("/getb", zap.RequestHandler(&somePackage, SomePackage.getB));
+ try simpleRouter.handle_func("/getb", &somePackage, &SomePackage.getB);
- try simpleRouter.handle_func("/inca", zap.RequestHandler(&somePackage, SomePackage.incrementA));
+ try simpleRouter.handle_func("/inca", &somePackage, &SomePackage.incrementA);
var listener = zap.HttpListener.init(.{
.port = 3000,
- .on_request = zap.RequestHandler(&simpleRouter, &zap.Router.serve),
+ .on_request = simpleRouter.on_request_handler(),
.log = true,
.max_clients = 100000,
});
diff --git a/facil.io/build.zig.zon b/facil.io/build.zig.zon
index 277ebf3..3ed7ce9 100644
--- a/facil.io/build.zig.zon
+++ b/facil.io/build.zig.zon
@@ -2,4 +2,3 @@
.name = "facil.io",
.version = "0.0.12",
}
-
diff --git a/src/middleware.zig b/src/middleware.zig
index 919876d..e9b121e 100644
--- a/src/middleware.zig
+++ b/src/middleware.zig
@@ -82,7 +82,8 @@ pub fn EndpointHandler(comptime HandlerType: anytype, comptime ContextType: anyt
/// If `breakOnFinish` is `true`, the handler will stop handing requests down the chain if
/// the endpoint processed the request.
pub fn onRequest(handler: *HandlerType, r: zap.Request, context: *ContextType) bool {
- var self: *Self = @fieldParentPtr("handler", handler);
+
+ const self: *Self = @fieldParentPtr("handler", handler);
r.setUserContext(context);
self.endpoint.onRequest(r);
diff --git a/src/router.zig b/src/router.zig
index 6b490c3..c9ca7d5 100644
--- a/src/router.zig
+++ b/src/router.zig
@@ -2,6 +2,8 @@ const std = @import("std");
const zap = @import("zap.zig");
const Allocator = std.mem.Allocator;
+
+/// Errors returnable by init()
const RouterError = error{
AlreadyExists,
EmptyPath,
@@ -9,46 +11,101 @@ const RouterError = error{
const Self = @This();
+/// This is a singleton
+var _instance: *Self = undefined;
+
+/// Options to pass to init()
pub const Options = struct {
+ /// an optional zap request function for 404 not found case
not_found: ?zap.HttpRequestFn = null,
};
-routes: std.StringHashMap(zap.HttpRequestFn),
+const CallbackTag = enum { bound, unbound };
+const BoundHandler = *fn (*const anyopaque, zap.Request) void;
+const Callback = union(CallbackTag) {
+ bound: struct { instance: usize, handler: usize },
+ unbound: zap.HttpRequestFn,
+};
+
+routes: std.StringHashMap(Callback),
not_found: ?zap.HttpRequestFn,
+/// Create a new Router
pub fn init(allocator: Allocator, options: Options) Self {
return .{
- .routes = std.StringHashMap(zap.HttpRequestFn).init(allocator),
+ .routes = std.StringHashMap(Callback).init(allocator),
.not_found = options.not_found,
};
}
+/// Deinit the router
pub fn deinit(self: *Self) void {
self.routes.deinit();
}
-pub fn handle_func(self: *Self, path: []const u8, h: zap.HttpRequestFn) !void {
+/// Call this to add a route with an unbound handler: a handler that is not member of a struct.
+pub fn handle_func_unbound(self: *Self, path: []const u8, h: zap.HttpRequestFn) !void {
if (path.len == 0) {
return RouterError.EmptyPath;
}
- const route = self.routes.get(path);
-
- if (route != null) {
+ if (self.routes.contains(path)) {
return RouterError.AlreadyExists;
}
- try self.routes.put(path, h);
+ try self.routes.put(path, Callback{ .unbound = h });
}
-pub fn serve(self: *Self, r: zap.Request) void {
- const path = if (r.path) |p| p else "/";
+/// Call this to add a route with a handler that is bound to an instance of a struct.
+/// Example:
+///
+/// ```zig
+/// const HandlerType = struct {
+/// pub fn getA(self: *HandlerType, r: zap.Request) void {
+/// _ = self;
+/// r.sendBody("hello\n\n") catch return;
+/// }
+/// }
+/// var handler_instance = HandlerType{};
+///
+/// my_router.handle_func("/getA", &handler_instance, HandlerType.getA);
+/// ```
+pub fn handle_func(self: *Self, path: []const u8, instance: *anyopaque, handler: anytype) !void {
+ // TODO: assert type of instance has handler
- const route = self.routes.get(path);
+ if (path.len == 0) {
+ return RouterError.EmptyPath;
+ }
- if (route) |handler| {
- handler(r);
+ if (self.routes.contains(path)) {
+ return RouterError.AlreadyExists;
+ }
+
+ try self.routes.put(path, Callback{ .bound = .{
+ .instance = @intFromPtr(instance),
+ .handler = @intFromPtr(handler),
+ } });
+}
+
+/// Get the zap request handler function needed for a listener
+pub fn on_request_handler(self: *Self) zap.HttpRequestFn {
+ _instance = self;
+ return zap_on_request;
+}
+
+fn zap_on_request(r: zap.Request) void {
+ return serve(_instance, r);
+}
+
+fn serve(self: *Self, r: zap.Request) void {
+ const path = r.path orelse "/";
+
+ if (self.routes.get(path)) |routeInfo| {
+ switch (routeInfo) {
+ .bound => |b| @call(.auto, @as(BoundHandler, @ptrFromInt(b.handler)), .{ @as(*anyopaque, @ptrFromInt(b.instance)), r }),
+ .unbound => |h| h(r),
+ }
} else if (self.not_found) |handler| {
// not found handler
handler(r);
diff --git a/src/util.zig b/src/util.zig
index 21e9eaf..4b6a4c9 100644
--- a/src/util.zig
+++ b/src/util.zig
@@ -2,23 +2,6 @@ const std = @import("std");
const fio = @import("fio.zig");
const zap = @import("zap.zig");
-/// capture self for RequestFn signature support
-pub inline fn RequestHandler(self: anytype, func: *const fn (@TypeOf(self), zap.Request) void) *const fn (zap.Request) void {
- return (opaque {
- var hidden_self: @TypeOf(self) = undefined;
- var hidden_func: *const fn (@TypeOf(self), zap.Request) void = undefined;
- pub fn init(h_self: @TypeOf(self), h_func: *const fn (@TypeOf(self), zap.Request) void) *const @TypeOf(run) {
- hidden_self = h_self;
- hidden_func = h_func;
- return &run;
- }
-
- fn run(req: zap.Request) void {
- hidden_func(hidden_self, req);
- }
- }).init(self, func);
-}
-
/// Used internally: convert a FIO object into its string representation.
/// note: since this is called from within request functions, we don't make
/// copies. Also, we return temp memory from fio. -> don't hold on to it outside
diff --git a/src/zap.zig b/src/zap.zig
index 0414d68..b8ab289 100644
--- a/src/zap.zig
+++ b/src/zap.zig
@@ -43,7 +43,7 @@ pub const Tls = @import("tls.zig");
/// }
///
/// fn get(e: *zap.Endpoint, r: zap.Request) void {
-/// const self: *StopEndpoint = @fieldParentPtr(StopEndpoint, "ep", e);
+/// const self: *StopEndpoint = @fieldParentPtr("ep", e);
/// _ = self;
/// _ = r;
/// zap.stop();
diff --git a/tools/announceybot.zig b/tools/announceybot.zig
index 08f517c..3a88deb 100644
--- a/tools/announceybot.zig
+++ b/tools/announceybot.zig
@@ -28,7 +28,8 @@ fn usage() void {
\\ instructions
;
std.debug.print("{s}", .{message});
- std.posix.exit(1);
+
+ std.process.exit(1);
}
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
@@ -338,7 +339,7 @@ fn command_announce(allocator: std.mem.Allocator, tag: []const u8) !void {
defer allocator.free(url);
sendToDiscord(allocator, url, announcement) catch |err| {
std.debug.print("HTTP ERROR: {any}\n", .{err});
- std.posix.exit(1);
+ std.process.exit(1);
};
}