Source src/silo:std.path
1##! Path — platform-independent file-system path values and operations. 2##! 3##! Unix-only today: the `UnixPath` / `UnixSeg` variants are populated 4##! and `main-separator` returns `/`. The Windows variants are declared 5##! so the type shape matches the spec, but observing one at runtime 6##! panics; compile-time `@cfg` dispatch arrives with the Windows 7##! target. 8##! 9##! `Display` impls land alongside the format pipeline. 10 11:use 12 :open core AnyInt Bool Byte Codepoint Option None Some Result Ok Err Str U8 U16 Vec 13:end 14 15# si[impl stdlib.path.type+2] 16##( 17`Path` MUST be an internal union of OS-native byte representations. On 18Unix targets the `UnixPath` variant is populated with a sequence of 198-bit bytes; on Windows targets `WindowsPath` carries 16-bit code units. 20The concrete variant is selected per target at compile time. Paths are 21NOT guaranteed to be valid UTF-8. 22)# 23:union(pub) Path 24 | UnixPath (Vec U8) 25 | WindowsPath (Vec U16) 26:end 27 28# si[impl stdlib.path.segment] 29##( 30`PathSegment` is a narrow type representing a single path fragment in 31OS-native bytes. Mirrors `Path`'s variants. 32)# 33:union(pub) PathSegment 34 | UnixSeg (Vec U8) 35 | WindowsSeg (Vec U16) 36:end 37 38# si[impl stdlib.path.component] 39##( 40`Component` classifies the kinds of fragment encountered while walking 41a `Path`. Mirrors Rust's `std::path::Component` minus the Windows 42`Prefix` variant (Silo is Unix-only until the Windows target lands). 43 44Variants: 45 - `Normal PathSegment` — a regular path segment in OS-native bytes. 46 - `RootDir` — the leading `/` of an absolute path. 47 - `CurDir` — a `.` fragment. 48 - `ParentDir` — a `..` fragment. 49)# 50:union(pub) Component 51 | Normal PathSegment 52 | RootDir 53 | CurDir 54 | ParentDir 55:end 56 57:impl Path 58 # si[impl stdlib.path.from-str+1] 59 ## `.from-str` — parse a `Str` into a `Path`. Leading `/` marks 60 ## absolute; consecutive `/` collapse; trailing `/` is dropped. 61 ## Qualified dispatch: `"/home/user" (Path .from-str)`. 62 .from-str ( Str -> Path ) 63 path-from-str-intrinsic ; 64 65 # si[impl stdlib.path.to-str+2] 66 ## `.to-str` — render a `Path` back to a `Str`. Returns `Err` when 67 ## the underlying bytes are not valid UTF-8. 68 .to-str ( Path -> (Result Str Str) ) 69 path-to-str-intrinsic ; 70 71 # si[impl stdlib.path.to-string-lossy+1] 72 ## `.to-string-lossy` — always-successful Str rendering; invalid 73 ## UTF-8 is replaced with U+FFFD. 74 .to-string-lossy ( Path -> Str ) 75 path-to-string-lossy-intrinsic ; 76 77 # si[impl stdlib.path.segments] 78 ## `.segments` — the sequence of `PathSegment` values after parsing, 79 ## excluding any leading root marker. 80 .segments ( Path -> (Vec PathSegment) ) 81 path-segments-intrinsic ; 82 83 # si[impl stdlib.path.file-name+1] 84 ## `.file-name` — last segment as `(Option PathSegment)`; `None` if 85 ## the path has no segments. 86 .file-name ( Path -> (Option PathSegment) ) 87 path-file-name-intrinsic ; 88 89 # si[impl stdlib.path.extension+1] 90 ## `.extension` — file extension (portion of last segment after the 91 ## final `.`). `None` if no `.`, `.` is first char, or no segments. 92 .extension ( Path -> (Option PathSegment) ) 93 path-extension-intrinsic ; 94 95 # si[impl stdlib.path.stem+1] 96 ## `.stem` — last segment with its extension stripped. `None` iff the 97 ## path has no segments. 98 .stem ( Path -> (Option PathSegment) ) 99 path-stem-intrinsic ; 100 101 # si[impl stdlib.path.parent+1] 102 ## `.parent` — path with last segment removed, or `None` if already at 103 ## root. Single-segment paths yield `/` (absolute) or `.` (relative). 104 .parent ( Path -> (Option Path) ) 105 path-parent-intrinsic ; 106 107 # si[impl stdlib.path.join+1] 108 ## `.join` — append a segment string. The string MUST NOT contain `/`. 109 .join ( Path Str -> Path ) 110 path-join-intrinsic ; 111 112 # si[impl stdlib.path.is-absolute+1] 113 ## `.is-absolute` — true iff the path starts with `/`. 114 .is-absolute ( Path -> Bool ) 115 path-is-absolute-intrinsic ; 116 117 # si[impl stdlib.path.is-relative+1] 118 ## `.is-relative` — `true` iff the path does not start with `/`. 119 .is-relative ( Path -> Bool ) 120 path-is-relative-intrinsic ; 121 122 # si[impl stdlib.path.components+1] 123 ## `.components` — decompose the path into its left-to-right sequence 124 ## of `Component` values. `RootDir` appears first (and only first) when 125 ## the path is absolute. `.` / `..` fragments surface as `CurDir` / 126 ## `ParentDir` and are NOT resolved (that is `.canonicalize`'s job). 127 .components ( Path -> (Vec Component) ) 128 path-components-intrinsic ; 129:end 130 131# si[impl stdlib.path.segment+1] 132:impl PathSegment 133 ## `.to-str` — decode as UTF-8; `Err` on invalid sequences. 134 .to-str ( PathSegment -> (Result Str Str) ) 135 pathseg-to-str-intrinsic ; 136 ## `.to-string-lossy` — always-successful Str rendering. 137 .to-string-lossy ( PathSegment -> Str ) 138 pathseg-to-string-lossy-intrinsic ; 139:end 140 141# si[impl stdlib.path.main-separator] 142##( 143`main-separator` — the host target's primary path separator, as a 144`Codepoint`. On Unix the value is `/` (U+002F); on Windows it would be 145`\` (U+005C). Silo is currently Unix-only, so this always returns `/`. 146 147Naming: the spec's Rust-style example uses the identifier 148`MAIN_SEPARATOR`; Silo's current grammar only permits lower-case 149identifiers as `:fn` names, so we expose this as `main-separator`. 150Once Silo grows an uppercase-const syntax (and `@cfg` dispatch for 151Windows), both changes will land together. 152)# 153:fn(pub) main-separator ( -> Codepoint ) 154 path-main-separator-intrinsic 155:end