API Reference
Every entry is a Wyn-callable function written as Namespace.method(args) -> ReturnType. Call them with dot syntax, e.g. Crypto.sha256("hello").
221 callable functions across 29 modules.
Args
3 functions
Args.get(name) -> stringArgs.has(name) -> boolArgs.positional() -> array
Base64
2 functions
Base64.encode(data) -> stringBase64.decode(data) -> string
Crypto
8 functions
Crypto.hash32(data) -> intCrypto.hash64(data) -> intCrypto.sha1(data) -> stringCrypto.sha1_base64(data) -> stringCrypto.sha256(data) -> stringCrypto.md5(data) -> stringCrypto.hmac_sha256(key, data) -> stringCrypto.random_bytes(n) -> string
Csv
8 functions
Csv.parse(text) -> intCsv.row_count(handle) -> intCsv.get(handle, row, col) -> stringCsv.get_field(handle, row, header) -> stringCsv.col_count(handle, row) -> intCsv.header(handle, col) -> stringCsv.header_count(handle) -> intCsv.write(path, rows)
Data
2 functions
Data.save(path, map)Data.load(path) -> HashMap
DateTime
16 functions
DateTime.now() -> intDateTime.millis() -> intDateTime.micros() -> intDateTime.format(timestamp, fmt) -> stringDateTime.sleep(seconds)DateTime.diff(a, b) -> intDateTime.add_seconds(t, n) -> intDateTime.to_iso(timestamp) -> stringDateTime.format_duration(ms) -> stringDateTime.day_of_week(timestamp) -> intDateTime.year(timestamp) -> intDateTime.month(timestamp) -> intDateTime.day(timestamp) -> intDateTime.hour(timestamp) -> intDateTime.minute(timestamp) -> intDateTime.second(timestamp) -> int
Db
11 functions
Db.open(path) -> intDb.exec(handle, sql) -> intDb.query(handle, sql) -> stringDb.query_one(handle, sql) -> stringDb.exec_p(handle, sql, params) -> intDb.query_p(handle, sql, params) -> stringDb.last_insert_id(handle) -> intDb.error(handle) -> stringDb.close(handle)Db.escape(str) -> stringDb.table_exists(handle, table_name) -> int
Encoding
5 functions
Encoding.base64_encode(data) -> stringEncoding.base64_decode(data) -> stringEncoding.hex_encode(data) -> stringEncoding.hex_decode(hex) -> stringEncoding.csv_parse(csv) -> string
Env
3 functions
Env.get(name) -> stringEnv.set(name, value) -> intEnv.all()- does not work as documented. The checker types the resultint, so assigning it fails to build (initializing 'long long' from 'WynArray'). Filed.
File
23 functions
File.read(p) -> stringFile.read_lines(p) -> stringFile.write(p, d) -> intFile.exists(p) -> intFile.delete(p) -> intFile.copy(s, d) -> intFile.move(s, d) -> intFile.size(p) -> intFile.is_dir(p) -> intFile.is_file(p) -> intFile.mkdir(p) -> intFile.list_dir(p) -> stringFile.append(p, d) -> intFile.cwd() -> stringFile.open(path, mode) -> intFile.read_line(handle) -> stringFile.write_line(handle, data) -> intFile.eof(handle) -> intFile.close(handle)File.rename(old_path, new_path) -> intFile.glob(pattern) -> stringFile.walk_dir(path) -> stringFile.temp_file() -> string
HashMap
Create with HashMap(), then use string keys and values:
m = HashMap.new()
m.set("name", "Wyn")
print(m.get("name")) // Wyn
print(m.len().to_string()) // 1
print(m.has("name").to_string()) // true
m.remove("name")
keys = m.keys() // []Methods (dot syntax on a HashMap value):
.set(key, value)- set a key-value pair.get(key) -> string- value for a key.has(key) -> bool- whether a key exists.len() -> int- number of entries.remove(key)- remove a key.keys() -> array- all keys
HashSet
1 function
HashSet.new() -> HashSet
Input (global builtins)
3 functions - not namespaced, callable anywhere.
input_line() -> string- read one line from stdin, newline strippedinput() -> int- read one line and parse it as an integerinput_float() -> float- read one line and parse it as a float
input() and input_float() validate the whole line and panic on anything else (changed in v1.21.0 - they previously returned 0 at exit 0, which turned bad input into a wrong answer):
$ echo abc | ./prog
panic: input(): "abc" is not a valid integer; use input_line() to read text
$ printf '' | ./prog
panic: input(): end of input (expected an integer)12abc is rejected rather than read as 12, the trailing newline is consumed (so a following input_line() returns the next line rather than ""), and 64-bit values survive. Set WYN_LENIENT=1 to warn and return 0 instead of aborting, if you are migrating a program that relied on the old behaviour. Use input_line() when the input is text.
Http
18 functions
Http.post(url, body) -> stringHttp.status(resp) -> intHttp.body(resp) -> stringHttp.header(resp, name) -> stringHttp.free(resp)Http.respond(client_fd, status, content_type, body)Http.route_match(pattern, path, params) -> intHttp.parse_request(raw) -> HashMapHttp.ctx_fd(ctx) -> intHttp.respond_json(fd, status, json)Http.respond_html(fd, status, html)Http.serve(port) -> intHttp.accept(server_fd) -> string- blocks for the next request. Since v1.21.0 it skips a connection that sends no request and keeps accepting, so it never returns"". Before that it did, and the documented.split_at("|", 3).to_int()idiom then panicked on the empty string - one unauthenticated packet, or an ordinary TCP health check, port scan or browser preconnect, killed the server process.Http.close_server(fd)Http.get_json(url) -> intHttp.post_json(url, data) -> intHttp.set_timeout(seconds)Http.timeout() -> int
Json
19 functions
Json.new() -> JsonJson.set(j, k, v)Json.set_string(j, k, v)Json.set_int(j, k, v)Json.set_bool(j, k, v)Json.stringify(j) -> stringJson.parse(text) -> intJson.get(root, key) -> stringJson.get_int(root, key) -> intJson.has(root, key) -> intJson.array_len(node) -> intJson.array_get(node, index) -> intJson.node_str(node) -> stringJson.keys(root) -> stringJson.get_float(root, key) -> floatJson.get_bool(root, key) -> intJson.get_array(root, key) -> intJson.get_object(root, key) -> intJson.to_pretty_string(j) -> string
Log
5 functions
Log.set_level(level)Log.debug(msg)Log.info(msg)Log.warn(msg)Log.error(msg)
Math
26 functions
Math.sin(x) -> floatMath.cos(x) -> floatMath.tan(x) -> floatMath.sqrt(x) -> floatMath.pow(base, exp) -> floatMath.floor(x) -> floatMath.ceil(x) -> floatMath.round_to(x, places) -> floatMath.atan2(y, x) -> floatMath.pi() -> floatMath.e() -> floatMath.round(x) -> floatMath.abs(x) -> intMath.max(a, b) -> floatMath.min(a, b) -> floatMath.checked_add(a, b) -> intMath.checked_sub(a, b) -> intMath.checked_mul(a, b) -> intMath.random() -> floatMath.log(x) -> floatMath.log10(x) -> floatMath.exp(x) -> floatMath.clamp(x, lo, hi) -> intMath.sign(x) -> intMath.lerp(a, b, t) -> floatMath.map_range(x, in_min, in_max, out_min, out_max) -> float
Net
6 functions
Net.listen(port) -> intNet.connect(host, port) -> intNet.send(sockfd, data) -> intNet.recv(sockfd) -> stringNet.close(sockfd) -> intNet.resolve(hostname) -> string
Os
6 functions
Os.platform() -> stringOs.arch() -> stringOs.hostname() -> stringOs.pid() -> intOs.temp_dir() -> stringOs.home_dir() -> string
Path
4 functions
Path.basename(p) -> stringPath.dirname(p) -> stringPath.extension(p) -> stringPath.join(a, b) -> string
Process
2 functions
Process.exec_capture(cmd) -> stringProcess.exec_status(cmd) -> int
Regex
5 functions
Regex.match(s, p) -> bool- whether the pattern matches anywhereRegex.replace(s, p, r) -> string- replace every matchRegex.find(s, p) -> int- byte offset of the first match, or -1Regex.find_all(s, p) -> string- one string, one match per lineRegex.split(s, p) -> string- one string, one field per line
find_all and split return newline-joined strings, not arrays. Iterate them with .trim().split("\n"):
fn main() {
text = "mail [email protected] or [email protected]"
emails = Regex.find_all(text, "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")
for email in emails.trim().split("\n") { println(email) }
}There are no capture groups. Regex.match returns a bool - there is no match object, no .group(n), no named groups. Extract fields with .split() or .substring() after matching.
The shorthand classes \d, \w and \s are not supported, and they fail silently - \d is matched as a literal d, so Regex.replace(s, "\\d+", "N") turns "disk" into "Nisk" and leaves the digits alone. Use explicit character classes, which work correctly:
| Instead of | Write |
|---|---|
\d | [0-9] |
\w | [A-Za-z0-9_] |
\s | [ \t\n] |
Supported: literals, ., character classes (including escapes inside them, e.g. [ \t]), *, +, ?, {n}, {n,m}, alternation (a|b), and the ^/$ anchors. Not supported: backreferences, lookaround, capture-group extraction, and the shorthand classes above.
Socket
8 functions
Socket.connect(host, port) -> intSocket.send(sock, data, len) -> intSocket.recv(sock, max_len) -> stringSocket.close(sock)Socket.set_timeout(sock, seconds) -> intSocket.set_nonblocking(sock) -> intSocket.poll_read(sock, timeout_ms) -> intSocket.read_line(sock) -> string
StringBuilder
8 functions
StringBuilder.new() -> intStringBuilder.append(handle, s)StringBuilder.to_string(handle) -> stringStringBuilder.len(handle) -> intStringBuilder.clear(handle)StringBuilder.free(handle)StringBuilder.append_int(handle, val)StringBuilder.append_line(handle, s)
System
9 functions
System.shell_escape(s) -> stringSystem.exec(cmd) -> stringSystem.exec_code(cmd) -> intSystem.exit(code)System.env(key) -> stringSystem.set_env(key, value) -> intSystem.args() -> arraySystem.gc()System.load_env(path)
Task
12 functions
Task.value(initial) -> intTask.get(handle) -> intTask.set(handle, value)Task.add(handle, amount)Task.free_value(handle)Task.channel(capacity) -> intTask.send(handle, value)Task.recv(handle) -> intTask.close(handle)Task.try_recv(handle) -> int?-Some(v)when a value is ready,nonewhen empty (changed in v1.20; the old two-argument out-param form no longer exists)Task.select_2(ch1, ch2) -> intTask.select_3(ch1, ch2, ch3) -> int
Toml
3 functions
Toml.parse(text) -> intToml.get(handle, key) -> stringToml.parse_file(path) -> int
Url
2 functions
Url.encode(str) -> stringUrl.decode(str) -> string
Uuid
2 functions
Uuid.generate() -> stringUuid.v4() -> string
Ws
4 functions. All four currently fail to link (Ws.connect, Ws.send, Ws.recv, Ws.close) - they type-check and then the build fails at the linker. Filed; do not build on these yet.
Ws.connect(url) -> intWs.send(sock, msg) -> intWs.recv(sock) -> stringWs.close(sock)