ghostty-unicode: Ghostty computes codepoint properties with the uucode Zig package (v0.2.0, Unicode 17.0.0). There is no Rust equivalent, so a trimmed UCD set is vendored in ucd/ and build.rs re-implements uucode's derivations: cell width rules incl. Ghostty's overrides for emoji modifiers and Prepend, grapheme break classes with the compile-time grapheme_break state table, the is_symbol set, and emoji presentation. Lookups are three array indexes per codepoint. Validated against the official GraphemeBreakTest.txt. ghostty-datastruct: split_tree (used for GTK splits; f16 ratios so rounding and debug diagrams match Zig), circ_buf, lru, cache_table, blocking_queue, segmented_pool, message_data, comparison, array_list_collection. intrusive_linked_list is not needed (lru is index based). lru now reports the evicted (old) key, Zig reported the new key, which appears to be a bug. Not yet covered: case_folding_full (needed by input bindings). Test Plan: - cargo test -p ghostty-unicode (16) -p ghostty-datastruct (88) - cargo clippy for both crates with -D warnings
3.9 KiB
3.9 KiB
ghostty-datastruct
Port of ZIG/src/datastruct/*.
| Zig | Rust (crates/ghostty-datastruct/src) |
Notes |
|---|---|---|
split_tree.zig |
split_tree.rs |
Full port, all 17 tests (+4 extra). |
circ_buf.zig |
circ_buf.rs |
CircBuf<T> takes the default value in new. All 21 tests (+2). |
lru.zig |
lru.rs |
Slab + index linked list. All 4 tests (+1). |
cache_table.zig |
cache_table.rs |
CacheContext trait (hash/eql/evicted). 1 test (+2). |
blocking_queue.zig |
blocking_queue.rs |
Mutex + Condvar. 2 tests (+3, incl. cross-thread). |
segmented_pool.zig |
segmented_pool.rs |
Index handles instead of pointers. 1 test. |
message_data.zig |
message_data.rs |
enum Small/Stable/Alloc. 3 tests (+1). |
comparison.zig |
comparison.rs |
DeepEqual / ApproxEq traits. All 24 tests. |
array_list_collection.zig |
array_list_collection.rs |
0 Zig tests (1 added). |
intrusive_linked_list.zig |
not ported | Only user is lru.zig; replaced by an index-based list. Its 1 test is skipped. |
main.zig |
lib.rs |
refAllDecls test skipped (Zig only). |
Zig tests: 73 ported (all), 2 skipped (intrusive_linked_list basic test,
main.zig refAllDecls). Total Rust tests: 88.
SplitTree design / deviations
- View type: Zig stores
*Viewwithref/unref. Rust:V: SplitTreeView(Clone+ optionalsplit_tree_label() -> Option<String>).Cloneis the ref,Dropis the unref (useRc/Arc/GObject handles inside the view). Allocation is infallible, so no allocator parameters; the arena is aVec.SplitTree::new(&view)replacesinit,empty()replaces.empty,Clonereplacesclone,Dropreplacesdeinit. - Only
splitcan fail (SplitError::OutOfMemorywhen > 65535 nodes, as in Zig). Handleis au16newtype (Handle::ROOT,idx(),offset(),from_idx());nodes()/zoomed()are read-only accessors.- Ratios and spatial slots use
half::f16exactly like Zig'sf16(so rounding in{d:.2}output,resize, spatial navigation match). gotono longer takes an allocator; spatial navigation allocates aVec.- Formatting:
Display= diagram + text (like{f});format_diagram,format_text(writer based),diagram_string()/text_string()helpers replacestd.fmt.alt(t, .formatDiagram/.formatText). If a view has no label, the node index is used (digit width =log10(nodes)+1). getGObjectType(GTK boxed type glue) is not ported: the GTK crate should wrapSplitTree<V>itself (e.g. aglib::Boxednewtype usingClone).
Other deviations
lru:V: Defaultis required (the new slot is default-initialised where Zig leaves it undefined).GetOrPutResult.evictedcontains the evicted entry's old key and old value (Zig set the new key before copying the entry out, which looks like a bug; only.valueis used in tests).getreturnsOption<&V>and does not affect LRU order (as in Zig).resizereturns the evicted values (oldest first) asOption<Vec<V>>.cache_table:getreturnsOption<&V>(moves the hit to the bucket end); buckets areVecs instead of fixed arrays;K/V: Cloneforputbecause the eviction hook and the return value both receive the evicted pair.blocking_queue:create/destroy->new()/Arc;drain()returns a guard iterator that releases the lock (and signals waiting producers) on drop. Blocking pushes usewait_while, so spurious wakeups no longer fail a push.segmented_pool:get()returns a slot index; useat/at_mut.message_data:Stableholds&'static [T];Allocholds aVec.comparison: Zig reflection (deepEqualover any type) is replaced by traits; implementDeepEqualfor custom types (rarely needed — preferPartialEq).expect_approx_equalpanics instead of returning an error;@Vectorand anonymous structs map to arrays/tuples.
TODO(integration)
None.