tigerbeetle 0.0.34 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/ext/tb_client/extconf.rb +13 -13
- data/ext/tb_client/tigerbeetle/LICENSE +177 -0
- data/ext/tb_client/tigerbeetle/build.zig +2327 -0
- data/ext/tb_client/tigerbeetle/src/aof.zig +1000 -0
- data/ext/tb_client/tigerbeetle/src/build_multiversion.zig +808 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/protocol.zig +1283 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/spec.zig +1704 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/types.zig +341 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp.zig +1450 -0
- data/ext/tb_client/tigerbeetle/src/cdc/runner.zig +1659 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/samples/main.c +406 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/context.zig +1084 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/echo_client.zig +286 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/packet.zig +158 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal.zig +229 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal_fuzz.zig +110 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_exports.zig +281 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header.zig +312 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header_test.zig +138 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/test.zig +466 -0
- data/ext/tb_client/tigerbeetle/src/clients/docs_samples.zig +157 -0
- data/ext/tb_client/tigerbeetle/src/clients/docs_types.zig +90 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/ci.zig +203 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/docs.zig +79 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/dotnet_bindings.zig +542 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/ci.zig +109 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/docs.zig +86 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/go_bindings.zig +370 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/pkg/native/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/ci.zig +167 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/docs.zig +126 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/java_bindings.zig +996 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/client.zig +748 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni.zig +3238 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_tests.zig +1718 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_thread_cleaner.zig +190 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/ci.zig +104 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/docs.zig +75 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/node.zig +522 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/node_bindings.zig +267 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/src/c.zig +3 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/src/translate.zig +379 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/ci.zig +131 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/docs.zig +63 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/python_bindings.zig +588 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/assets/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/ci.zig +73 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/docs.zig +106 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/rust_bindings.zig +305 -0
- data/ext/tb_client/tigerbeetle/src/config.zig +296 -0
- data/ext/tb_client/tigerbeetle/src/constants.zig +790 -0
- data/ext/tb_client/tigerbeetle/src/copyhound.zig +202 -0
- data/ext/tb_client/tigerbeetle/src/counting_allocator.zig +72 -0
- data/ext/tb_client/tigerbeetle/src/direction.zig +11 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/build.zig +158 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/content.zig +156 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/docs.zig +252 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/file_checker.zig +313 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/html.zig +87 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/page_writer.zig +63 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/redirects.zig +47 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/search_index_writer.zig +28 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/service_worker_writer.zig +61 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/single_page_writer.zig +169 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/website.zig +46 -0
- data/ext/tb_client/tigerbeetle/src/ewah.zig +445 -0
- data/ext/tb_client/tigerbeetle/src/ewah_benchmark.zig +128 -0
- data/ext/tb_client/tigerbeetle/src/ewah_fuzz.zig +171 -0
- data/ext/tb_client/tigerbeetle/src/fuzz_tests.zig +179 -0
- data/ext/tb_client/tigerbeetle/src/integration_tests.zig +662 -0
- data/ext/tb_client/tigerbeetle/src/io/common.zig +155 -0
- data/ext/tb_client/tigerbeetle/src/io/darwin.zig +1093 -0
- data/ext/tb_client/tigerbeetle/src/io/linux.zig +1880 -0
- data/ext/tb_client/tigerbeetle/src/io/test.zig +1005 -0
- data/ext/tb_client/tigerbeetle/src/io/windows.zig +1598 -0
- data/ext/tb_client/tigerbeetle/src/io.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/iops.zig +134 -0
- data/ext/tb_client/tigerbeetle/src/list.zig +236 -0
- data/ext/tb_client/tigerbeetle/src/lsm/binary_search.zig +848 -0
- data/ext/tb_client/tigerbeetle/src/lsm/binary_search_benchmark.zig +179 -0
- data/ext/tb_client/tigerbeetle/src/lsm/cache_map.zig +424 -0
- data/ext/tb_client/tigerbeetle/src/lsm/cache_map_fuzz.zig +420 -0
- data/ext/tb_client/tigerbeetle/src/lsm/compaction.zig +2117 -0
- data/ext/tb_client/tigerbeetle/src/lsm/composite_key.zig +182 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest.zig +1119 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest_fuzz.zig +1102 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest_table_iterator.zig +200 -0
- data/ext/tb_client/tigerbeetle/src/lsm/groove.zig +1495 -0
- data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge.zig +739 -0
- data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge_benchmark.zig +166 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest.zig +754 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_level.zig +1294 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_level_fuzz.zig +510 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_log.zig +1263 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_log_fuzz.zig +628 -0
- data/ext/tb_client/tigerbeetle/src/lsm/node_pool.zig +247 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_buffer.zig +116 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_builder.zig +543 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_fuzz.zig +938 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_lookup.zig +293 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_merge.zig +362 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_range.zig +99 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_state.zig +17 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_tree.zig +1036 -0
- data/ext/tb_client/tigerbeetle/src/lsm/schema.zig +617 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scratch_memory.zig +84 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array.zig +1500 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_benchmark.zig +149 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_fuzz.zig +7 -0
- data/ext/tb_client/tigerbeetle/src/lsm/set_associative_cache.zig +865 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table.zig +607 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table_memory.zig +843 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table_value_iterator.zig +105 -0
- data/ext/tb_client/tigerbeetle/src/lsm/timestamp_range.zig +40 -0
- data/ext/tb_client/tigerbeetle/src/lsm/tree.zig +630 -0
- data/ext/tb_client/tigerbeetle/src/lsm/tree_fuzz.zig +933 -0
- data/ext/tb_client/tigerbeetle/src/lsm/zig_zag_merge.zig +557 -0
- data/ext/tb_client/tigerbeetle/src/message_buffer.zig +469 -0
- data/ext/tb_client/tigerbeetle/src/message_bus.zig +1214 -0
- data/ext/tb_client/tigerbeetle/src/message_bus_fuzz.zig +936 -0
- data/ext/tb_client/tigerbeetle/src/message_pool.zig +343 -0
- data/ext/tb_client/tigerbeetle/src/multiversion.zig +2195 -0
- data/ext/tb_client/tigerbeetle/src/queue.zig +390 -0
- data/ext/tb_client/tigerbeetle/src/repl/completion.zig +201 -0
- data/ext/tb_client/tigerbeetle/src/repl/parser.zig +1356 -0
- data/ext/tb_client/tigerbeetle/src/repl/terminal.zig +496 -0
- data/ext/tb_client/tigerbeetle/src/repl.zig +1034 -0
- data/ext/tb_client/tigerbeetle/src/scripts/amqp.zig +973 -0
- data/ext/tb_client/tigerbeetle/src/scripts/cfo.zig +1866 -0
- data/ext/tb_client/tigerbeetle/src/scripts/changelog.zig +304 -0
- data/ext/tb_client/tigerbeetle/src/scripts/ci.zig +227 -0
- data/ext/tb_client/tigerbeetle/src/scripts/client_readmes.zig +658 -0
- data/ext/tb_client/tigerbeetle/src/scripts/devhub.zig +466 -0
- data/ext/tb_client/tigerbeetle/src/scripts/release.zig +1058 -0
- data/ext/tb_client/tigerbeetle/src/scripts.zig +105 -0
- data/ext/tb_client/tigerbeetle/src/shell.zig +1195 -0
- data/ext/tb_client/tigerbeetle/src/stack.zig +260 -0
- data/ext/tb_client/tigerbeetle/src/state_machine/auditor.zig +911 -0
- data/ext/tb_client/tigerbeetle/src/state_machine/workload.zig +2079 -0
- data/ext/tb_client/tigerbeetle/src/state_machine.zig +4872 -0
- data/ext/tb_client/tigerbeetle/src/state_machine_fuzz.zig +288 -0
- data/ext/tb_client/tigerbeetle/src/state_machine_tests.zig +3128 -0
- data/ext/tb_client/tigerbeetle/src/static_allocator.zig +82 -0
- data/ext/tb_client/tigerbeetle/src/stdx/bit_set.zig +157 -0
- data/ext/tb_client/tigerbeetle/src/stdx/bounded_array.zig +292 -0
- data/ext/tb_client/tigerbeetle/src/stdx/debug.zig +65 -0
- data/ext/tb_client/tigerbeetle/src/stdx/flags.zig +1414 -0
- data/ext/tb_client/tigerbeetle/src/stdx/mlock.zig +92 -0
- data/ext/tb_client/tigerbeetle/src/stdx/prng.zig +677 -0
- data/ext/tb_client/tigerbeetle/src/stdx/radix.zig +336 -0
- data/ext/tb_client/tigerbeetle/src/stdx/ring_buffer.zig +511 -0
- data/ext/tb_client/tigerbeetle/src/stdx/sort_test.zig +112 -0
- data/ext/tb_client/tigerbeetle/src/stdx/stdx.zig +1160 -0
- data/ext/tb_client/tigerbeetle/src/stdx/testing/low_level_hash_vectors.zig +142 -0
- data/ext/tb_client/tigerbeetle/src/stdx/testing/snaptest.zig +361 -0
- data/ext/tb_client/tigerbeetle/src/stdx/time_units.zig +275 -0
- data/ext/tb_client/tigerbeetle/src/stdx/unshare.zig +295 -0
- data/ext/tb_client/tigerbeetle/src/stdx/vendored/aegis.zig +436 -0
- data/ext/tb_client/tigerbeetle/src/stdx/windows.zig +48 -0
- data/ext/tb_client/tigerbeetle/src/stdx/zipfian.zig +402 -0
- data/ext/tb_client/tigerbeetle/src/storage.zig +489 -0
- data/ext/tb_client/tigerbeetle/src/storage_fuzz.zig +180 -0
- data/ext/tb_client/tigerbeetle/src/testing/bench.zig +146 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/grid_checker.zig +53 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/journal_checker.zig +61 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/manifest_checker.zig +76 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/message_bus.zig +110 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/network.zig +412 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/state_checker.zig +331 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/storage_checker.zig +458 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster.zig +1198 -0
- data/ext/tb_client/tigerbeetle/src/testing/exhaustigen.zig +128 -0
- data/ext/tb_client/tigerbeetle/src/testing/fixtures.zig +181 -0
- data/ext/tb_client/tigerbeetle/src/testing/fuzz.zig +144 -0
- data/ext/tb_client/tigerbeetle/src/testing/id.zig +97 -0
- data/ext/tb_client/tigerbeetle/src/testing/io.zig +317 -0
- data/ext/tb_client/tigerbeetle/src/testing/marks.zig +126 -0
- data/ext/tb_client/tigerbeetle/src/testing/packet_simulator.zig +533 -0
- data/ext/tb_client/tigerbeetle/src/testing/reply_sequence.zig +154 -0
- data/ext/tb_client/tigerbeetle/src/testing/state_machine.zig +389 -0
- data/ext/tb_client/tigerbeetle/src/testing/storage.zig +1247 -0
- data/ext/tb_client/tigerbeetle/src/testing/table.zig +249 -0
- data/ext/tb_client/tigerbeetle/src/testing/time.zig +98 -0
- data/ext/tb_client/tigerbeetle/src/testing/tmp_tigerbeetle.zig +212 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/constants.zig +26 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/faulty_network.zig +580 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/java_driver/ci.zig +39 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/logged_process.zig +214 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/rust_driver/ci.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/supervisor.zig +766 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/workload.zig +543 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/zig_driver.zig +181 -0
- data/ext/tb_client/tigerbeetle/src/tidy.zig +1448 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_driver.zig +227 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_load.zig +1069 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/cli.zig +1422 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect.zig +1658 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect_integrity.zig +518 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/libtb_client.zig +36 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/main.zig +646 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle.zig +958 -0
- data/ext/tb_client/tigerbeetle/src/time.zig +236 -0
- data/ext/tb_client/tigerbeetle/src/trace/event.zig +745 -0
- data/ext/tb_client/tigerbeetle/src/trace/statsd.zig +462 -0
- data/ext/tb_client/tigerbeetle/src/trace.zig +556 -0
- data/ext/tb_client/tigerbeetle/src/unit_tests.zig +321 -0
- data/ext/tb_client/tigerbeetle/src/vopr.zig +1785 -0
- data/ext/tb_client/tigerbeetle/src/vortex.zig +101 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checkpoint_trailer.zig +473 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checksum.zig +208 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checksum_benchmark.zig +43 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client.zig +768 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client_replies.zig +532 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client_sessions.zig +338 -0
- data/ext/tb_client/tigerbeetle/src/vsr/clock.zig +1019 -0
- data/ext/tb_client/tigerbeetle/src/vsr/fault_detector.zig +279 -0
- data/ext/tb_client/tigerbeetle/src/vsr/free_set.zig +1381 -0
- data/ext/tb_client/tigerbeetle/src/vsr/free_set_fuzz.zig +315 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid.zig +1460 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid_blocks_missing.zig +757 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid_scrubber.zig +797 -0
- data/ext/tb_client/tigerbeetle/src/vsr/journal.zig +2586 -0
- data/ext/tb_client/tigerbeetle/src/vsr/marzullo.zig +308 -0
- data/ext/tb_client/tigerbeetle/src/vsr/message_header.zig +1777 -0
- data/ext/tb_client/tigerbeetle/src/vsr/multi_batch.zig +715 -0
- data/ext/tb_client/tigerbeetle/src/vsr/multi_batch_fuzz.zig +185 -0
- data/ext/tb_client/tigerbeetle/src/vsr/repair_budget.zig +333 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica.zig +12355 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_format.zig +416 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_reformat.zig +165 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_test.zig +2910 -0
- data/ext/tb_client/tigerbeetle/src/vsr/routing.zig +1075 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock.zig +1603 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_fuzz.zig +484 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums.zig +405 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +355 -0
- data/ext/tb_client/tigerbeetle/src/vsr/sync.zig +29 -0
- data/ext/tb_client/tigerbeetle/src/vsr.zig +1727 -0
- data/lib/tb_client/shared_lib.rb +12 -5
- data/lib/tigerbeetle/client.rb +1 -1
- data/lib/tigerbeetle/platforms.rb +9 -0
- data/lib/tigerbeetle/version.rb +2 -2
- data/tigerbeetle.gemspec +22 -5
- metadata +242 -3
- data/ext/tb_client/pkg.tar.gz +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
//! Analyze LLVM IR to find:
|
|
2
|
+
//! - large memcpy calls
|
|
3
|
+
//! - functions with many copies due to monomorphisation and big total size
|
|
4
|
+
//!
|
|
5
|
+
//! To get a file with IR, use `-femit-llvm-ir` cli argument for `zig build-exe` or
|
|
6
|
+
//!
|
|
7
|
+
//! $ zig build -Drelease -Demit-llvm-ir
|
|
8
|
+
//!
|
|
9
|
+
//! Pass the resulting .ll file to copyhound on stdin.
|
|
10
|
+
//!
|
|
11
|
+
//! ## Needless memcpy
|
|
12
|
+
//!
|
|
13
|
+
//! Run:
|
|
14
|
+
//!
|
|
15
|
+
//! $ zig run -OReleaseSafe src/copyhound.zig -- memcpy --bytes 128 < tigerbeetle.ll \
|
|
16
|
+
//! | sort -n -k 2
|
|
17
|
+
//!
|
|
18
|
+
//! This only detects memory copies with comptime-know size (eg, when you copy a `T`, rather than a
|
|
19
|
+
//! `[]T`).
|
|
20
|
+
//!
|
|
21
|
+
//! ## Code size
|
|
22
|
+
//!
|
|
23
|
+
//! Run:
|
|
24
|
+
//!
|
|
25
|
+
//! $ zig run -OReleaseSafe src/copyhound.zig -- funcsize < tigerbeetle.ll \
|
|
26
|
+
//! | awk '{a[$1] += $2; b[$1] += 1} END {for (i in a) print i, b[i], a[i]}' \
|
|
27
|
+
//! | sort -n -k 3
|
|
28
|
+
//!
|
|
29
|
+
//! This will print every function name (first column), number of times it was monomorphized (second
|
|
30
|
+
//! column) and the total size of all monorphisations (third column).
|
|
31
|
+
|
|
32
|
+
const std = @import("std");
|
|
33
|
+
const stdx = @import("stdx");
|
|
34
|
+
|
|
35
|
+
const MiB = stdx.MiB;
|
|
36
|
+
|
|
37
|
+
const log = std.log;
|
|
38
|
+
pub const std_options = .{
|
|
39
|
+
.log_level = .info,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const CLIArgs = union(enum) {
|
|
43
|
+
memcpy: struct { bytes: u32 },
|
|
44
|
+
funcsize,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
pub fn main() !void {
|
|
48
|
+
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
49
|
+
var arena = std.heap.ArenaAllocator.init(gpa.allocator());
|
|
50
|
+
defer arena.deinit();
|
|
51
|
+
|
|
52
|
+
const allocator = arena.allocator();
|
|
53
|
+
|
|
54
|
+
var args = try std.process.argsWithAllocator(allocator);
|
|
55
|
+
|
|
56
|
+
const cli_args = stdx.flags(&args, CLIArgs);
|
|
57
|
+
|
|
58
|
+
const line_buffer = try allocator.alloc(u8, MiB);
|
|
59
|
+
const func_buf = try allocator.alloc(u8, 4096);
|
|
60
|
+
|
|
61
|
+
const stdin = std.io.getStdIn();
|
|
62
|
+
var buf_reader = std.io.bufferedReader(stdin.reader());
|
|
63
|
+
var in_stream = buf_reader.reader();
|
|
64
|
+
|
|
65
|
+
const stdout = std.io.getStdOut();
|
|
66
|
+
var buf_writer = std.io.bufferedWriter(stdout.writer());
|
|
67
|
+
defer buf_writer.flush() catch {};
|
|
68
|
+
|
|
69
|
+
var out_stream = buf_writer.writer();
|
|
70
|
+
|
|
71
|
+
var current_function: ?[]const u8 = null;
|
|
72
|
+
var current_function_size: u32 = 0;
|
|
73
|
+
while (try in_stream.readUntilDelimiterOrEof(line_buffer, '\n')) |line| {
|
|
74
|
+
if (std.mem.startsWith(u8, line, "define ")) {
|
|
75
|
+
current_function = extract_function_name(line, func_buf) orelse {
|
|
76
|
+
log.err("can't parse define line={s}", .{line});
|
|
77
|
+
return error.BadDefine;
|
|
78
|
+
};
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (current_function) |function| {
|
|
83
|
+
if (std.mem.eql(u8, line, "}")) {
|
|
84
|
+
if (cli_args == .funcsize) {
|
|
85
|
+
try out_stream.print("{s} {}\n", .{ function, current_function_size });
|
|
86
|
+
}
|
|
87
|
+
current_function = null;
|
|
88
|
+
current_function_size = 0;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
current_function_size += 1;
|
|
92
|
+
if (stdx.cut(line, "@llvm.memcpy")) |cut| {
|
|
93
|
+
const size = extract_memcpy_size(cut.suffix) orelse {
|
|
94
|
+
log.err("can't parse memcpy call line={s}", .{line});
|
|
95
|
+
return error.BadMemcpy;
|
|
96
|
+
};
|
|
97
|
+
if (cli_args == .memcpy) {
|
|
98
|
+
if (size > cli_args.memcpy.bytes) {
|
|
99
|
+
try out_stream.print("{s} {}\n", .{ function, size });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// Demangles function name by removing all comptime arguments (which are always inside `()`).
|
|
108
|
+
fn extract_function_name(define: []const u8, buf: []u8) ?[]const u8 {
|
|
109
|
+
if (!std.mem.endsWith(u8, define, "{")) return null;
|
|
110
|
+
|
|
111
|
+
_, const mangled_name = stdx.cut(define, "@") orelse return null;
|
|
112
|
+
var buf_count: usize = 0;
|
|
113
|
+
var level: u32 = 0;
|
|
114
|
+
for (mangled_name) |c| {
|
|
115
|
+
switch (c) {
|
|
116
|
+
'(' => level += 1,
|
|
117
|
+
')' => level -= 1,
|
|
118
|
+
'"' => {},
|
|
119
|
+
else => {
|
|
120
|
+
if (level > 0) continue;
|
|
121
|
+
if (c == ' ') return buf[0..buf_count];
|
|
122
|
+
if (buf_count == buf.len) return null;
|
|
123
|
+
buf[buf_count] = c;
|
|
124
|
+
buf_count += 1;
|
|
125
|
+
},
|
|
126
|
+
}
|
|
127
|
+
} else return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
test "extract_function_name" {
|
|
131
|
+
var buf: [1024]u8 = undefined;
|
|
132
|
+
const func_name = extract_function_name(
|
|
133
|
+
\\define internal fastcc i64 @".vsr.vsr.clock.ClockType(.vsr.time.Time).monotonic"
|
|
134
|
+
++
|
|
135
|
+
\\(%.vsr.time.Time* %.0.1.val) unnamed_addr #1 !dbg !71485 {
|
|
136
|
+
, &buf).?;
|
|
137
|
+
try std.testing.expectEqualStrings(".vsr.vsr.clock.ClockType.monotonic", func_name);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/// Parses out the size argument of an memcpy call.
|
|
141
|
+
fn extract_memcpy_size(memcpy_call: []const u8) ?u32 {
|
|
142
|
+
_, const call_args = stdx.cut(memcpy_call, "(") orelse return null;
|
|
143
|
+
var level: u32 = 0;
|
|
144
|
+
var arg_count: u32 = 0;
|
|
145
|
+
|
|
146
|
+
const args_after_size = for (call_args, 0..) |c, i| {
|
|
147
|
+
switch (c) {
|
|
148
|
+
'(' => level += 1,
|
|
149
|
+
')' => level -= 1,
|
|
150
|
+
',' => {
|
|
151
|
+
if (level > 0) continue;
|
|
152
|
+
arg_count += 1;
|
|
153
|
+
if (!std.mem.startsWith(u8, call_args[i..], ", ")) return null;
|
|
154
|
+
if (arg_count == 2) break call_args[i + 2 ..];
|
|
155
|
+
},
|
|
156
|
+
else => {},
|
|
157
|
+
}
|
|
158
|
+
} else return null;
|
|
159
|
+
|
|
160
|
+
const size_arg, _ = stdx.cut(args_after_size, ",") orelse return null;
|
|
161
|
+
|
|
162
|
+
_, const size_value = stdx.cut(size_arg, " ") orelse return null;
|
|
163
|
+
|
|
164
|
+
// Runtime-known memcpy size, assume that's OK.
|
|
165
|
+
if (std.mem.startsWith(u8, size_value, "%")) return 0;
|
|
166
|
+
|
|
167
|
+
return std.fmt.parseInt(u32, size_value, 10) catch null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
test "extract_memcpy_size" {
|
|
171
|
+
const T = struct {
|
|
172
|
+
fn check(
|
|
173
|
+
line: []const u8,
|
|
174
|
+
want: ?u32,
|
|
175
|
+
) !void {
|
|
176
|
+
const got = extract_memcpy_size(line);
|
|
177
|
+
try std.testing.expectEqual(want, got);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// One argument is a nested expression with a function call.
|
|
182
|
+
try T.check(
|
|
183
|
+
" call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %0, i8* align 8 bitcast(" ++
|
|
184
|
+
"{ void (i32, %std.os.linux.siginfo_t*, i8*)*," ++
|
|
185
|
+
" [32 x i32], <{ i32, [4 x i8] }>, void ()* }*" ++
|
|
186
|
+
" @8 to i8*), i64 152, i1 false)",
|
|
187
|
+
152,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// The argument is `%6` --- a runtime value.
|
|
191
|
+
try T.check(
|
|
192
|
+
\\ call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %8, i8* align 1 %4, i64 %6, i1 false)
|
|
193
|
+
, 0);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// Format and print an error message followed by the usage string to stderr,
|
|
197
|
+
/// then exit with an exit code of 1.
|
|
198
|
+
pub fn fatal(comptime fmt_string: []const u8, args: anytype) noreturn {
|
|
199
|
+
const stderr = std.io.getStdErr().writer();
|
|
200
|
+
stderr.print("error: " ++ fmt_string ++ "\n", args) catch {};
|
|
201
|
+
std.posix.exit(1);
|
|
202
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const Alignment = std.mem.Alignment;
|
|
3
|
+
|
|
4
|
+
const CountingAllocator = @This();
|
|
5
|
+
|
|
6
|
+
parent_allocator: std.mem.Allocator,
|
|
7
|
+
alloc_size: u64 = 0,
|
|
8
|
+
free_size: u64 = 0,
|
|
9
|
+
|
|
10
|
+
pub fn init(parent_allocator: std.mem.Allocator) CountingAllocator {
|
|
11
|
+
return .{ .parent_allocator = parent_allocator };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn deinit(self: *CountingAllocator) void {
|
|
15
|
+
self.* = undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn allocator(self: *CountingAllocator) std.mem.Allocator {
|
|
19
|
+
return .{
|
|
20
|
+
.ptr = self,
|
|
21
|
+
.vtable = &.{
|
|
22
|
+
.alloc = alloc,
|
|
23
|
+
.resize = resize,
|
|
24
|
+
.remap = remap,
|
|
25
|
+
.free = free,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pub fn live_size(self: *CountingAllocator) u64 {
|
|
31
|
+
return self.alloc_size - self.free_size;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fn alloc(ctx: *anyopaque, len: usize, ptr_align: Alignment, ret_addr: usize) ?[*]u8 {
|
|
35
|
+
const self: *CountingAllocator = @ptrCast(@alignCast(ctx));
|
|
36
|
+
self.alloc_size += len;
|
|
37
|
+
return self.parent_allocator.rawAlloc(len, ptr_align, ret_addr);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn resize(ctx: *anyopaque, buf: []u8, buf_align: Alignment, new_len: usize, ret_addr: usize) bool {
|
|
41
|
+
const self: *CountingAllocator = @ptrCast(@alignCast(ctx));
|
|
42
|
+
|
|
43
|
+
if (self.parent_allocator.rawResize(buf, buf_align, new_len, ret_addr)) {
|
|
44
|
+
if (new_len > buf.len) {
|
|
45
|
+
self.alloc_size += new_len - buf.len;
|
|
46
|
+
} else {
|
|
47
|
+
self.free_size += buf.len - new_len;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
} else {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fn remap(ctx: *anyopaque, buf: []u8, buf_align: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 {
|
|
56
|
+
const self: *CountingAllocator = @ptrCast(@alignCast(ctx));
|
|
57
|
+
if (self.parent_allocator.rawRemap(buf, buf_align, new_len, ret_addr)) |remapped| {
|
|
58
|
+
if (new_len > buf.len) {
|
|
59
|
+
self.alloc_size += new_len - buf.len;
|
|
60
|
+
} else {
|
|
61
|
+
self.free_size += buf.len - new_len;
|
|
62
|
+
}
|
|
63
|
+
return remapped;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fn free(ctx: *anyopaque, buf: []u8, buf_align: Alignment, ret_addr: usize) void {
|
|
69
|
+
const self: *CountingAllocator = @ptrCast(@alignCast(ctx));
|
|
70
|
+
self.free_size += buf.len;
|
|
71
|
+
return self.parent_allocator.rawFree(buf, buf_align, ret_addr);
|
|
72
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const Website = @import("src/website.zig").Website;
|
|
3
|
+
const docs = @import("src/docs.zig");
|
|
4
|
+
const redirects = @import("src/redirects.zig");
|
|
5
|
+
|
|
6
|
+
pub const exclude_extensions: []const []const u8 = &.{
|
|
7
|
+
".DS_Store",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
pub fn build(b: *std.Build) !void {
|
|
11
|
+
const url_prefix: []const u8 = b.option(
|
|
12
|
+
[]const u8,
|
|
13
|
+
"url_prefix",
|
|
14
|
+
"Prefix links with this string",
|
|
15
|
+
) orelse "";
|
|
16
|
+
|
|
17
|
+
const git_commit = b.option(
|
|
18
|
+
[]const u8,
|
|
19
|
+
"git-commit",
|
|
20
|
+
"The git commit revision of the source code.",
|
|
21
|
+
) orelse std.mem.trimRight(u8, b.run(&.{ "git", "rev-parse", "--verify", "HEAD" }), "\n");
|
|
22
|
+
|
|
23
|
+
const pandoc_bin = get_pandoc_bin(b) orelse return;
|
|
24
|
+
const vale_bin = get_vale_bin(b) orelse return;
|
|
25
|
+
|
|
26
|
+
const check_spelling = std.Build.Step.Run.create(b, "run vale");
|
|
27
|
+
hide_stdout(check_spelling);
|
|
28
|
+
check_spelling.addFileArg(vale_bin);
|
|
29
|
+
const md_files = b.run(&.{ "git", "ls-files", "../../**/*.md" });
|
|
30
|
+
var md_files_iter = std.mem.tokenizeScalar(u8, md_files, '\n');
|
|
31
|
+
while (md_files_iter.next()) |md_file| {
|
|
32
|
+
check_spelling.addFileArg(b.path(md_file));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const content = b.addWriteFiles();
|
|
36
|
+
{ //TODO(zig): https://github.com/ziglang/zig/issues/20571
|
|
37
|
+
var dir = try b.build_root.handle.openDir("assets", .{ .iterate = true });
|
|
38
|
+
defer dir.close();
|
|
39
|
+
|
|
40
|
+
var walker = try dir.walk(b.allocator);
|
|
41
|
+
defer walker.deinit();
|
|
42
|
+
|
|
43
|
+
while (try walker.next()) |entry| {
|
|
44
|
+
if (entry.kind == .file) {
|
|
45
|
+
if (std.mem.eql(u8, entry.basename, ".DS_Store")) continue;
|
|
46
|
+
const source = b.path("assets").path(b, entry.path);
|
|
47
|
+
_ = content.addCopyFile(source, entry.path);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
content.step.dependOn(&check_spelling.step);
|
|
53
|
+
|
|
54
|
+
const website = Website.init(b, url_prefix, pandoc_bin);
|
|
55
|
+
try docs.build(b, content, website);
|
|
56
|
+
try redirects.build(b, content, website);
|
|
57
|
+
|
|
58
|
+
const clean_zigout_step = b.addRemoveDirTree(b.path("zig-out"));
|
|
59
|
+
|
|
60
|
+
const install_content_step = b.addInstallDirectory(.{
|
|
61
|
+
.source_dir = content.getDirectory(),
|
|
62
|
+
.install_dir = .prefix,
|
|
63
|
+
.install_subdir = ".",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
install_content_step.step.dependOn(&clean_zigout_step.step);
|
|
67
|
+
|
|
68
|
+
const service_worker_writer = b.addRunArtifact(b.addExecutable(.{
|
|
69
|
+
.name = "service_worker_writer",
|
|
70
|
+
.root_source_file = b.path("src/service_worker_writer.zig"),
|
|
71
|
+
.target = b.graph.host,
|
|
72
|
+
}));
|
|
73
|
+
service_worker_writer.addArgs(&.{ url_prefix, git_commit });
|
|
74
|
+
service_worker_writer.addDirectoryArg(content.getDirectory());
|
|
75
|
+
|
|
76
|
+
const service_worker = service_worker_writer.captureStdOut();
|
|
77
|
+
|
|
78
|
+
const file_checker = b.addRunArtifact(b.addExecutable(.{
|
|
79
|
+
.name = "file_checker",
|
|
80
|
+
.root_source_file = b.path("src/file_checker.zig"),
|
|
81
|
+
.target = b.graph.host,
|
|
82
|
+
}));
|
|
83
|
+
file_checker.addArg("zig-out");
|
|
84
|
+
|
|
85
|
+
file_checker.step.dependOn(&install_content_step.step);
|
|
86
|
+
file_checker.step.dependOn(&b.addInstallFile(service_worker, "service-worker.js").step);
|
|
87
|
+
|
|
88
|
+
b.getInstallStep().dependOn(&file_checker.step);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fn get_pandoc_bin(b: *std.Build) ?std.Build.LazyPath {
|
|
92
|
+
const host = b.graph.host.result;
|
|
93
|
+
const name = switch (host.os.tag) {
|
|
94
|
+
.linux => switch (host.cpu.arch) {
|
|
95
|
+
.x86_64 => "pandoc_linux_amd64",
|
|
96
|
+
else => @panic("unsupported cpu arch"),
|
|
97
|
+
},
|
|
98
|
+
.macos => switch (host.cpu.arch) {
|
|
99
|
+
.aarch64 => "pandoc_macos_arm64",
|
|
100
|
+
else => @panic("unsupported cpu arch"),
|
|
101
|
+
},
|
|
102
|
+
else => @panic("unsupported os"),
|
|
103
|
+
};
|
|
104
|
+
if (b.lazyDependency(name, .{})) |dep| {
|
|
105
|
+
return dep.path("bin/pandoc");
|
|
106
|
+
} else {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fn get_vale_bin(b: *std.Build) ?std.Build.LazyPath {
|
|
112
|
+
const host = b.graph.host.result;
|
|
113
|
+
const name = switch (host.os.tag) {
|
|
114
|
+
.linux => switch (host.cpu.arch) {
|
|
115
|
+
.x86_64 => "vale_linux_amd64",
|
|
116
|
+
else => @panic("unsupported cpu arch"),
|
|
117
|
+
},
|
|
118
|
+
.macos => switch (host.cpu.arch) {
|
|
119
|
+
.aarch64 => "vale_macos_arm64",
|
|
120
|
+
else => @panic("unsupported cpu arch"),
|
|
121
|
+
},
|
|
122
|
+
else => @panic("unsupported os"),
|
|
123
|
+
};
|
|
124
|
+
if (b.lazyDependency(name, .{})) |dep| {
|
|
125
|
+
return dep.path("vale");
|
|
126
|
+
} else {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Hide step's stdout unless it fails. Sadly, this requires overriding Build.Step.Run make function.
|
|
132
|
+
fn hide_stdout(run: *std.Build.Step.Run) void {
|
|
133
|
+
_ = run.captureStdOut();
|
|
134
|
+
|
|
135
|
+
const override = struct {
|
|
136
|
+
var global_map: std.AutoHashMapUnmanaged(usize, std.Build.Step.MakeFn) = .{};
|
|
137
|
+
|
|
138
|
+
fn make(step: *std.Build.Step, options: std.Build.Step.MakeOptions) anyerror!void {
|
|
139
|
+
const original = global_map.get(@intFromPtr(step)).?;
|
|
140
|
+
original(step, options) catch |err| {
|
|
141
|
+
const run_step: *std.Build.Step.Run = @fieldParentPtr("step", step);
|
|
142
|
+
if (run_step.captured_stdout) |output| {
|
|
143
|
+
const file = try std.fs.cwd().openFile(output.generated_file.getPath(), .{});
|
|
144
|
+
defer file.close();
|
|
145
|
+
|
|
146
|
+
const stdout = try file.readToEndAlloc(step.owner.allocator, 100 * 1024);
|
|
147
|
+
std.debug.print("{s}\n", .{stdout});
|
|
148
|
+
}
|
|
149
|
+
return err;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const original = run.step.makeFn;
|
|
155
|
+
const b = run.step.owner;
|
|
156
|
+
override.global_map.put(b.allocator, @intFromPtr(&run.step), original) catch @panic("OOM");
|
|
157
|
+
run.step.makeFn = override.make;
|
|
158
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
//! Walk the `/docs` directory to build table of contents by parsing links to child pages from
|
|
2
|
+
//! the READMEs.
|
|
3
|
+
const std = @import("std");
|
|
4
|
+
const Allocator = std.mem.Allocator;
|
|
5
|
+
const assert = std.debug.assert;
|
|
6
|
+
|
|
7
|
+
const log = std.log.scoped(.content);
|
|
8
|
+
const cut_prefix = @import("./docs.zig").cut_prefix;
|
|
9
|
+
const cut = @import("./docs.zig").cut;
|
|
10
|
+
|
|
11
|
+
pub const Page = struct {
|
|
12
|
+
content: PageContent,
|
|
13
|
+
path: []const u8, // Always ends in .md
|
|
14
|
+
children: []Page,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Parsed content of a single .md file.
|
|
18
|
+
const PageContent = struct {
|
|
19
|
+
title: []const u8,
|
|
20
|
+
children: []Child,
|
|
21
|
+
|
|
22
|
+
const Child = struct {
|
|
23
|
+
title: []const u8,
|
|
24
|
+
path: []const u8,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
pub fn load(arena: Allocator, base: std.fs.Dir, page_buffer: []u8) !Page {
|
|
29
|
+
return load_page(arena, base, "./", page_buffer);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fn load_page(arena: Allocator, base: std.fs.Dir, path: []const u8, page_buffer: []u8) !Page {
|
|
33
|
+
errdefer log.err("error while loading '{s}'", .{path});
|
|
34
|
+
const is_dir = std.mem.endsWith(u8, path, "/");
|
|
35
|
+
const is_client = std.mem.indexOf(u8, path, "src/clients") != null;
|
|
36
|
+
|
|
37
|
+
const file_path = if (is_dir) try std.fs.path.join(arena, &.{ path, "README.md" }) else path;
|
|
38
|
+
if (!std.mem.endsWith(u8, file_path, ".md")) {
|
|
39
|
+
return error.InvalidPath;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const text = try read_file(base, file_path, page_buffer);
|
|
43
|
+
const content = try parse_page_content(arena, text, .{
|
|
44
|
+
.parse_children = is_dir and !is_client,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
var children: std.ArrayListUnmanaged(Page) = .{};
|
|
48
|
+
for (content.children) |child| {
|
|
49
|
+
assert(is_dir);
|
|
50
|
+
const child_path = if (std.mem.startsWith(u8, child.path, "/src/clients"))
|
|
51
|
+
try std.fs.path.join(arena, &.{
|
|
52
|
+
"..",
|
|
53
|
+
child.path,
|
|
54
|
+
})
|
|
55
|
+
else
|
|
56
|
+
try std.fs.path.join(arena, &.{
|
|
57
|
+
path,
|
|
58
|
+
cut_prefix(child.path, "./") orelse child.path,
|
|
59
|
+
});
|
|
60
|
+
const child_page = try load_page(arena, base, child_path, page_buffer);
|
|
61
|
+
try children.append(arena, child_page);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (is_dir and !is_client) {
|
|
65
|
+
var dir = try base.openDir(path, .{ .iterate = true });
|
|
66
|
+
defer dir.close();
|
|
67
|
+
|
|
68
|
+
var dir_iterator = dir.iterate();
|
|
69
|
+
while (try dir_iterator.next()) |entry| {
|
|
70
|
+
if (std.mem.eql(u8, entry.name, "README.md")) continue;
|
|
71
|
+
if (std.mem.eql(u8, entry.name, "internals")) continue;
|
|
72
|
+
if (std.mem.eql(u8, entry.name, "TIGER_STYLE.md")) continue;
|
|
73
|
+
if (std.mem.eql(u8, entry.name, "ARCHITECTURE.md")) continue;
|
|
74
|
+
for (content.children) |child| {
|
|
75
|
+
const name = std.mem.trimRight(
|
|
76
|
+
u8,
|
|
77
|
+
cut_prefix(child.path, "./") orelse child.path,
|
|
78
|
+
"/",
|
|
79
|
+
);
|
|
80
|
+
if (std.mem.eql(u8, name, entry.name)) break;
|
|
81
|
+
} else {
|
|
82
|
+
log.err("orphaned page: {s}{s}", .{ path, entry.name });
|
|
83
|
+
return error.OrphanedPage;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return .{
|
|
89
|
+
.content = content,
|
|
90
|
+
.path = file_path,
|
|
91
|
+
.children = children.items,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fn parse_page_content(arena: Allocator, text: []const u8, options: struct {
|
|
96
|
+
parse_children: bool,
|
|
97
|
+
}) !PageContent {
|
|
98
|
+
var line_iterator = std.mem.tokenizeScalar(u8, text, '\n');
|
|
99
|
+
var title_line = line_iterator.next() orelse return error.TitleInvalid;
|
|
100
|
+
if (std.mem.startsWith(u8, title_line, "<!--")) {
|
|
101
|
+
// Clients' readmes start with auto-generated comment, skip over it.
|
|
102
|
+
title_line = line_iterator.next() orelse return error.TitleInvalid;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
var title = cut_prefix(title_line, "# ") orelse return error.TitleInvalid;
|
|
106
|
+
title = std.mem.trim(u8, title, "`");
|
|
107
|
+
if (title.len < 3) return error.TitleInvalid;
|
|
108
|
+
|
|
109
|
+
var children: std.ArrayListUnmanaged(PageContent.Child) = .{};
|
|
110
|
+
|
|
111
|
+
if (options.parse_children) {
|
|
112
|
+
while (line_iterator.next()) |line| {
|
|
113
|
+
if (try parse_page_child(line)) |child| {
|
|
114
|
+
try children.append(arena, .{
|
|
115
|
+
.title = try arena.dupe(u8, child.title),
|
|
116
|
+
.path = try arena.dupe(u8, child.path),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return .{
|
|
123
|
+
.title = try arena.dupe(u8, title),
|
|
124
|
+
.children = children.items,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fn parse_page_child(line: []const u8) !?PageContent.Child {
|
|
129
|
+
errdefer log.err("error while parsing '{s}'", .{line});
|
|
130
|
+
|
|
131
|
+
var rest = cut_prefix(line, "- [") orelse return null;
|
|
132
|
+
const title, rest = cut(rest, "](") orelse return error.InvalidLink;
|
|
133
|
+
const path, _ = cut(rest, ")") orelse return error.InvalidLink;
|
|
134
|
+
if (!std.mem.startsWith(u8, path, "./")) {
|
|
135
|
+
if (std.mem.startsWith(u8, path, "/src/clients/")) {
|
|
136
|
+
// Special case.
|
|
137
|
+
} else {
|
|
138
|
+
log.err("ToC links must start with './'", .{});
|
|
139
|
+
return error.InvalidLink;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (!std.mem.endsWith(u8, path, ".md") and !std.mem.endsWith(u8, path, "/")) {
|
|
143
|
+
log.err("ToC links must end with '/' or '.md'", .{});
|
|
144
|
+
return error.InvalidLink;
|
|
145
|
+
}
|
|
146
|
+
return .{
|
|
147
|
+
.title = std.mem.trim(u8, title, "`"),
|
|
148
|
+
.path = path,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fn read_file(dir: std.fs.Dir, path: []const u8, page_buffer: []u8) ![]const u8 {
|
|
153
|
+
const result = try dir.readFile(path, page_buffer);
|
|
154
|
+
if (result.len == page_buffer.len) return error.FileToLarge;
|
|
155
|
+
return result;
|
|
156
|
+
}
|