diff --git a/_03.Standard-library.sz b/_03.Standard-library.sz index 811a032..03f0c6a 100644 --- a/_03.Standard-library.sz +++ b/_03.Standard-library.sz @@ -19,7 +19,7 @@ For more details, see @link["modules/std/array.html"]{@code{(std array)}} and @l @subsection{std/fmt} -Formatting in two layers: interpolation and layout. @code{println*} prints strings, ints, doubles, chars and bools written in one vec. The layout layer is made of blocks: a @code{Block} is one piece of output, and every combinator takes its content as a @code{(Vec Block)}, a vec literal such as @code{["x = " 7 nl]}, and gives back one @code{Block}. With them you pad, cut and align text, wrap and justify paragraphs, format numbers, and lay out tables with borders, a header, and columns that fit the width. The section on formatting text in "Writing programs" is a guide, with what goes in the brackets and what to write when it does not compile. +Formatting in two layers: interpolation and layout. @code{println*} prints strings, ints, doubles, chars and bools written in one vec. The layout layer is made of blocks: a @code{Block} is one piece of output, and every combinator takes its content as a block and gives back a block. A string, an int and a character are blocks, and so is a vec of blocks, such as @code{["x = " 7 nl]}. With them you pad, cut and align text, wrap and justify paragraphs, format numbers, and lay out tables with borders, a header, and columns that fit the width. The section on formatting text in "Writing programs" is a guide, with what goes in the brackets and what to write when it does not compile. For more details, see @link["modules/std/fmt.html"]{@code{(std fmt)}}. @subsection{std/rx} @@ -27,6 +27,11 @@ For more details, see @link["modules/std/fmt.html"]{@code{(std fmt)}}. Bjolang provides a built-in regular expression engine. Unlike languages that use strings for regex (like @code{"[a-z]+"}), Bjolang uses structural S-expressions. This means you never have to double-escape characters, and the compiler validates your patterns at compile time. Built-in character sets and anchors are written as keywords (e.g., @code{:bos}, @code{:digit}), and operations that group or repeat patterns are function-like lists (e.g., @code{(seq ...)}). For more details, see @link["modules/std/rx.html"]{@code{(std rx)}}. +@subsection{std/scan} + +Reading a line by a pattern, after OCaml's @code{Scanf}. The pattern is a quoted list of what the line holds, in order: @code{(scan "3-17" '(long "-" long))} is 3 and 17, and @code{'(int "x" int ": " int ... #:sep " ")} reads @code{"12x5: 1 0 3"} as two ints and a vec of them. There are items for numbers, a character, a word, the rest of the line, a run of given characters and the text up to one, with a width, a skip, a repetition, an option and a choice. The type of the result comes from the pattern, so @code{'(int "," int)} gives a @code{(Tuple int int)}. The macro compiles the pattern into straight code over the line's bytes, and a pattern of numbers and strings allocates nothing. The whole line must match. @code{try-scan} gives an @code{Err} that says at which column it failed, instead of raising. A scan does not search and does not backtrack: use @code{(std rx)} to find text in a line. +For more details, see @link["modules/std/scan.html"]{@code{(std scan)}}. + @subsection{std/http} The @code{std/http} module allows you to build and send HTTP requests. Sending a request three ways — blocking, suspending, or as an event — is the only thing that differs between the entry points. There is no C# in this module: @code{System.Net.Http} is reached with @code{import/extern}, and the response body is an ordinary @code{TextInputPort}. @@ -47,6 +52,16 @@ For more details, see @link["modules/std/run.html"]{@code{(std run)}}. The random module provides a ChaCha20 generator, seeded with 256 bits from the OS CSPRNG, with one generator per thread. The default path locks nothing and shares nothing, making it safe and fast on a bjoroutine. The ambient source has no state to race on, so drawing from multiple threads is efficient. You can generate random integers and more. For more details, see @link["modules/std/random.html"]{@code{(std random)}}. +@subsection{std/uuid} + +Uuids as RFC 9562 specifies them. @code{uuid-v4} is random, for an identifier that must tell nothing. @code{uuid-v7} starts with the time, for a database key: new keys go at the end of an index, and keys sort by when they were made, and the ones made by one process always increase. @code{uuid-v5} is made from a namespace and a name, so the same input gives the same uuid. A @code{Uuid} is 16 bytes and compares as its bytes do, which is also the order of its text and of Postgres' @code{uuid}. @code{uuid->string} writes the one text form, and @code{string->uuid} reads it in either case. The random bits come from @code{current-random} and the time from @code{current-clock}, so a test can make the same uuids in every run. +For more details, see @link["modules/std/uuid.html"]{@code{(std uuid)}}. + +@subsection{std/crypto/hash} + +Hashes, HMAC and password hashing, from .NET's @code{System.Security.Cryptography}. @code{hash-bytes}, @code{hash-string} and @code{hash-file} make a digest, SHA-256 unless @code{#:algorithm} says otherwise, and @code{make-hasher} makes one a piece at a time. @code{hmac-bytes} and @code{hmac-string} sign a message with a key. A digest is fast, so it is not a password hash: @code{password-hash} uses PBKDF2 with a random salt and gives a PHC string, which holds the algorithm and the iteration count, so @code{password-verify} needs only the password and the string, and @code{password-needs-rehash?} says which to replace after the count is raised. A password hash takes a few hundred milliseconds, and in a bjoroutine it runs on a thread of its own. Compare secrets with @code{constant-time-equal?}, not @code{=}. +For more details, see @link["modules/std/crypto/hash.html"]{@code{(std crypto hash)}}. + @subsection{std/atomic} An atomic is a cell that threads can read and write without a lock. @code{(make-atomic v)} makes one of any type, and @code{atomic-ref}, @code{atomic-set!}, @code{atomic-swap!}, @code{atomic-compare-and-swap!} and @code{atomic-update!} work on it. For @code{int}, @code{uint}, @code{long} and @code{ulong} there are also @code{atomic-increment!}, @code{atomic-decrement!}, @code{atomic-add!} and @code{atomic-sub!}, which compile to direct calls to @code{System.Threading.Interlocked} and wrap on overflow. Swap and compare-and-swap return the value from before the call; the other operations that change the atomic return the new value. The width of a counter comes from type inference, so write @code{(make-atomic 0L)} for a long counter: @code{(make-atomic 0)} is an int. @@ -82,6 +97,11 @@ For more details, see @link["modules/std/effect.html"]{@code{(std effect)}}. Persistent collections beside the prelude's @code{Map}: an update returns a new collection and does not change the old one. @code{(std hashset)} has the unordered @code{HashSet}, a CHAMP trie that compares elements with @code{Eq}. @code{(std orderedset)} and @code{(std orderedmap)} have @code{OrderedSet} and @code{OrderedMap}, B-trees kept in the order of @code{compare}. They add what the order gives: @code{-min}, @code{-max}, @code{-successor}, @code{-predecessor} and the range walks @code{-range}, @code{-from} and @code{-until}. Each collection has a builder, which makes it in one pass, and a transient, which edits it in place and gives it back as a persistent collection in O(1). For more details, see @link["modules/std/hashset.html"]{@code{(std hashset)}}, @link["modules/std/orderedset.html"]{@code{(std orderedset)}} and @link["modules/std/orderedmap.html"]{@code{(std orderedmap)}}. +@subsection{std/priority-queue} + +A persistent priority queue, least priority first. A @code{(PriorityQueue a p)} holds elements under priorities, and orders the priorities, so the elements need no order of their own. @code{priorityqueue-empty} orders priorities by their @code{Ord}, and @code{priorityqueue-by} by a comparison you give it. Adding or removing gives a new queue and leaves the old one as it was. It is a pairing heap: peeking, adding and @code{priorityqueue-merge} are O(1), and @code{priorityqueue-remove-min} is O(log n) amortised. That bound assumes each queue is used once. Call @code{priorityqueue-balance} on a queue you keep and remove from many times. Entries of equal priority come out in the order they went in. There is a transient and a builder, as for the other persistent collections. For a queue that is used in one place and never shared, @code{(std mutable heap)} is faster. +For more details, see @link["modules/std/priority-queue.html"]{@code{(std priority-queue)}}. + @subsection{std/mutable} Collections that change in place. Use them for a cache, an index, a worklist or a scratch buffer, where you do not need old versions. @code{(std mutable vec)}, @code{(std mutable map)}, @code{(std mutable set)} and @code{(std mutable heap)} are the .NET @code{List}, @code{Dictionary}, @code{HashSet} and @code{PriorityQueue} themselves, not wrappers, so .NET code that takes those types accepts them as they are. They compare with .NET's equality and order. @code{(std mutable deque)} is a double-ended queue with O(1) amortized push and pop at both ends. None of them has a lock. @@ -125,10 +145,20 @@ For more details, see @link["modules/std/syntax-match.html"]{@code{(std syntax-m @subsection{text/bjodat} -bjodat is Bjolang's shapes read as data: no evaluation, no macro expansion, no environment. It is what a package manifest, a lockfile, or a config file is written in. You can parse text straight into a record using @code{bjodat-parse-}, which avoids intermediate trees and allocations. -For more details, see @link["modules/text/bjodat.html"]{@code{(text bjodat)}}. +bjodat is Bjolang's shapes read as data: no evaluation, no macro expansion, no environment. It is what a package manifest, a lockfile, or a config file is written in. You can parse text straight into a record using @code{bjodat-parse-}, which avoids intermediate trees and allocations. @code{(text bjodat-core)} is the machinery underneath: the @code{Bjodat} tree, with @code{parse-bjodat}, @code{bjodat-ref} and the writer, for data whose shape is not known until the program runs. +For more details, see @link["modules/text/bjodat.html"]{@code{(text bjodat)}} and @link["modules/text/bjodat-core.html"]{@code{(text bjodat-core)}}. -@subsection{text/json} +@subsection{text/json and text/json-codec} -The @code{text/json} module provides JSON parsing and generation capabilities. Like @code{bjodat}, it allows for working with structured data but using the standard JSON format, which is essential for web communication. -For more details, see @code{prelude.org} and related standard library documentation. +@code{(text json)} reads JSON, exactly as RFC 8259 has it, into a @code{Json}: a union with a case for each kind of value. @code{parse-json} reads a string and @code{read-json} a port. A document that is not JSON is an @code{Err} that says the line and column where it went wrong. A number without a fraction or an exponent is a @code{JsonInt}, and an object is a @code{(Map string Json)}, so the order of its keys is not kept. @code{(text json-codec)} reads a record straight from the tree and back: @code{def/json-type} declares a record and the instances of @code{->json} and @code{json->} for it, with defaults, optional fields and other names for the keys. An @code{Option} is @code{null} when it is @code{None}. There is no writer yet, so a @code{Json} cannot be written out as text. +For more details, see @link["modules/text/json.html"]{@code{(text json)}} and @link["modules/text/json-codec.html"]{@code{(text json-codec)}}. + +@subsection{text/xml} + +XML, in three modules over @code{System.Xml}. @code{(text xml)} is the tree: names, elements, texts, comments and processing instructions, built by @code{xml-element} and the others, and taken apart by views. @code{(text xml read)} reads XML in four layers: a stream of signals, a fold after SSAX, a tree of your own type, and @code{parse-xml}, which gives a @code{Document}. @code{xml-for-each} reads a large document one element at a time. The defaults are the safe ones: a document with a DOCTYPE is refused unless asked for, and nothing external is ever resolved. @code{(text xml write)} writes a node or a document to a port or a string. It chooses the namespace prefixes, and content that XML cannot hold is an @code{XmlWriteError} rather than an exception. +For more details, see @link["modules/text/xml.html"]{@code{(text xml)}}, @link["modules/text/xml/read.html"]{@code{(text xml read)}} and @link["modules/text/xml/write.html"]{@code{(text xml write)}}. + +@subsection{text/encodings} + +Every character encoding .NET knows, as a value of the prelude's @code{Encoding}, to give to @code{string->bytes} and @code{bytes->string}, or to @code{reencode-input-port} and @code{reencode-output-port} from @code{(std ports)} for a port. There is one for each of the 139, named in lower case as .NET names them: @code{utf-16be}, @code{iso-8859-1}, @code{windows-1252}, @code{shift_jis}, @code{koi8-r} and the rest. .NET's little-endian @code{utf-16} and @code{utf-32} are @code{utf-16le} and @code{utf-32le} here. @code{encoding-named} finds one by name and @code{encoding-of-code-page} by number, both as an @code{Option}. No encoding writes or skips a byte order mark. Each encoding is made the first time it is used, so importing the module costs nothing. +For more details, see @link["modules/text/encodings.html"]{@code{(text encodings)}}. diff --git a/modules/std/crypto/hash.sz b/modules/std/crypto/hash.sz new file mode 100644 index 0000000..f4bbfcd --- /dev/null +++ b/modules/std/crypto/hash.sz @@ -0,0 +1,3 @@ +(meta (title "(std crypto hash)")) + +@generate-docs[#:module "std crypto hash"] diff --git a/modules/std/crypto/index.sz b/modules/std/crypto/index.sz new file mode 100644 index 0000000..a1e49d9 --- /dev/null +++ b/modules/std/crypto/index.sz @@ -0,0 +1,2 @@ +(meta (title "(std crypto)") + (sort title)) diff --git a/modules/std/priority-queue.sz b/modules/std/priority-queue.sz new file mode 100644 index 0000000..8c7b0ba --- /dev/null +++ b/modules/std/priority-queue.sz @@ -0,0 +1,3 @@ +(meta (title "(std priority-queue)")) + +@generate-docs[#:module "std priority-queue"] diff --git a/modules/std/scan.sz b/modules/std/scan.sz new file mode 100644 index 0000000..17bc420 --- /dev/null +++ b/modules/std/scan.sz @@ -0,0 +1,3 @@ +(meta (title "(std scan)")) + +@generate-docs[#:module "std scan"] diff --git a/modules/std/uuid.sz b/modules/std/uuid.sz new file mode 100644 index 0000000..4fa8678 --- /dev/null +++ b/modules/std/uuid.sz @@ -0,0 +1,3 @@ +(meta (title "(std uuid)")) + +@generate-docs[#:module "std uuid"] diff --git a/modules/text/encodings.sz b/modules/text/encodings.sz new file mode 100644 index 0000000..686306e --- /dev/null +++ b/modules/text/encodings.sz @@ -0,0 +1,3 @@ +(meta (title "(text encodings)")) + +@generate-docs[#:module "text encodings"]