This C++20 library provides some general useful building blocks and integrates with Google's Abseil library.
The library is tested with Clang (20+) and GCC (13+) on Ubuntu and MacOS (arm) using continuous integration: .
The C++ library is organized in functional groups each residing in their own directory:
namespace mbo::config--//mbo/config:limited_ordered_max_unroll_capacity which controls the maximum unroll size for LimitedOrdered and thus LimitedMap and LimitedSet.--//mbo/config:require_throws which controls whether MBO_CONFIG_REQUIRE throw exceptions or use crash logging (the default False or 0). This mostly affects containers.MBO_CONFIG_REQUIRE(condition, message) which allows to check a condition and either throw an exception or crash with Abseil FATAL logging. The behavior is controlled by --//mbo/config:require_throws.namespace mbo::containerAnyScan: A container type independent iteration view - or scan over the container.ConstScan: A container type independent iteration view for const value_types.ConvertingScan: A container scanner that allows for conversions.MakeAnyScan: Helper function to create AnyScan instances.MakeConstScan: Helper function to create ConstScan instances.MakeConvertingScan: Helper function to create ConvertingScan instances.ConvertContainer simplifies copying containers to value convertible containers.LimitedMap: A space limited, constexpr compliant map.LimitedOptions: A compile time configuration option for LimitedSet and LimitedMap.LimitedSet: A space limited, constexpr compliant set.LimitedVector: A space limited, constexpr compliant vector.namespace mbo::diffDiff: A class that implements line based diffing in unified, context, normal or side-by-side output format (DiffOptions::output_format), using the Myers minimal diff algorithm by default (DiffOptions::algorithm also offers naive and direct).diff: A binary that diffs two files; defaults to unified format, --format selects unified, context, normal or side-by-side (--width), --algorithm selects myers (default), naive or direct; --minimal guarantees minimal myers diffs.diff_test: A test rule that compares an output versus a golden file.namespace mbo::digest - principles and library docs: mbo/digest/README.md<algo>::Digest(std::string_view): constexpr-safe, spec-transcribed, vector-pinned message digests; one namespace per algorithm: sha224/sha256/sha384/sha512/sha512_224/sha512_256 (FIPS 180-4), sha3_224/sha3_256/sha3_384/sha3_512 (FIPS 202), blake2b/blake2b_256 (RFC 7693), blake3, and sha1/md5 (legacy interop only; collision-broken).shake128::Digest<N> / shake256::Digest<N>: the FIPS 202 XOFs - any output length (Algorithm<N> for a fixed size; different lengths share their prefix).blake3::DigestXof<N> / blake3::DigestKeyed / blake3::DeriveKey<N>: BLAKE3's XOF, keyed, and KDF modes (official-test-vector pinned).blake2b::Algorithm::DigestKeyed / StreamInitKeyed: BLAKE2b native keying (RFC 7693; keys up to 64 bytes) - BLAKE2 is its own MAC.IsDigestAlgorithm / HasStreaming: the algorithm plug-in contract (per-algorithm Algorithm structs).Streamer<Algo>: incremental digesting (Update(...).Update(...).Finalize(); peekable finalize), guaranteed equal to the one-shot value.Hmac<Algo> / class HmacStreamer<Algo>: HMAC (RFC 2104) over any streaming digest (HMAC-SHA3 uses rate-sized blocks per NIST).ToHexString(digest): lowercase hex, matching hexdigest()/sha256sum presentation.digest: checksum-style CLI, byte-compatible with sha256sum/shasum output; -a/--algorithm selects any library algorithm, -c/--check verifies checksum files (coreutils-interchangeable; --quiet, --status, --ignore_missing, --strict), --reverse swaps the columns, -d/--ignore_directories skips directories, - reads stdin.namespace mbo::filesArtefact: Holds information about a file (its data content, name, and modified time).GetContents: Reads a file and returns its contents or an absl::Status error.GetMTime: Returns the last update/modified time of a file or an absl::Status error.GetMaxLines: Reads at most given number of text lines from a file or returns absl::Status error.IsAbsolutePath: Returns whether a given path is absolute.JoinPaths: Join multiple path elements.JoinPathsRespectAbsolute: Join multiple path elements respecting absolute path elements.NormalizePath: Normalizes a path.Readable: Returns whether a file is readable or an absl::Status error.SetContents: Writes contents to a file.Glob2Re2Options: Control conversion of a glob pattern into a RE2 pattern.GlobEntry: Stores data for a single globbed entry (file, dir, etc.).GlobOptions: Options for functions Glob2Re2 and Glob2Re2Expression.GlobEntryAction: Allows GlobEntryFunc to control further glob progression.GlobEntryFunc: Callback for acceptable glob entries.GlobRe2: Performs recursive glob functionality using a RE2 pattern.Glob: Performs recursive glob functionality using a fnmatch style pattern.GlobSplit: Splits a pattern into root and pattern parts.glob: A recursive glob, see glob --help.IniFile: A simple INI file reader.namespace mbo::hash - principles and library docs: mbo/hash/README.mdGetHash64<Algo>(std::string_view, seed) / GetHash128<Algo>(std::string_view, seed): A constexpr-safe, non-cryptographic hash; the algorithms default to the in-house mumbo/jumbo family (mumbo for 64-bit, jumbo for the native 128-bit - both SMHasher3-clean, see mbo/hash/README.md) and can be replaced by any IsHashAlgorithm struct. Values are not stable across versions and not for persistence. Big-endian targets are supported by construction (byte-assembled loads) but not exercised by CI.GetHash32<Algo>(std::string_view, seed): 32-bit companion; uses an algorithm's native 32-bit variant where provided, else the XOR-fold of the 64-bit hash.HasGetHash32 / HasGetHash64 / HasGetHash128: Detect which static member functions an algorithm struct provides; IsHashAlgorithm requires a 64- or 128-bit one.Hasher<Algo>: Completes any IsHashAlgorithm struct into the full GetHash64/GetHash128/GetHash32 interface, synthesizing what is missing (fold for 64; two decorrelated passes for 128 -- the second skips the first up-to-8 bytes and injects them via the seed). Also a transparent functor over GetHash64, so it drops into absl/std hash containers with heterogeneous string_view lookup.mumbo::Algorithm, jumbo::Algorithm, murmur3::Algorithm, siphash::Algorithm, fnv1a::Algorithm, dumbo::Algorithm (plus rapidhash::Algorithm, xxh3::Algorithm, xxh64::Algorithm via hash_extra.h): the per-algorithm plug-ins for GetHash*<Algo> / Hasher<Algo>.Hash128: The 128-bit result type (h1, h2); ordered (<=>) and Abseil hash/stringify compatible.Hash128To64(Hash128): Folds a 128-bit hash into a well-mixed 64-bit one, e.g. Hash128To64(murmur3::GetHash128(data)).CombineHashes(uint64_t, uint64_t): Combines two hashes (order-dependent, well mixed).Hash64To32(uint64_t): Shrinks a hash to 32 bits by XOR-folding the halves (the correct default for all algorithms, incl. weak-low-bit ones like FNV-1a).HasStreaming / class Streamer<Algo>: incremental hashing (Update(...).Update(...).Finalize()), guaranteed equal to the one-shot value; provided by mumbo, xxh64, and siphash (rapidhash has no canonical streaming form).dumbo::GetHash64(std::string_view, seed): the legacy in-house hash (64-bit, weakly seeded, weak mixing; kept for comparison only - use GetHash64 / mumbo instead). Formerly mbo::hash::simple.fnv1a::GetHash64(std::string_view, seed): canonical FNV-1a 64 (constexpr-safe).xxh64::GetHash64(std::string_view, seed): canonical XXH64 / xxHash 64-bit (constexpr-safe; in hash_extra.h, see below).xxh3::GetHash64/GetHash128(std::string_view, seed): canonical XXH3 64- and 128-bit (modern xxHash generation, the fast file-checksum format; scalar; constexpr-safe; in hash_extra.h).murmur3::GetHash64/GetHash128(std::string_view, seed): canonical MurmurHash3 x64 128-bit (constexpr-safe; GetHash64 is the customary h1 truncation).rapidhash::GetHash64(std::string_view, seed): canonical rapidhash V3 (wyhash family; SMHasher3-clean; constexpr-safe; in hash_extra.h).mumbo::GetHash64 / jumbo::GetHash128 (mbo/hash/hash_mumbo.h): the in-house mumbo/jumbo family and default - widening-multiply ("MUM") based, SMHasher3 PASS 188/188 in both widths (the only clean native 128 measured), best mixed-length latency, streaming-capable, notice-free.siphash::GetHash64(std::string_view, key0, key1) / siphash::SipHash<C, D>(...): canonical SipHash-2-4 (and -1-3 via GetHash64Sip13) - keyed, hash-flooding resistant; adversarial protection requires a secret key.GetHash<Algo, Seed>(std::string_view): as GetHash64 but XORed with one build-selected constant, so values deliberately do not compare across independently configured builds (still constexpr).HashMangle(uint64_t): XORs the build-selected mangle constant into a hash; identity when built with --//mbo/hash:mangle_seed_buckets=0 (fully reproducible, GetHash == GetHash64).MangledHasher<Algo>: Hasher<Algo> extended with the mangled GetHash; the functor form applies the mangle.--//mbo/hash:mangle_seed: any printable-ASCII string (user name, release tag, date) selecting the mangle constant; folded - together with the module version from MODULE.bazel, so every release rotates the constant by construction - to a bucket inside the generation rule, so build caches converge. Only hash_mangle_cc dependents rebuild on rotation.--//mbo/hash:mangle_seed_buckets: bucket count bounding the variation (default 8); 0 disables the mangle (GetHash == GetHash64), 1 pins one stable constant across releases and seeds.rapidhash MIT; xxh64/xxh3 BSD-2-Clause) as an opt-in target: linking it requires shipping the repository-root NOTICE; the default hash_cc target is notice-free (see "Third-party components").namespace mbo::jsonJson: A JSON value/document that can be built from almost any structured type (see ConvertibleToJson) and serialized to JSON text.Json::SerializeMode: Selects kCompact, kLine, or kPretty JSON output.Json::Serialize: Returns the JSON value as a std::string.Json::Stream: Writes the JSON value to a std::ostream.ConvertibleToJson: Determines whether a value can be stored in a Json.namespace mbo::logDemangle to log de-mangled typeid names.LogTiming([args]) a simple timing logger.namespace mbo::mopeMOPE templating engine. Run bazel run //mbo/mope -- --help for detailed documentation.mope.Template: The mope template engine and data holder.ReadIniToTemplate: Helper to initialize a mope Template from an INI file.mope: A rule that expands a mope template file.mope_test: A test rule that compares mope template expansion against golden files. This
supports clang-format and thus can be used for source-code generation and verification.namespace mbo::statusStatusBuilder which allows to extend the message of an absl::Status.GetStatus allows to convert types to an absl::Status.MBO_ASSIGN_OR_RETURN: Macro that simplifies handling functions returning absl::StatusOr<T>.MBO_MOVE_TO_OR_RETURN: Macro that simplifies handling functions returning absl::StatusOr<T> where the result requires commas, in particular structured bindings.MBO_RETURN_IF_ERROR: Macro that simplifies handling functions returning absl::Status or absl::StausOr<T>.namespace mbo::stringsDropIndent: Converts a raw-string text block as if it had no indent.DropIndentAndSplit: Variant of DropIndent that returns the result as lines.BigNumber: Convert integral number to string with thousands separator.BigNumberLen: Calculate required string length for BigNumer.ParseString: Parses strings respecting C++ and custom escapes as well as quotes (all configurable).ParseStringList: Parses and splits strings respecting C++ and custom escapes as well as quotes (all configurable).AtLast: Allows `absl::StrSplit' to split on the last occurrence of a separator.ConsumePrefix: Removes a prefix from a std::string (like absl::ConsumePrefix).ConsumeSuffix: Removes a suffix from a std::string (like absl::ConsumeSuffix).StripPrefix: Removes a prefix from a std::string&& (like absl::StripPrefix).StripSuffix: Removes a suffix from a std::string&& (like absl::StripSuffix).StripCommentsArgs: Arguments for StripComments and StripLineComments.StripComments: Strips comments from lines.StripLineComments: Strips comments from a single line.StripParsedCommentsArgs: Arguments for StripParsedComments and StripParsedLineComments.StripParsedComments: Strips comments from parsed lines.StripLineParsedComments: Strips comments from a single parsed line.CapacityIs which checks the capacity of a container.EqualsText which compares text using line by line unified text diff.IsElementOf which checks that a value equals at least one element of a container — the element-on-the-left orientation of gmock's Contains. Subject types do not need to be converted to the container's value_type.IsKeyOf which checks that a value equals at least one key of a map (shorthand for "is this key in the map?").IsNullopt which compares its argument agains std::nullopt.IsValueOf which checks that a value equals at least one mapped value of a map (shorthand for "is this value in the map?").WhenTransformedBy which allows to compare containers after transforming them. This sometimes allows for much more concise comparisons where a golden expectation is already available that only differs in a simple transformation.WithDropIndent which modifies EqualsText so that DropIndent will be applied to the expected text.IsOk: Tests whether an absl::Status or absl::StatusOr is absl::OkStatus.IsOkAndHolds: Tests an absl::StatusOr for absl::OkStatus and contents.StatusIs: Tests an absl::Status or absl::StatusOr against a specific status code and message.StatusHasPayload: Tests whether an absl::Status or absl::StatusOr payload map has any payload, a specific payload url, or a payload url with specific content.StatusPayloads Tests whether an absl::Status or absl::StatusOr payload map matches.MBO_ASSERT_OK_AND_ASSIGN: Simplifies testing with functions that return absl::StatusOr<T>.MBO_ASSERT_OK_AND_MOVE_TO: Simplifies testing with functions that return absl::StatusOr<T> where the result requires commas, in particular structured bindings.namespace mbo::typesCases: Allows to switch types based on conditions.CaseIndex: Evaluates the first non zero case (1-based, 0 if all zero).IfThen: Helper type to generate if-then Cases types.IfElse: Helper type to generate else Cases which are always true and must go last.IfFalseThenVoid: Helper type that can be used to skip a case.IfTrueThenVoid: Helper type to inject default cases and to ensure the required type expansion is always possible.CompareArithmetic which cmpares two values that are scalar-numbers (including foat/double, excluding pointers and references).CompareFloat which can compare two float, double or long double values returning std::strong_ordering.CompareIntegral which compares two values that are integral-numbers (no float/double, no pointers, no references).CompareLess which is compatible to std::Less but allows container optimizations.CompareScalar which compares two values that are scalar-numbers (including float/double and pointers, excluding references).ThreeWayComparableTo which is similar to std::three_way_comparable_with but we only verify that L <=> R can be interpreted as Cat in the presented argument order.WeakToStrong which converts a std::weak_ordering to a std::strong_ordering.ContainerProxy which allows to add container access to other types including smart pointers of containers.Extend: Enables extending of struct/class types with basic functionality.ExtendNoDefault Like Extend but without default extender functionality.ExtendNoPrint Like Extend but without Printable and Streamable extender functionality.namespace extenderAbslStringify: Extender that injects functionality to make an Extended type work with abseil format/print functions. See Stringify for various API extension points.AbslHashable: Extender that injects functionality to make an Extended type work with abseil hashing (and also std::hash).Comparable: Extender that injects functionality to make an Extended type comparable. All comparators will be injected: <=>, ==, !=, <, <=, >, >=.Printable:Extended type get a std::string ToString() const function which can be used to convert a type into a std::string.{ 25, 42 }.{ .first = 25, .second = 42 }.Streamable: Extender that injects functionality to make an Extended type streamable. This allows the type to be used directly with std::ostreams.NoDestruct<T>: Implements a type that allows to use any type as a static constant.OpaquePtr an opaque alternative to std::unique_ptr which works with forward declared types.OpaqueValue an OpaquePtr with direct access, comparison and hashing which will not allow a nullptr.OpaqueContainer an OpaqueValue with direct container access.IsOptionalDataOrRef which determines whether a type is a OptionalDataOrRef.OptionalDataOrRef similar to std::optional but can hold std::nullopt, a type T or a reference T&/const T&.OptionalDataOrConstRef similar to std::optional but can hold std::nullopt, a type T or a const reference const T&.IsOptionalRef which determines whether a type is a OptionalRef.OptionalRef similar to std::optional but can hold std::nullopt or a reference T&/const T&.RefWrap<T>: similar to std::reference_wrapper but supports operators -> and *.Required<T>: similar to RefWrap but stores the actual type (and unlike std::optional cannot be reset).Stringify a utility to convert structs into strings.StringifyWithFieldNames a format control adapter for Stringify.StringifyFieldOptions which controls outer and inner options (both a const StringifyOptions&).StringifyOptions which can be used to control Stringify formatting.StringifyRootOptions which can be used to control outer/root options for streaming/printing structs.MboTypesStringifySupport which enables Stringify support even if not otherwise enabled (disables Abseil stringify support in Stringify).MboTypesStringifyConvert(I, T, V) allows to control conversion based on field types via a static call to the owning type, receiving the field index, the object and the field value.MboTypesStringifyDisable which disables Stringify support. This allows to prevent
complex classes (and more importantly fields of complex types) from being printed/streamed using StringifyMboTypesStringifyDoNotPrintFieldNames which if present disables field names in Stringify.MboTypesStringifyFieldNames which adds field names to Stringify.MboTypesStringifyOptions which adds full format control to Stringify.MboTypesStringifyValueAccess which allows to replace a struct with a single value in Stringify processing.std::ostream& operator<<(std::ostream&, const MboTypesStringifySupport auto& v) - conditioanl automatic ostream support for structs using Stringify.SetStringifyOstreamOutputMode which sets global Stringify stream options by mode.SetStringifyOstreamOptions which sets global Stringify stream options.ConstructibleFrom implements a variant of std::constructible_from that works around its limitations to deal with array args.ConstructibleInto determines whether one type can be constructed from another. Similar to std::convertible_to but with the argument order of std::constructible_from.ContainerConstIteratorValueType returned the value-type of the const_iterator of a container.ContainerIsForwardIteratable determines whether a types can be used in forward iteration.ContainerHasEmplace determines whether a container has emplace.ContainerHasEmplaceBack determines whether a container has emplace_back.ContainerHasInsert determines whether a container has insert.ContainerHasPushBack determines whether a container has push_back.ContainerHasForwardIterator determines whether a container has begin, end and std::forward_iterator compliant iterators.ContainerHasInputIterator determines whether a container has begin, end and std::input_iterator compliant iterators.GetDifferenceType is either set to the type's difference_type or std::ptrdiff_t.HasDifferenceType determines whether a type has a difference_type.IsAggregate determines whether a type is an aggregate.IsArithmetic uses std::is_arithmetic_v<T>.IsBracesConstructibleV determines whether a type can be constructed from given argument types.IsCharArray determines whether a type is a char* or char[] related type.IsDecomposable determines whether a type can be used in static-bindings.IsEmptyType determines whether a type is empty (calls std::is_empty_v).IsFloatingPoint determines whether a type is a floating point type (uses std::floating_point).IsInitializerList determines whether a type is `std::initializerIsScalar uses std::is_scalar_v<T>.IsOptional determines whether a type is a std::optional type.IsPair determines whether a type is a std::pair type.IsReferenceWrapper determines whether a type is a std::reference_wrapper.IsSameAsAnyOf which determines whether a type is the same as one of a list of types. Similar to IsSameAsAnyOfRaw but using exact types. The inversion is available as NotSameAsAnyOf.IsSameAsAnyOfRaw which determines whether a type is one of a list of types. Similar to IsSameAsAnyOf but applies std::remove_cvref_t on all types. The inversion is available as NotSameAsAnyOfRaw.IsScalar uses std::is_scalar_v<T>.IsSet determines whether a type is a std::set type.IsSmartPtr determines whether a type is a std::shared_ptr, std::unique_ptr or std::weak_ptr.IsSmartPtrImpl.IsStringKeyedContainer which determines whether a type is a container whose elements are pairs and whose keys are convertible to a std::string_view.IsTuple determines whether a type is a std::tuple type.IsVector determines whether a type is a std::vector type.BinarySearch implements templated binary search algorithm.LinearSearch implements templated linear search algorithm.ReverseSearch implements templated reverse linear search algorithm.MaxSearch implements templated linear search for last match algorithm.tstring: Implements type tstring a compile time string-literal type.operator"" _ts: String literal support for Clang, GCC and derived compilers.TupleCat which concatenates tuple types.TypedView a wrapper for STL views that provides type definitions, most importantly value_type. That allows such views to be used with GoogleTest container matchers.IsVariant determines whether a type is a std::variant type.IsVariantMemberType determine whether a Type is any of the types in a Variant.Overloaded which implements an Overload handler for std::visit(std::variant<...>) and std::variant::visit.This repository requires a C++20 compiler (in case of MacOS XCode 15 is needed). This is done so that newer features like std::source_location can be used.
The project only comes with a Bazel BUILD.bazel file and can be added to other Bazel projects.
The project is formatted with specific clang-format settings which require clang 16+ (in case of MacOs LLVM 16+ can be installed using brew). For simplicity in dev mode the project pulls the appropriate clang tools and can be compiled with those tools using bazel [build|test] --config=clang ....
Lint and format are driven by Trunk. Devs are required to install the CLI locally — curl https://get.trunk.io -fsSL | bash — then run trunk check and trunk fmt before pushing. The repo enables trunk-fmt-pre-commit and trunk-check-pre-push so the hooks run automatically once installed. CI runs trunk check only (no auto-fixing on the GitHub side); failing lint must be fixed locally and re-pushed.
Check Releases for details. All that is needed is a bazel_dep instruction with the correct version.
bazel_dep(name = "helly25_mbo", version = "0.0.0")
The Bazel-Central-Registry installation does not provide the LLVM tools and thus does not come with its own compiler — a restriction in how Bazel handles toolchains under bzlmod. To pull in the bundled toolchain, vendor bazelmod/llvm.MODULE.bazel as described in the release notes. Nonetheless all versions can be compiled with GCC 11+, Clang 17+ on Ubuntu and MacOs as enforced by CI. Other platforms and compilers are likely to work as well. However, Windows lacks some of the necessary tools and the library as well as its build system mostly assume Unix-style file and path names. That unfortunately means that on Windows some code cannot even be built.
Presented at C++ On Sea 2024, this presentation covers the theory behind:
mbo::hash::dumbo::GetHash64 (presented as mbo::hash::simple::GetHash),mbo::container::LimitedVector,mbo::container::LimitedMap, andmbo::container::LimitedSet.The hash and digest libraries contain constexpr transcriptions of third-party algorithms. The transcriptions are original code, but some closely follow their reference implementations; the repository-root NOTICE file reproduces the upstream notices, and the list below tracks exactly which headers and Bazel rules make it apply. The project itself is Apache-2.0 (see LICENSE).
NOTICE entries required for license compliance - for these algorithms the licensed reference implementation effectively is the specification, and the transcription follows its expression:
| Header | Bazel rule | Upstream | License |
|---|---|---|---|
| mbo/hash/hash_rapidhash.h | //mbo/hash:hash_extra_cc | rapidhash | MIT |
| mbo/hash/hash_xxh64.h, mbo/hash/hash_xxh3.h | //mbo/hash:hash_extra_cc | xxHash | BSD-2-Clause |
NOTICE entries that are courtesy attribution only - public-domain/CC0 upstreams with no notice obligation, recorded for provenance (and to preempt license-scanner findings of structural similarity):
| Header | Bazel rule | Upstream | License |
|---|---|---|---|
| mbo/hash/hash_murmur3.h | //mbo/hash:hash_cc | MurmurHash3 | public domain |
| mbo/hash/hash_siphash.h | //mbo/hash:hash_cc | SipHash | CC0 / public domain |
| mbo/hash/hash_fnv1a.h | //mbo/hash:hash_cc | FNV-1a | public domain |
| mbo/digest/digest_blake3.h | //mbo/digest:digest_cc | BLAKE3 | CC0-1.0 OR Apache-2.0 (CC0 elected) |
Everything else is original helly25 code. In particular, all algorithms
implemented from public standards carry no upstream code and need no notices:
SHA-1/SHA-2/SHA-3/SHAKE (FIPS 180-4 / FIPS 202), MD5 (RFC 1321), BLAKE2b
(RFC 7693), and HMAC (RFC 2104), and the default hash algorithms (the
in-house mumbo/jumbo family) are original code. Practical rule: only a
distribution that includes code from //mbo/hash:hash_extra_cc - directly or
transitively - must retain NOTICE; the default //mbo/hash:hash_cc
and //mbo/digest:digest_cc carry no compliance obligation (the digest
library's only NOTICE entry is courtesy).
MBO, a C++20 library: This C++20 library provides some general useful building blocks and integrates with Google's Abseil library.
@helly25/mbo0.13.1 +21h2026-07-12 | |
0.13.0 +14d2026-07-12 | |
0.12.0 +8d2026-06-27 | |
0.11.1 +3d2026-06-19 | |
0.11.0 +7.1mo2026-06-16 | |
0.10.0 +5.5mo2025-11-15 | |
0.9.0 +28d2025-06-04 | |
0.8.0 +4d2025-05-06 | |
0.7.0 +1.1mo2025-05-02 | |
0.6.0 +5d2025-03-29 | |
0.5.0 +12d2025-03-23 | |
0.4.4 +5d2025-03-10 | |
0.4.3 +19h2025-03-05 | |
0.4.2 +20h2025-03-04 | |
0.4.1 +7d2025-03-03 | |
0.4.0-rc.12025-02-24 |