Slib reader¶
A .slib metadata reader, written in Sushi: read_metadata, sizes and
bitcode_size. It mirrors the Python reader LibraryFormat.read_metadata_only.
Import¶
use <toolchain/slib>
fn main() i32:
return Result.Ok(0)
Overview¶
toolchain/slib is a Sushi-source standard-library module. It reads the fixed
52-byte little-endian header and the MessagePack metadata map of a version-4 .slib
library (see Library Format). The metadata comes back as a
MsgValue tree. The reader stops after the metadata blob; it
reads the length of a payload section, never the payload.
The module imports <encoding/msgpack> and <io/files> — the first source module that
imports another source module.
Types¶
public enum SlibError:
OpenFailed(string) # the path that did not open
BadMagic() # the 16 magic bytes do not match
BadVersion(u32) # header version is not 4
Truncated() # the file ends inside the header or the blob
Decode(MpError) # the metadata blob does not decode
public struct SlibSizes:
u64 source # the length of the source section
u64 bitcode # the length of the bitcode section
Functions¶
read_metadata(string path) -> MsgValue | SlibError¶
Read the metadata map of a .slib file. The four spare header fields are read and not
validated, the same as the Python reader.
use <encoding/msgpack>
use <toolchain/slib>
fn library_name(string path) string:
match read_metadata(path):
Result.Ok(meta) ->
let Maybe@(MsgValue) found = map_get(meta, "library_name")??
match found:
Maybe.Some(v) ->
return Result.Ok(show(v)??)
Maybe.None() ->
return Result.Ok("missing")
Result.Err(_) ->
return Result.Ok("read error")
return Result.Ok("read error")
fn main() i32:
println(library_name("mylib.slib").realise("error"))
return Result.Ok(0)
sizes(string path) -> SlibSizes | SlibError¶
The length of both payload sections, in one pass over the file. A version-4 container puts a length-prefixed source section between the metadata and the bitcode, so a reader steps over the source to reach the bitcode length. A source library records no bitcode, and a binary one no source.
use <toolchain/slib>
fn main() i32:
match sizes("mylib.slib"):
Result.Ok(sizes) ->
println("source {sizes.source}, bitcode {sizes.bitcode}")
Result.Err(_) ->
println("read error")
return Result.Ok(0)
bitcode_size(string path) -> u64 | SlibError¶
The bitcode field of sizes, on its own. The reader reads only the two 8-byte
length fields, never a payload.
Error handling¶
use <toolchain/slib>
fn classify(string path) string:
match read_metadata(path):
Result.Ok(_) ->
return Result.Ok("ok")
Result.Err(e) ->
match e:
SlibError.OpenFailed(p) ->
return Result.Ok("cannot open {p}")
SlibError.BadMagic() ->
return Result.Ok("not a .slib library")
SlibError.BadVersion(v) ->
return Result.Ok("unsupported version {v}")
SlibError.Truncated() ->
return Result.Ok("truncated file")
SlibError.Decode(_) ->
return Result.Ok("metadata does not decode")
fn main() i32:
println(classify("missing.slib").realise("error")) # cannot open missing.slib
return Result.Ok(0)
The slib-info tool¶
toolchain/src/slib_info.sushi (in the repository, not in the wheel) renders the same
report as sushic --lib-info. A repo checkout builds it with ./toolchain/build.py,
and sushic --lib-info then delegates to the binary. See toolchain/README.md.
Limitations¶
- Read-only, metadata-only. Writing a
.slibstays in Python. - No typed manifest structs: consumers walk the
MsgValuetree withmap_get. - Metadata above 2 GiB is not supported; a hostile length reads nothing and reports a decode error on the empty blob.
See also¶
- MessagePack — the
MsgValuetree and its accessors - Library Format — the
.slibcontainer specification