morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
bundle.hpp File Reference

What the UI service's client and server share (spec 5 §12): content hashes, the bundle's manifest, and the bodies of the ui-hello, ui-catalog and ui-fetch envelopes, with their bounds and their parsers. More...

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <functional>
#include <glaze/glaze.hpp>
#include <initializer_list>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <variant>
#include <vector>
#include "../core/wire.hpp"
#include "../session/session_auth.hpp"
#include "document.hpp"
#include "value.hpp"

Go to the source code of this file.

Classes

struct  morph::ui::ManifestFile
 One file of a manifest. More...
struct  morph::ui::Manifest
 A bundle's manifest: every file the application serves, by its hash (spec 5 §12, "Content addressing"). More...
struct  morph::ui::HelloRequest
 The body of a ui-hello request: what the client speaks and carries. More...
struct  morph::ui::HelloReply
 The body of a ui-hello reply. More...
struct  morph::ui::EvaluateReply
 The body of a ui-evaluate reply: what ActionDispatcher::evaluate answered. More...
struct  morph::ui::FileRequest
 The body of a ui-file request: one step of an upload or a download, named by op. More...
struct  morph::ui::FileReply
 The body of a ui-file reply: the members its op answers, the others absent. More...
struct  morph::ui::CatalogEntry
 One catalog entry (spec 6 §8). More...
struct  morph::ui::CatalogReply
 The body of a ui-catalog reply: the catalog filtered for the principal, and the facts a client's load-time validation reads (ui::Catalog). More...
struct  morph::ui::FetchRequest
 The body of a ui-fetch request. More...

Functions

std::string morph::ui::contentHash (std::string_view bytes)
 The content hash of bytes: sha256: and the SHA-256 digest in 64 lower-case hexadecimal digits.
bool morph::ui::isContentHash (std::string_view text)
 Whether text is a well-formed content hash.
std::optional< std::string > morph::ui::detail::mustUnderstand (Json const &json, std::string_view where)
 The must-understand key (!name) of one object, if it has one.
std::optional< std::string > morph::ui::detail::mustUnderstandIn (Json const &root, std::string_view what, std::initializer_list< std::string_view > arrays, std::initializer_list< std::string_view > maps)
 The must-understand keys of a message: its top level, every element of its listed arrays and every value of its listed maps.
template<typename T>
std::expected< T, std::string > morph::ui::detail::readMessage (std::string_view text, std::string_view what, std::initializer_list< std::string_view > arrays, std::initializer_list< std::string_view > maps)
 Reads a message: bounded depth, must-understand keys refused, unknown keys ignored.
template<typename T>
std::string morph::ui::detail::writeMessage (T const &value)
 Writes a message as JSON, escaping control bytes as wire::encode does.
std::optional< std::string > morph::ui::detail::checkName (std::string_view name, std::string_view what)
 Checks a name's length.
std::optional< std::string > morph::ui::detail::checkNames (std::vector< std::string > const &names, std::size_t limit, std::string_view list, std::string_view item)
 Checks a list of names: its length and each name's.
std::optional< std::string > morph::ui::detail::checkHostNames (std::map< std::string, std::int64_t, std::less<> > const &names, std::string_view list, std::string_view item)
 Checks a map of host names to versions: its size and each name's length.
std::string morph::ui::manifestText (Manifest const &manifest)
 The manifest's text: the JSON its digest is the hash of. Equal manifests write equal text.
std::expected< Manifest, std::string > morph::ui::parseManifest (std::string_view text)
 Reads a manifest a server sent.
std::expected< HelloRequest, std::string > morph::ui::parseHelloRequest (std::string_view text)
 Reads a ui-hello request body.
std::expected< HelloReply, std::string > morph::ui::parseHelloReply (std::string_view text)
 Reads a ui-hello reply body.
std::expected< EvaluateReply, std::string > morph::ui::parseEvaluateReply (std::string_view text)
 Reads a ui-evaluate reply body.
std::expected< FileRequest, std::string > morph::ui::parseFileRequest (std::string_view text)
 Reads a ui-file request body.
std::expected< FileReply, std::string > morph::ui::parseFileReply (std::string_view text)
 Reads a ui-file reply body.
std::expected< CatalogReply, std::string > morph::ui::parseCatalogReply (std::string_view text)
 Reads a ui-catalog reply body.
std::expected< FetchRequest, std::string > morph::ui::parseFetchRequest (std::string_view text)
 Reads a ui-fetch request body.

Variables

constexpr std::string_view morph::ui::kExprVocabulary = "expr/1"
 The expression vocabulary every bundle needs alongside ui/1.
constexpr std::string_view morph::ui::kHelloKind = "ui-hello"
 The envelope kind of the handshake.
constexpr std::string_view morph::ui::kCatalogKind = "ui-catalog"
 The envelope kind of the catalog.
constexpr std::string_view morph::ui::kFetchKind = "ui-fetch"
 The envelope kind that fetches a file by its hash.
constexpr std::string_view morph::ui::kEvaluateKind = "ui-evaluate"
 The envelope kind that evaluates an action body without running it (spec 5 §7).
constexpr std::string_view morph::ui::kFileKind = "ui-file"
 The envelope kind of the file side channel (files/1, spec 6 §18): uploads and downloads in chunks.
constexpr std::string_view morph::ui::kServiceModel = "ui"
 The pseudo-model the service's envelopes are authorised under: authorize(session, "ui", <action>).
constexpr std::string_view morph::ui::kHelloAction = "hello"
 The pseudo-action that gates ui-hello, and the fetch of a public file or the manifest.
constexpr std::string_view morph::ui::kCatalogAction = "catalog"
 The pseudo-action that gates ui-catalog.
constexpr std::string_view morph::ui::kFetchAction = "fetch"
 The pseudo-action that gates the fetch of a file that is not public.
constexpr std::string_view morph::ui::kHashPrefix = "sha256:"
 The prefix of a content hash.
constexpr std::size_t morph::ui::kHashDigits = 64
 The hexadecimal digits of a SHA-256 digest.
constexpr std::size_t morph::ui::kMaxFileChunkBytes = std::size_t{256} * 1024
 The most file bytes one ui-file chunk carries, before base64url.
constexpr std::size_t morph::ui::kMaxFileRequestBytes = (kMaxFileChunkBytes / 3 * 4) + (std::size_t{4} * 1024)
 The largest ui-file request body a server reads: a chunk in base64url, and the rest of the request.
constexpr std::size_t morph::ui::kMaxRequestBytes = std::size_t{64} * 1024
 The largest request body (ui-hello, ui-fetch) a server reads.
constexpr std::size_t morph::ui::kMaxFileBytes = std::size_t{4} * 1024 * 1024
 The largest file a bundle may hold, and a client accepts.
constexpr std::size_t morph::ui::kMaxBundleFiles = 4096
 The most files a manifest, and entries a catalog, may list.
constexpr std::size_t morph::ui::kMaxCatalogFacts = 16384
 The most action ids, model facts or action facts a catalog may carry.
constexpr std::size_t morph::ui::kMaxListItems = 256
 The most items of a list or map in a ui-hello (vocabularies, host components, commands, values).
constexpr std::size_t morph::ui::kMaxNameBytes = 256
 The longest name: an id, a kind, a vocabulary, a host name, an application id or version.
constexpr std::string_view morph::ui::kScreenFile = "screen"
 The file kinds of a manifest.
constexpr std::string_view morph::ui::kAppFile = "app"
 The app document (spec 6 §5).
constexpr std::string_view morph::ui::kThemeFile = "theme"
 A theme (ui-theme/1, spec 6 §6).
constexpr std::string_view morph::ui::kMessagesFile = "messages"
 A message catalogue.
constexpr std::string_view morph::ui::kComponentFile = "component"
 A delivered custom component (spec 5 §10).
constexpr std::string_view morph::ui::kIconFile = "icon"
 An icon of a theme's icon set: SVG text.
constexpr std::size_t morph::ui::kMaxIconBytes = std::size_t{64} * 1024
 The largest icon file a bundle may hold.

Detailed Description

What the UI service's client and server share (spec 5 §12): content hashes, the bundle's manifest, and the bodies of the ui-hello, ui-catalog and ui-fetch envelopes, with their bounds and their parsers.

Specified in docs/spec/ui/service.md.

Definition in file bundle.hpp.

Function Documentation

◆ contentHash()

std::string morph::ui::contentHash ( std::string_view bytes)
inlinenodiscard

The content hash of bytes: sha256: and the SHA-256 digest in 64 lower-case hexadecimal digits.

Parameters
bytesThe bytes.
Returns
The hash.

Definition at line 99 of file bundle.hpp.

◆ isContentHash()

bool morph::ui::isContentHash ( std::string_view text)
inlinenodiscard

Whether text is a well-formed content hash.

Parameters
textThe text.
Returns
true for sha256: followed by exactly 64 lower-case hexadecimal digits.

Definition at line 115 of file bundle.hpp.

◆ mustUnderstand()

std::optional< std::string > morph::ui::detail::mustUnderstand ( Json const & json,
std::string_view where )
inlinenodiscard

The must-understand key (!name) of one object, if it has one.

Parameters
jsonThe value; anything but an object has none.
whereWhat the object is, for the reason.
Returns
Why the message is refused, or nothing.

Definition at line 369 of file bundle.hpp.

◆ mustUnderstandIn()

std::optional< std::string > morph::ui::detail::mustUnderstandIn ( Json const & root,
std::string_view what,
std::initializer_list< std::string_view > arrays,
std::initializer_list< std::string_view > maps )
inlinenodiscard

The must-understand keys of a message: its top level, every element of its listed arrays and every value of its listed maps.

Parameters
rootThe parsed message.
whatWhat the message is.
arraysThe keys of arrays whose elements are objects this layer defines.
mapsThe keys of maps whose values are objects this layer defines.
Returns
Why the message is refused, or nothing.

Definition at line 391 of file bundle.hpp.

◆ readMessage()

template<typename T>
std::expected< T, std::string > morph::ui::detail::readMessage ( std::string_view text,
std::string_view what,
std::initializer_list< std::string_view > arrays,
std::initializer_list< std::string_view > maps )
nodiscard

Reads a message: bounded depth, must-understand keys refused, unknown keys ignored.

Template Parameters
TThe message type.
Parameters
textThe JSON text.
whatWhat the message is, for the reason.
arraysThe keys of arrays whose elements are objects this layer defines.
mapsThe keys of maps whose values are objects this layer defines.
Returns
The message, or why it was refused.

Definition at line 437 of file bundle.hpp.

◆ writeMessage()

template<typename T>
std::string morph::ui::detail::writeMessage ( T const & value)
nodiscard

Writes a message as JSON, escaping control bytes as wire::encode does.

Template Parameters
TThe message type.
Parameters
valueThe message.
Returns
The JSON text.

Definition at line 459 of file bundle.hpp.

◆ checkName()

std::optional< std::string > morph::ui::detail::checkName ( std::string_view name,
std::string_view what )
inlinenodiscard

Checks a name's length.

Parameters
nameThe name.
whatWhat it names, for the reason.
Returns
Why it is refused, or nothing.

Definition at line 471 of file bundle.hpp.

◆ checkNames()

std::optional< std::string > morph::ui::detail::checkNames ( std::vector< std::string > const & names,
std::size_t limit,
std::string_view list,
std::string_view item )
inlinenodiscard

Checks a list of names: its length and each name's.

Parameters
namesThe names.
limitThe most names allowed.
listWhat the list is, for the reason.
itemWhat one name is, for the reason.
Returns
Why the list is refused, or nothing.

Definition at line 485 of file bundle.hpp.

◆ checkHostNames()

std::optional< std::string > morph::ui::detail::checkHostNames ( std::map< std::string, std::int64_t, std::less<> > const & names,
std::string_view list,
std::string_view item )
inlinenodiscard

Checks a map of host names to versions: its size and each name's length.

Parameters
namesThe map.
listWhat the map holds, for the reason.
itemWhat one name is, for the reason.
Returns
Why the map is refused, or nothing.

Definition at line 503 of file bundle.hpp.

◆ manifestText()

std::string morph::ui::manifestText ( Manifest const & manifest)
inlinenodiscard

The manifest's text: the JSON its digest is the hash of. Equal manifests write equal text.

Parameters
manifestThe manifest; its files should be sorted by kind then id.
Returns
The JSON text.

Definition at line 523 of file bundle.hpp.

◆ parseManifest()

std::expected< Manifest, std::string > morph::ui::parseManifest ( std::string_view text)
inlinenodiscard

Reads a manifest a server sent.

Refused: text that is not JSON or nests deeper than kMaxJsonDepth, a must-understand key at the top or in a file, more than kMaxBundleFiles files, a name longer than kMaxNameBytes, a malformed hash, a size above kMaxFileBytes, or two files of one kind with one id. Unknown keys are ignored.

Parameters
textThe manifest's text, already verified against its digest.
Returns
The manifest, or why it was refused.

Definition at line 532 of file bundle.hpp.

◆ parseHelloRequest()

std::expected< HelloRequest, std::string > morph::ui::parseHelloRequest ( std::string_view text)
inlinenodiscard

Reads a ui-hello request body.

Refused: a body longer than kMaxRequestBytes, text that is not JSON or nests too deep, a must-understand key, more than kMaxListItems vocabularies or host names of a kind, or a name longer than kMaxNameBytes.

Parameters
textThe request body; empty reads as a client that speaks nothing.
Returns
The request, or why it was refused.

Definition at line 574 of file bundle.hpp.

◆ parseHelloReply()

std::expected< HelloReply, std::string > morph::ui::parseHelloReply ( std::string_view text)
inlinenodiscard

Reads a ui-hello reply body.

Refused: text that is not JSON or nests too deep, a must-understand key, more than kMaxListItems vocabularies, a name longer than kMaxNameBytes, or a digest that is not a content hash.

Parameters
textThe reply body.
Returns
The reply, or why it was refused.

Definition at line 607 of file bundle.hpp.

◆ parseEvaluateReply()

std::expected< EvaluateReply, std::string > morph::ui::parseEvaluateReply ( std::string_view text)
inlinenodiscard

Reads a ui-evaluate reply body.

Refused: text that is not JSON or nests too deep, a must-understand key at the top, a body that is not an object, or more than kMaxCatalogFacts field errors.

Parameters
textThe reply body.
Returns
The reply, or why it was refused.

Definition at line 633 of file bundle.hpp.

◆ parseFileRequest()

std::expected< FileRequest, std::string > morph::ui::parseFileRequest ( std::string_view text)
inlinenodiscard

Reads a ui-file request body.

Refused: a body longer than kMaxFileRequestBytes, text that is not JSON or nests too deep, a must-understand key, or an op that is not begin, chunk, end or read.

Parameters
textThe request body.
Returns
The request, or why it was refused.

Definition at line 654 of file bundle.hpp.

◆ parseFileReply()

std::expected< FileReply, std::string > morph::ui::parseFileReply ( std::string_view text)
inlinenodiscard

Reads a ui-file reply body.

Parameters
textThe reply body.
Returns
The reply, or why it was refused.

Definition at line 672 of file bundle.hpp.

◆ parseCatalogReply()

std::expected< CatalogReply, std::string > morph::ui::parseCatalogReply ( std::string_view text)
inlinenodiscard

Reads a ui-catalog reply body.

Refused: text that is not JSON or nests too deep, a must-understand key at the top, in an entry or in a model's or action's facts, more than kMaxBundleFiles entries, more than kMaxCatalogFacts permitted actions, model facts or action facts, or an entry id longer than kMaxNameBytes.

Parameters
textThe reply body.
Returns
The reply, or why it was refused.

Definition at line 683 of file bundle.hpp.

◆ parseFetchRequest()

std::expected< FetchRequest, std::string > morph::ui::parseFetchRequest ( std::string_view text)
inlinenodiscard

Reads a ui-fetch request body.

Refused: a body longer than kMaxRequestBytes, text that is not JSON or nests too deep, a must-understand key, or a hash that is not a content hash.

Parameters
textThe request body.
Returns
The request, or why it was refused.

Definition at line 714 of file bundle.hpp.

Variable Documentation

◆ kExprVocabulary

std::string_view morph::ui::kExprVocabulary = "expr/1"
inlineconstexpr

The expression vocabulary every bundle needs alongside ui/1.

Definition at line 36 of file bundle.hpp.

◆ kHelloKind

std::string_view morph::ui::kHelloKind = "ui-hello"
inlineconstexpr

The envelope kind of the handshake.

Definition at line 39 of file bundle.hpp.

◆ kCatalogKind

std::string_view morph::ui::kCatalogKind = "ui-catalog"
inlineconstexpr

The envelope kind of the catalog.

Definition at line 41 of file bundle.hpp.

◆ kFetchKind

std::string_view morph::ui::kFetchKind = "ui-fetch"
inlineconstexpr

The envelope kind that fetches a file by its hash.

Definition at line 43 of file bundle.hpp.

◆ kEvaluateKind

std::string_view morph::ui::kEvaluateKind = "ui-evaluate"
inlineconstexpr

The envelope kind that evaluates an action body without running it (spec 5 §7).

Definition at line 45 of file bundle.hpp.

◆ kFileKind

std::string_view morph::ui::kFileKind = "ui-file"
inlineconstexpr

The envelope kind of the file side channel (files/1, spec 6 §18): uploads and downloads in chunks.

Definition at line 47 of file bundle.hpp.

◆ kServiceModel

std::string_view morph::ui::kServiceModel = "ui"
inlineconstexpr

The pseudo-model the service's envelopes are authorised under: authorize(session, "ui", <action>).

Definition at line 50 of file bundle.hpp.

◆ kHelloAction

std::string_view morph::ui::kHelloAction = "hello"
inlineconstexpr

The pseudo-action that gates ui-hello, and the fetch of a public file or the manifest.

Definition at line 52 of file bundle.hpp.

◆ kCatalogAction

std::string_view morph::ui::kCatalogAction = "catalog"
inlineconstexpr

The pseudo-action that gates ui-catalog.

Definition at line 54 of file bundle.hpp.

◆ kFetchAction

std::string_view morph::ui::kFetchAction = "fetch"
inlineconstexpr

The pseudo-action that gates the fetch of a file that is not public.

Definition at line 56 of file bundle.hpp.

◆ kHashPrefix

std::string_view morph::ui::kHashPrefix = "sha256:"
inlineconstexpr

The prefix of a content hash.

Definition at line 59 of file bundle.hpp.

◆ kHashDigits

std::size_t morph::ui::kHashDigits = 64
inlineconstexpr

The hexadecimal digits of a SHA-256 digest.

Definition at line 61 of file bundle.hpp.

◆ kMaxFileChunkBytes

std::size_t morph::ui::kMaxFileChunkBytes = std::size_t{256} * 1024
inlineconstexpr

The most file bytes one ui-file chunk carries, before base64url.

Definition at line 64 of file bundle.hpp.

◆ kMaxFileRequestBytes

std::size_t morph::ui::kMaxFileRequestBytes = (kMaxFileChunkBytes / 3 * 4) + (std::size_t{4} * 1024)
inlineconstexpr

The largest ui-file request body a server reads: a chunk in base64url, and the rest of the request.

Definition at line 66 of file bundle.hpp.

◆ kMaxRequestBytes

std::size_t morph::ui::kMaxRequestBytes = std::size_t{64} * 1024
inlineconstexpr

The largest request body (ui-hello, ui-fetch) a server reads.

Definition at line 69 of file bundle.hpp.

◆ kMaxFileBytes

std::size_t morph::ui::kMaxFileBytes = std::size_t{4} * 1024 * 1024
inlineconstexpr

The largest file a bundle may hold, and a client accepts.

Definition at line 71 of file bundle.hpp.

◆ kMaxBundleFiles

std::size_t morph::ui::kMaxBundleFiles = 4096
inlineconstexpr

The most files a manifest, and entries a catalog, may list.

Definition at line 73 of file bundle.hpp.

◆ kMaxCatalogFacts

std::size_t morph::ui::kMaxCatalogFacts = 16384
inlineconstexpr

The most action ids, model facts or action facts a catalog may carry.

Definition at line 75 of file bundle.hpp.

◆ kMaxListItems

std::size_t morph::ui::kMaxListItems = 256
inlineconstexpr

The most items of a list or map in a ui-hello (vocabularies, host components, commands, values).

Definition at line 77 of file bundle.hpp.

◆ kMaxNameBytes

std::size_t morph::ui::kMaxNameBytes = 256
inlineconstexpr

The longest name: an id, a kind, a vocabulary, a host name, an application id or version.

Definition at line 79 of file bundle.hpp.

◆ kScreenFile

std::string_view morph::ui::kScreenFile = "screen"
inlineconstexpr

The file kinds of a manifest.

Definition at line 82 of file bundle.hpp.

◆ kAppFile

std::string_view morph::ui::kAppFile = "app"
inlineconstexpr

The app document (spec 6 §5).

Definition at line 84 of file bundle.hpp.

◆ kThemeFile

std::string_view morph::ui::kThemeFile = "theme"
inlineconstexpr

A theme (ui-theme/1, spec 6 §6).

Definition at line 86 of file bundle.hpp.

◆ kMessagesFile

std::string_view morph::ui::kMessagesFile = "messages"
inlineconstexpr

A message catalogue.

Definition at line 88 of file bundle.hpp.

◆ kComponentFile

std::string_view morph::ui::kComponentFile = "component"
inlineconstexpr

A delivered custom component (spec 5 §10).

Definition at line 90 of file bundle.hpp.

◆ kIconFile

std::string_view morph::ui::kIconFile = "icon"
inlineconstexpr

An icon of a theme's icon set: SVG text.

Definition at line 92 of file bundle.hpp.

◆ kMaxIconBytes

std::size_t morph::ui::kMaxIconBytes = std::size_t{64} * 1024
inlineconstexpr

The largest icon file a bundle may hold.

Definition at line 94 of file bundle.hpp.