tiny.sys.font
Defined in tiny.sys.
API (54)
Actions
Public operations.
Catalog.activateCatalog.appendDirectory: Puts one subdirectory on the queue, once the walk decides to descend into it, and hands back the index of its record.Catalog.appendEntry: Appends one accepted font file during the walk, taking its path, its size, its format, and the index of the root it came from.Catalog.appendRoot: Puts one root directory on the queue and hands back the index of its record.Catalog.deinitCatalog.directoryAtCatalog.directoryCountCatalog.directoryPathCatalog.entriesCatalog.entryCountCatalog.entryPathCatalog.initCatalog.pathBytesUsedCatalog.reset: Resets the catalog so a caller reuses one region for a second enumeration.Catalog.takeDirectory: Drains the frontier one directory per turn for the walk, taking the next directory off the queue and returning its index.Format.fromName: Decides whether a file is a font at all by reading the text after a name's last dot and matching it against the known extensions, upper and lower case alike.RootSet.append: Addsdirectoryto the end of the list, when the path is absolute, the list lacks it, and the bytes fit, and reports whether it went in.RootSet.appendJoined: Joinsparentandchildwith a single separator and adds the result.RootSet.clearRootSet.pathdefaultRoots: Fillssetwith the directories this machine's operating system keeps fonts in, ordered as the search visits them.enumerate: Puts every font file found beneath the directories insetintocatalogand leaves an account of what it passed over instats, so a caller can run one enumeration and read the result out of its own catalog storage.hostEnvironment: Looks upHOME,XDG_DATA_HOME, andXDG_DATA_DIRSin the running process, for a caller running against the real host.rootsFor: Fillssetfor the operating system named byos_tagafter clearing the set first, so a test on one host can check another platform's search order and the refusal an unlisted one produces.
Types and contracts
Public types and contracts.
Catalog: Holds one enumeration's results and the directories still queued for the walk over a byte region the caller supplies, so a caller reads the whole enumeration back out of it.Catalog.CapacityCatalog.ExhaustionCatalog.InitErrorCatalog.LimitsCatalog.StorageDirectory: Records one visited directory so the walk can descend from it and detect a cycle.Entry: Records one accepted font file so a caller walking admitted entries can get each font's path and size.Environment: Holds the three environment values that shape the Linux list:HOME,XDG_DATA_HOME, andXDG_DATA_DIRS.Error: Combines the capacity refusals of the catalog with cancellation, so a caller distinguishes a full catalog from a cancelled walk because nothing else stops one.Format: Identifies which container a font file uses, among TrueType, OpenType, the two collection containers, and Type 1, so a caller tells a TrueType file from a Type 1 file.Options: The limits a caller sets on one walk.RootSet: Keeps a list of absolute font directories in inline storage, ordered as the search visits them, which a caller holds across a resolve and a walk with no allocation anywhere in between.Stats: Provides a counter for each kind of thing the walk saw and passed over, so a caller can tell a complete enumeration from one that skipped part of the tree.Support: The outcome of resolving the platform's default roots, either the count of roots written or the reason none were, so a caller can tell an empty platform from an empty search.Unsupported: The reason a platform reports no font roots, read by a caller that got none.
Namespaces
Public namespaces.
Values and defaults
Public values and defaults.
Catalog.claimCatalog.storage_alignmentCatalog.work_limitsdepth_limit: Hard ceiling of 16 levels on descent that caps two things: how many steps the cycle guard climbs, and anyOptions.depth_maxa caller sets for the walk to assert against.directories_maxentries_max: The ceilings on the three counts a caller picks as limits: files, directories, and path bytes.entries_per_directory_max: Caps how many directory entries get read out of a single directory before the walk moves on, so a caller reading statistics knows what one enormous directory does to an enumeration in progress.extension_bytes_max: The longest extensionFormat.fromNamewill case-fold before matching, at eight bytes.path_bytes_limit: Defines the longest path the catalog will take, which lets a record hold its length in sixteen bits.path_bytes_maxrequired_capabilitiesroot_bytes_max: The largest total byte count a root set retains for its root paths, at 4096.roots_max: The largest number of roots a root set retains, at 24.
Source
Source: lib/sys/src/font/catalog.zig:169
/// Holds one enumeration's results and the directories still queued for the/// walk over a byte region the caller supplies, so a caller reads the whole/// enumeration back out of it. That byte region holds the entry records, then/// the directory records, then the shared path arena. Each admission tests the/// entry count, the directory count, and the remaining path bytes before it/// writes anything, which leaves everything accepted so far untouched when one/// of the three refuses, so a caller may read a refusal as the answer being cut/// short at `entryCount`. The order of use runs `init`, then `activate`, then/// admissions, then `deinit`, which hands the caller's storage back.pub const Catalog = struct { phase: capacity.Phase, capacity: CatalogCapacity, storage: Storage, entry_count: u32, directory_count: u32, directory_head: u32, path_used: u32, pub const storage_alignment: usize = 8; pub const Storage: type = []align(storage_alignment) u8; pub const Limits: type = CatalogLimits; pub const Capacity: type = CatalogCapacity; pub const Exhaustion: type = CatalogExhaustion; pub const InitError: type = CatalogInitError; pub const work_limits: capacity.WorkLimits = .{ .transition_steps_max = 1, .cleanup_steps_per_call_max = 0, .cleanup_calls_at_capacity_max = 0, }; pub const claim: capacity.Declaration = .{ .source = .{ .id = "sys.font_walk", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{ .{ .id = "caller_font_entry_records", .lifetime = .transferred, .detail = "caller entry records for accepted font files", }, .{ .id = "caller_font_directory_records", .lifetime = .transferred, .detail = "caller directory records for the depth bounded frontier", }, .{ .id = "caller_font_path_bytes", .lifetime = .transferred, .detail = "caller path arena shared by entry and directory records", }, }, .excluded = &.{ "caller-owned root set, walk options, and enumeration statistics", "directory handles, iterator read buffers, and kernel path state", "process environment strings borrowed while default roots resolve", }, }, .capacity = .{ .inputs = &.{ capacity.bindInput(CatalogLimits, "entries", "entries"), capacity.bindInput(CatalogLimits, "directories", "directories"), capacity.bindInput(CatalogLimits, "path_bytes", "path_bytes"), }, .type_selectors = &.{ capacity.bindType(Entry, "entry"), capacity.bindType(Directory, "directory"), }, .nodes = &.{ .{ .input = 0 }, .{ .input = 1 }, .{ .input = 2 }, .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 0 } } }, .{ .scale = .{ .node = 1, .coefficient = .{ .size_of_concrete_type = 1 } } }, .{ .add = .{ .left = 3, .right = 4 } }, .{ .add = .{ .left = 5, .right = 2 } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .exact, .expression = 6, }}, }, .overload = .{ .kind = .reject_before_mutation, .detail = "an admission past entry, directory, or path capacity writes nothing", }, .risks = .{ .transitive = .{ .status = .open, .detail = "the walk enters directory iteration owned by the standard library", }, .foreign = .{ .status = .open, .detail = "directory handles and iterator read buffers belong to the kernel", }, }, .work = .{ .equation = "transition_steps <= 1 and cleanup_steps == 0" }, .obligations = &.{ .{ .key = "sys_font_walk_capacity_model", .role = .capacity_model }, .{ .key = "sys_font_walk_overload", .role = .overload }, .{ .key = "sys_font_walk_work_bound", .role = .work_bound }, }, }, .bindings = .{ .owner = @This(), .seal = .{ .family = capacity.selector(@This().activate), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, .teardown = .{ .family = capacity.selector(@This().deinit), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, }, }; pub fn init(storage: Storage, limits: CatalogLimits) CatalogInitError!Catalog { const derived = try CatalogCapacity.derive(limits); if (storage.len < derived.storage_bytes) return error.StorageTooShort; return .{ .phase = .initialization, .capacity = derived, .storage = storage, .entry_count = 0, .directory_count = 0, .directory_head = 0, .path_used = 0, }; } pub fn activate(self: *Catalog) void { std.debug.assert(self.phase == .initialization); self.phase = .steady; } /// Resets the catalog so a caller reuses one region for a second /// enumeration. The call sets the entry count, the directory count, the /// queue position, and the used path bytes back to zero, while the caller's /// storage stays with the catalog. pub fn reset(self: *Catalog) void { std.debug.assert(self.phase == .steady); self.entry_count = 0; self.directory_count = 0; self.directory_head = 0; self.path_used = 0; } /// Appends one accepted font file during the walk, taking its path, its /// size, its format, and the index of the root it came from. The entry /// count and the remaining path bytes are both checked before anything is /// written, so a refusal changes no record and no byte. pub fn appendEntry( self: *Catalog, path: []const u8, size_bytes: u64, format: Format, root: u8, ) CatalogExhaustion!void { std.debug.assert(self.phase == .steady); std.debug.assert(path.len != 0); if (self.entry_count == self.capacity.entries) return error.FontEntriesExhausted; const offset = try self.reservePath(path); self.entryStore()[self.entry_count] = .{ .size_bytes = size_bytes, .path_offset = offset, .path_len = @intCast(path.len), .format = format, .root = root, }; self.entry_count += 1; } /// Puts one root directory on the queue and hands back the index of its /// record. The walk calls it once per font root before it starts /// descending. The record's parent index is its own index, which terminates /// the ancestor climb of the walk's cycle guard. pub fn appendRoot( self: *Catalog, path: []const u8, inode: u64, root: u8, ) CatalogExhaustion!u32 { const index = try self.appendDirectory(path, inode, self.directory_count, 0, root); std.debug.assert(self.directoryStore()[index].parent == index); return index; } /// Puts one subdirectory on the queue, once the walk decides to descend /// into it, and hands back the index of its record. The record keeps the /// inode, the index of the record it was reached from, how far beneath the /// root it sits, and which root that is. The directory count and the /// remaining path bytes are both checked before anything is written, so a /// refusal changes no record and no byte. pub fn appendDirectory( self: *Catalog, path: []const u8, inode: u64, parent: u32, depth: u8, root: u8, ) CatalogExhaustion!u32 { std.debug.assert(self.phase == .steady); std.debug.assert(path.len != 0); if (self.directory_count == self.capacity.directories) { return error.FontDirectoriesExhausted; } const offset = try self.reservePath(path); std.debug.assert(self.directory_count < self.capacity.directories); const index = self.directory_count; std.debug.assert(parent <= index); self.directoryStore()[index] = .{ .inode = inode, .path_offset = offset, .parent = parent, .path_len = @intCast(path.len), .depth = depth, .root = root, }; self.directory_count += 1; return index; } /// Drains the frontier one directory per turn for the walk, taking the next /// directory off the queue and returning its index. The call returns null /// once the frontier is drained. Records come back in the order they went /// in, which makes the walk breadth-first. pub fn takeDirectory(self: *Catalog) ?u32 { std.debug.assert(self.phase == .steady); std.debug.assert(self.directory_head <= self.directory_count); if (self.directory_head == self.directory_count) return null; const index = self.directory_head; self.directory_head += 1; return index; } pub fn directoryAt(self: *const Catalog, index: u32) Directory { std.debug.assert(self.phase == .steady); std.debug.assert(index < self.directory_count); return self.directoryStore()[index]; } pub fn entryCount(self: *const Catalog) u32 { return self.entry_count; } pub fn directoryCount(self: *const Catalog) u32 { return self.directory_count; } pub fn pathBytesUsed(self: *const Catalog) u32 { return self.path_used; } pub fn entries(self: *const Catalog) []const Entry { return self.entryStore()[0..self.entry_count]; } pub fn entryPath(self: *const Catalog, entry: Entry) []const u8 { const start = entry.path_offset; std.debug.assert(start + entry.path_len <= self.path_used); return self.pathStore()[start..][0..entry.path_len]; } pub fn directoryPath(self: *const Catalog, directory: Directory) []const u8 { const start = directory.path_offset; std.debug.assert(start + directory.path_len <= self.path_used); return self.pathStore()[start..][0..directory.path_len]; } pub fn deinit(self: *Catalog) Storage { std.debug.assert(self.phase == .steady); self.phase = .teardown; const storage = self.storage; self.* = undefined; return storage; } fn reservePath(self: *Catalog, path: []const u8) CatalogExhaustion!u32 { std.debug.assert(path.len != 0); std.debug.assert(self.path_used <= self.capacity.path_bytes); if (path.len > path_bytes_limit) return error.FontPathBytesExhausted; const remaining = self.capacity.path_bytes - self.path_used; if (path.len > remaining) return error.FontPathBytesExhausted; const offset = self.path_used; @memcpy(self.pathStore()[offset..][0..path.len], path); self.path_used = offset + @as(u32, @intCast(path.len)); std.debug.assert(self.path_used <= self.capacity.path_bytes); return offset; } fn entryStore(self: *const Catalog) []Entry { std.debug.assert(self.storage.len >= self.capacity.storage_bytes); const bytes = self.storage[0 .. self.capacity.entries * @sizeOf(Entry)]; return @alignCast(std.mem.bytesAsSlice(Entry, bytes)); } fn directoryStore(self: *const Catalog) []Directory { std.debug.assert(self.storage.len >= self.capacity.storage_bytes); const start = self.capacity.entries * @sizeOf(Entry); std.debug.assert(start % storage_alignment == 0); const count = self.capacity.directories * @sizeOf(Directory); const bytes = self.storage[start..][0..count]; return @alignCast(std.mem.bytesAsSlice(Directory, bytes)); } fn pathStore(self: *const Catalog) []u8 { std.debug.assert(self.storage.len >= self.capacity.storage_bytes); const start = self.capacity.entries * @sizeOf(Entry) + self.capacity.directories * @sizeOf(Directory); return self.storage[start..][0..self.capacity.path_bytes]; }};Source: lib/sys/src/font/catalog.zig:58
/// Records one visited directory so the walk can descend from it and detect a/// cycle. The record stores where its path sits in the path arena, its inode,/// the record it was reached from, how deep it sits, and which root it came/// from. The walk's cycle guard compares the inode against every ancestor's/// inode by following the parent index, and a root's parent index is its own/// index, which ends that climb.pub const Directory = extern struct { inode: u64, path_offset: u32, parent: u32, path_len: u16, depth: u8, root: u8,};Source: lib/sys/src/font/catalog.zig:44
/// Records one accepted font file so a caller walking admitted entries can get/// each font's path and size. The record keeps where its path sits in the path/// arena and how long it is, the file size, the format, and which root it came/// from. The size and the format come from one stat call, so the file itself/// stays closed, and `Catalog.entryPath` turns the offset and length back into/// the path bytes.pub const Entry = extern struct { size_bytes: u64, path_offset: u32, path_len: u16, format: Format, root: u8,};Source: lib/sys/src/font/catalog.zig:10
/// Identifies which container a font file uses, among TrueType, OpenType, the/// two collection containers, and Type 1, so a caller tells a TrueType file/// from a Type 1 file. The answer comes from the text after the last dot in the/// name, and no file gets opened to reach it.pub const Format = enum(u8) { truetype, opentype, truetype_collection, opentype_collection, type1, /// Decides whether a file is a font at all by reading the text after a /// name's last dot and matching it against the known extensions, upper and /// lower case alike. The matched extensions are ttf, otf, ttc, otc, and /// pfb, while a name with no dot, an empty extension, or an extension /// longer than `extension_bytes_max` returns null. pub fn fromName(name: []const u8) ?Format { const dot = std.mem.lastIndexOfScalar(u8, name, '.') orelse return null; const extension = name[dot + 1 ..]; if (extension.len == 0 or extension.len > extension_bytes_max) return null; var lowered: [extension_bytes_max]u8 = undefined; for (extension, 0..) |byte, index| lowered[index] = std.ascii.toLower(byte); const folded = lowered[0..extension.len]; if (std.mem.eql(u8, folded, "ttf")) return .truetype; if (std.mem.eql(u8, folded, "otf")) return .opentype; if (std.mem.eql(u8, folded, "ttc")) return .truetype_collection; if (std.mem.eql(u8, folded, "otc")) return .opentype_collection; if (std.mem.eql(u8, folded, "pfb")) return .type1; return null; }};Source: lib/sys/src/font/roots.zig:36
/// Holds the three environment values that shape the Linux list: `HOME`,/// `XDG_DATA_HOME`, and `XDG_DATA_DIRS`. A program fills it from the running/// process with `hostEnvironment`, while a test fills it with literals so the/// search order can be checked on any machine without touching the process/// environment.pub const Environment = struct { home: ?[]const u8 = null, xdg_data_home: ?[]const u8 = null, xdg_data_dirs: ?[]const u8 = null,};Source: lib/sys/src/font/roots.zig:53
/// Keeps a list of absolute font directories in inline storage, ordered as the/// search visits them, which a caller holds across a resolve and a walk with no/// allocation anywhere in between. Once either bound is reached the set refuses/// the next directory and adds one to `dropped`, which leaves a caller whose/// machine lists more directories than the bound with the prefix that fits and/// a count of what fell away.pub const RootSet = struct { bytes: [root_bytes_max]u8 = undefined, spans: [roots_max]Span = @splat(.{ .offset = 0, .len = 0 }), count: u8 = 0, dropped: u16 = 0, used: u16 = 0, pub fn clear(self: *RootSet) void { self.count = 0; self.dropped = 0; self.used = 0; } pub fn path(self: *const RootSet, index: u8) []const u8 { std.debug.assert(index < self.count); const span = self.spans[index]; std.debug.assert(span.len != 0); std.debug.assert(span.offset + span.len <= self.used); return self.bytes[span.offset..][0..span.len]; } /// Adds `directory` to the end of the list, when the path is absolute, the /// list lacks it, and the bytes fit, and reports whether it went in. A /// caller uses it to add a root of its own to the platform's list. Trailing /// separators are trimmed before the comparison and the copy, while a /// relative, empty, or duplicate path returns false and leaves `dropped` /// alone so `dropped` counts capacity refusals only. pub fn append(self: *RootSet, directory: []const u8) bool { const trimmed = sys.path.trimTrailingSeparators(directory); if (trimmed.len == 0 or !sys.path.isAbsolute(trimmed)) return false; for (0..self.count) |index| { if (std.mem.eql(u8, self.path(@intCast(index)), trimmed)) return false; } if (self.count == roots_max or trimmed.len > root_bytes_max - self.used) { self.dropped +|= 1; return false; } const offset = self.used; @memcpy(self.bytes[offset..][0..trimmed.len], trimmed); self.spans[self.count] = .{ .offset = offset, .len = @intCast(trimmed.len) }; self.count += 1; self.used = offset + @as(u16, @intCast(trimmed.len)); std.debug.assert(self.count <= roots_max); std.debug.assert(self.used <= root_bytes_max); return true; } /// Joins `parent` and `child` with a single separator and adds the result. /// Platform lists build most of their roots this way, joining a directory /// from the environment to a fixed suffix. A join longer than the path /// buffer counts a drop and returns false. pub fn appendJoined(self: *RootSet, parent: []const u8, child: []const u8) bool { var buffer: [std.Io.Dir.max_path_bytes]u8 = undefined; const trimmed = sys.path.trimTrailingSeparators(parent); const joined = std.fmt.bufPrint(&buffer, "{s}/{s}", .{ trimmed, child }) catch { self.dropped +|= 1; return false; }; return self.append(joined); }};Source: lib/sys/src/font/roots.zig:26
/// The outcome of resolving the platform's default roots, either the count of/// roots written or the reason none were, so a caller can tell an empty/// platform from an empty search.pub const Support = union(enum) { supported: u8, unsupported: Unsupported,};Source: lib/sys/src/font/roots.zig:18
/// The reason a platform reports no font roots, read by a caller that got none.pub const Unsupported = enum { /// `lib/sys` carries no list of font directories for this operating system. platform,};Source: lib/sys/src/font/walk.zig:22
/// The limits a caller sets on one walk.pub const Options = struct { /// Sets how many levels beneath a root the walk goes, which a caller lowers /// to keep a walk shallow and cheap. The default is six, and zero reads the /// roots alone. depth_max: u8 = 6,};Source: lib/sys/src/font/walk.zig:33
/// Provides a counter for each kind of thing the walk saw and passed over, so a/// caller can tell a complete enumeration from one that skipped part of the/// tree. Counters saturate at their maximum, so a reported maximum means at/// least that many.pub const Stats = struct { roots_visited: u32 = 0, roots_missing: u32 = 0, directories_visited: u32 = 0, directories_unreadable: u32 = 0, directories_depth_skipped: u32 = 0, directories_cycle_skipped: u32 = 0, directories_truncated: u32 = 0, files_seen: u32 = 0, files_unreadable: u32 = 0, paths_too_long: u32 = 0,};Source: lib/sys/src/font/catalog.zig:75
pub const directories_max: usize = 1 << 16;Source: lib/sys/src/font/catalog.zig:74
/// The ceilings on the three counts a caller picks as limits: files,/// directories, and path bytes. A limit past any of the three is refused with/// `CapacityExceeded`.pub const entries_max: usize = 1 << 20;Source: lib/sys/src/font/catalog.zig:69
/// The longest extension `Format.fromName` will case-fold before matching, at/// eight bytes. A longer extension is no extension.pub const extension_bytes_max: usize = 8;Source: lib/sys/src/font/catalog.zig:81
/// Defines the longest path the catalog will take, which lets a record hold its/// length in sixteen bits. A longer path is refused with/// `FontPathBytesExhausted`.pub const path_bytes_limit: usize = std.math.maxInt(u16);Source: lib/sys/src/font/catalog.zig:76
pub const path_bytes_max: usize = 1 << 26;Source: lib/sys/src/font/roots.zig:128
/// Fills `set` with the directories this machine's operating system keeps fonts/// in, ordered as the search visits them. A caller enumerating host fonts/// starts here.pub fn defaultRoots(set: *RootSet, environment: Environment) Support { return rootsFor(set, native_os, environment);}Source: lib/sys/src/font/roots.zig:117
/// Looks up `HOME`, `XDG_DATA_HOME`, and `XDG_DATA_DIRS` in the running/// process, for a caller running against the real host.pub fn hostEnvironment() Environment { return .{ .home = env.get("HOME"), .xdg_data_home = env.get("XDG_DATA_HOME"), .xdg_data_dirs = env.get("XDG_DATA_DIRS"), };}Source: lib/sys/src/font/roots.zig:15
/// The largest total byte count a root set retains for its root paths, at 4096./// Past it the set refuses roots and counts them in `dropped`.pub const root_bytes_max: usize = 4096;Source: lib/sys/src/font/roots.zig:137
/// Fills `set` for the operating system named by `os_tag` after clearing the/// set first, so a test on one host can check another platform's search order/// and the refusal an unlisted one produces. Linux and the BSD targets take the/// XDG order, the Apple targets take the Library order, and every other target/// reports itself unsupported.pub fn rootsFor( set: *RootSet, os_tag: std.Target.Os.Tag, environment: Environment,) Support { set.clear(); return switch (os_tag) { .linux, .freebsd, .netbsd, .openbsd, .dragonfly, .illumos, .hurd => .{ .supported = linuxRoots(set, environment), }, .macos, .maccatalyst, .ios, .tvos, .watchos, .visionos => .{ .supported = appleRoots(set, environment), }, else => .{ .unsupported = .platform }, };}Source: lib/sys/src/font/roots.zig:11
/// The largest number of roots a root set retains, at 24. Past it the set/// refuses roots and counts them in `dropped`.pub const roots_max: u8 = 24;Source: lib/sys/src/font/walk.zig:50
/// Combines the capacity refusals of the catalog with cancellation, so a caller/// distinguishes a full catalog from a cancelled walk because nothing else/// stops one. A cancellation from the io implementation travels out to the/// caller.pub const Error = Catalog.Exhaustion || error{Canceled};Source: lib/sys/src/font/walk.zig:12
/// Hard ceiling of 16 levels on descent that caps two things: how many steps/// the cycle guard climbs, and any `Options.depth_max` a caller sets for the/// walk to assert against.pub const depth_limit: u8 = 16;Source: lib/sys/src/font/walk.zig:19
/// Caps how many directory entries get read out of a single directory before/// the walk moves on, so a caller reading statistics knows what one enormous/// directory does to an enumeration in progress. A directory past this bound is/// counted in `directories_truncated`, and the walk carries on with the next/// one.pub const entries_per_directory_max: u32 = 1 << 20;Source: lib/sys/src/font/walk.zig:64
/// Puts every font file found beneath the directories in `set` into `catalog`/// and leaves an account of what it passed over in `stats`, so a caller can run/// one enumeration and read the result out of its own catalog storage. The/// roots are admitted first and the directories are then drained in admission/// order, so the descent is breadth-first.////// A directory that will not open, a file that disappears between the listing/// and the stat, and a name too long for `std.Io.Dir.max_path_bytes` each add/// to a counter and leave the walk running. Capacity refusal and cancellation/// are the two things that stop the walk, and a refusal leaves the accepted/// prefix in the catalog. The call overwrites `stats` at its start, and it/// asserts an empty catalog and an `options.depth_max` within `depth_limit`.pub fn enumerate( io: std.Io, catalog: *Catalog, set: *const RootSet, options: Options, stats: *Stats,) Error!void { std.debug.assert(options.depth_max <= depth_limit); std.debug.assert(catalog.entryCount() == 0); std.debug.assert(catalog.directoryCount() == 0); stats.* = .{}; var path_buffer: [std.Io.Dir.max_path_bytes]u8 = undefined; for (0..set.count) |index| { try admitRoot(io, catalog, set.path(@intCast(index)), @intCast(index), stats); } var drained: u32 = 0; while (catalog.takeDirectory()) |index| { std.debug.assert(drained < catalog.directoryCount()); std.debug.assert(index == drained); drained += 1; try readDirectory(io, catalog, index, options, &path_buffer, stats); } std.debug.assert(drained == catalog.directoryCount()); std.debug.assert(stats.roots_visited <= set.count);}Source: lib/sys/src/font/root.zig
const sys = @import("../root.zig");const catalog = @import("catalog.zig");const roots = @import("roots.zig");const walk = @import("walk.zig");pub const required_capabilities = sys.capabilities.host(&.{ .environment, .filesystem });pub const fixture = @import("fixture.zig");pub const Catalog = catalog.Catalog;pub const Directory = catalog.Directory;pub const Entry = catalog.Entry;pub const Format = catalog.Format;pub const directories_max = catalog.directories_max;pub const entries_max = catalog.entries_max;pub const extension_bytes_max = catalog.extension_bytes_max;pub const path_bytes_limit = catalog.path_bytes_limit;pub const path_bytes_max = catalog.path_bytes_max;pub const Environment = roots.Environment;pub const RootSet = roots.RootSet;pub const Support = roots.Support;pub const Unsupported = roots.Unsupported;pub const defaultRoots = roots.defaultRoots;pub const rootsFor = roots.rootsFor;pub const hostEnvironment = roots.hostEnvironment;pub const root_bytes_max = roots.root_bytes_max;pub const roots_max = roots.roots_max;pub const Error = walk.Error;pub const Options = walk.Options;pub const Stats = walk.Stats;pub const depth_limit = walk.depth_limit;pub const entries_per_directory_max = walk.entries_per_directory_max;pub const enumerate = walk.enumerate;Source: lib/sys/src/root.zig:31
pub const font = @import("font/root.zig");Complete caller list for font.Catalog.activate
10 direct callers.
lib.sys.src.font.catalog.test_font_catalog_rejects_a_path_past_the_remaining_arena_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:570in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_rejects_every_admission_past_capacity_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:539in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_transitions_once_and_releases_the_caller's_storage[function] — test source atlib/sys/src/font/catalog.zig:589in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.test.test_font_enumeration_admits_every_font_below_the_depth_bound[function] — test source atlib/sys/src/font/test.zig:58in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_at_depth_zero_reads_roots_only[function] — test source atlib/sys/src/font/test.zig:104in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_over_an_unsupported_platform_walks_nothing[function] — test source atlib/sys/src/font/test.zig:161in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_rejects_at_the_directory_bound[function] — test source atlib/sys/src/font/test.zig:142in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_rejects_at_the_entry_bound_and_keeps_the_accepted_prefix[function] — test source atlib/sys/src/font/test.zig:120in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_reports_format,_size,_and_root_for_every_admitted_file[function] — test source atlib/sys/src/font/test.zig:80in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_host_font_enumeration_terminates_over_the_installed_roots[function] — test source atlib/sys/src/font/test.zig:176in nearest public ownerlib.sys.src.font.test
Complete caller list for font.Catalog.deinit
10 direct callers.
lib.sys.src.font.catalog.test_font_catalog_rejects_a_path_past_the_remaining_arena_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:570in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_rejects_every_admission_past_capacity_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:539in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_transitions_once_and_releases_the_caller's_storage[function] — test source atlib/sys/src/font/catalog.zig:589in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.test.test_font_enumeration_admits_every_font_below_the_depth_bound[function] — test source atlib/sys/src/font/test.zig:58in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_at_depth_zero_reads_roots_only[function] — test source atlib/sys/src/font/test.zig:104in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_over_an_unsupported_platform_walks_nothing[function] — test source atlib/sys/src/font/test.zig:161in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_rejects_at_the_directory_bound[function] — test source atlib/sys/src/font/test.zig:142in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_rejects_at_the_entry_bound_and_keeps_the_accepted_prefix[function] — test source atlib/sys/src/font/test.zig:120in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_reports_format,_size,_and_root_for_every_admitted_file[function] — test source atlib/sys/src/font/test.zig:80in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_host_font_enumeration_terminates_over_the_installed_roots[function] — test source atlib/sys/src/font/test.zig:176in nearest public ownerlib.sys.src.font.test
Complete caller list for font.Catalog.entryCount
7 direct callers.
lib.sys.src.font.catalog.test_font_catalog_rejects_a_path_past_the_remaining_arena_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:570in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_rejects_every_admission_past_capacity_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:539in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_transitions_once_and_releases_the_caller's_storage[function] — test source atlib/sys/src/font/catalog.zig:589in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.test.test_font_enumeration_admits_every_font_below_the_depth_bound[function] — test source atlib/sys/src/font/test.zig:58in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_at_depth_zero_reads_roots_only[function] — test source atlib/sys/src/font/test.zig:104in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_over_an_unsupported_platform_walks_nothing[function] — test source atlib/sys/src/font/test.zig:161in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_rejects_at_the_entry_bound_and_keeps_the_accepted_prefix[function] — test source atlib/sys/src/font/test.zig:120in nearest public ownerlib.sys.src.font.test
Complete caller list for font.Catalog.init
10 direct callers.
lib.sys.src.font.catalog.test_font_catalog_rejects_a_path_past_the_remaining_arena_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:570in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_rejects_every_admission_past_capacity_without_mutating[function] — test source atlib/sys/src/font/catalog.zig:539in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.catalog.test_font_catalog_transitions_once_and_releases_the_caller's_storage[function] — test source atlib/sys/src/font/catalog.zig:589in nearest public ownerlib.sys.src.font.cataloglib.sys.src.font.test.test_font_enumeration_admits_every_font_below_the_depth_bound[function] — test source atlib/sys/src/font/test.zig:58in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_at_depth_zero_reads_roots_only[function] — test source atlib/sys/src/font/test.zig:104in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_over_an_unsupported_platform_walks_nothing[function] — test source atlib/sys/src/font/test.zig:161in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_rejects_at_the_directory_bound[function] — test source atlib/sys/src/font/test.zig:142in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_rejects_at_the_entry_bound_and_keeps_the_accepted_prefix[function] — test source atlib/sys/src/font/test.zig:120in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_font_enumeration_reports_format,_size,_and_root_for_every_admitted_file[function] — test source atlib/sys/src/font/test.zig:80in nearest public ownerlib.sys.src.font.testlib.sys.src.font.test.test_host_font_enumeration_terminates_over_the_installed_roots[function] — test source atlib/sys/src/font/test.zig:176in nearest public ownerlib.sys.src.font.test
Audit
| Definitions | 54 |
|---|---|
| Public names | 54 |
| Members | 45 |
| Version | 26.7.0 |
| Revision | daab053ee433 |