silk.schema.yaml.
Read and write Schema types as YAML.
When to use#
Call SchemaYaml.decode to read a value of a silk.schema.schema.Schema type from YAML text,
such as a configuration file, SchemaYaml.decodeAll to report every problem in the text at
once, and SchemaYaml.encode to write a value as YAML to the ambient Writer. Show the
problems with silk.schema.report.SchemaReport. Use silk.yaml.document.YamlDocument to work
with YAML whose shape is not known in advance.
Details#
Decoding parses the text into a YamlDocument first, then reads the value from it, so members
may come in any order. Members the type does not name are skipped, or reported when its spec is
Spec.strict. Every problem carries the span of the bytes it is about. A field that holds text
also accepts a plain scalar that YAML reads as another kind, such as version: 1.10 or
zip: 01234, and gets its text exactly as written. Encoding writes block-style YAML, with struct
fields in declaration order.
Examples#
Read a configuration file#
import silk.collections.list { List }
import silk.core.effect { Effect }
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.schema.issue { SchemaError }
import silk.schema.schema { Schema }
import silk.schema.yaml { SchemaYaml }
import silk.text.string { String }
struct Service {
pub name: String,
pub version: String,
pub ports: List<u16>,
}
impl Schema for Service {}
effect fn load() -> i32 ! SchemaError | OutOfMemoryError ? &mut Allocator {
let api = run SchemaYaml.decode<Service>(b"name: api\nversion: 1.10\nports: [80, 443]\n")
if api.name.view() != "api" || api.version.view() != "1.10" || List<u16>.get(&api.ports, 1) != 443 {
return 1
}
return 0
}
pub effect fn main() -> i32 ! SchemaError | OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
return run load() |> Effect.provideMut<Allocator>(&mut allocator)
}Import as SchemaYaml with import silk.schema.yaml { SchemaYaml }.
Public declarations: 3.
SchemaYaml#
pub struct SchemaYamlThe owner of the YAML entry points. It has no fields and is never constructed.
Implementation SchemaYaml#
impl SchemaYamlAssociated function decode#
pub effect fn decode<T: Schema>(bytes: &[u8]) -> T ! SchemaError | OutOfMemoryError ? &mut AllocatorReads one value of type T from the YAML text bytes, stopping at the first problem.
Details#
The text must hold one YAML document. A text field also accepts a plain scalar that YAML reads as a number, a boolean, or null, and gets the text as written.
Errors#
SchemaErrorif the text is not valid YAML, holds more than one document, or does not hold aT. Itspathnames the part that failed, and its issue has the span of the bytes it is about. Invalid YAML givesIssueReason.InvalidSyntax.OutOfMemoryErrorif theAllocatorcannot supply the document or the value.
Associated function decodeAll#
pub effect fn decodeAll<T: Schema>(bytes: &[u8]) -> T ! SchemaErrors | OutOfMemoryError ? &mut AllocatorReads one value of type T from the YAML text bytes, reporting every problem.
Details#
A field, element or variant that fails is recorded and skipped, and reading goes on with the
next one, so one call lists every problem, in input order: a missing key, a wrong type, a
number out of range and a failed rule alike. Text that is not valid YAML is the one problem
reported. At most MAX_PROBLEMS (64) are listed.
Errors#
SchemaErrorswith every problem found.OutOfMemoryErrorif theAllocatorcannot supply the document or the value.
Associated function encode#
pub effect fn encode<T: Schema>(value: &T)
-> () ! SchemaError | WriterError | OutOfMemoryError ? &mut Writer | &mut AllocatorWrites value as block-style YAML to the ambient Writer.
Details#
Struct fields are written in declaration order, nested collections are indented by two
spaces, and strings are quoted only when a reader would read them as something else. The text
goes to the Writer in pieces of up to 4 KiB. It does not flush the Writer.
Errors#
SchemaErrorif the value nests more than 128 levels deep. Its path is empty.WriterErrorif theWriterfails. Bytes that it accepted before the failure stay written.OutOfMemoryErrorif a codec needs memory that theAllocatorcannot supply.
Examples#
import silk.collections.slice { Slice }
import silk.core.effect { Effect }
import silk.io.writer { Writer, WriterError }
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.schema.issue { SchemaError }
import silk.schema.schema { Schema }
import silk.schema.yaml { SchemaYaml }
struct Limits {
pub retries: u8,
}
impl Schema for Limits {}
struct Server {
pub port: u16,
pub limits: Limits,
}
impl Schema for Server {}
struct Capture {
bytes: [u8; 64],
length: usize,
}
impl Writer for Capture {
effect fn writeAll(self: &mut Self, val: &[u8]) -> () ! WriterError ? &mut Writer {
Slice.copyInto<u8>(&mut self.bytes, self.length, val)
self.length = self.length + val.length
return ()
}
effect fn flush(self: &mut Self) -> () ! WriterError ? &mut Writer { return () }
}
pub effect fn main() -> i32 ! SchemaError | WriterError | OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let mut capture = Capture {bytes: [0; 64], length: 0}
let server = Server {port: 8080, limits: Limits {retries: 3}}
run SchemaYaml.encode<Server>(&server) |> Effect.provideMut<Writer>(&mut capture)
|> Effect.provideMut<Allocator>(&mut allocator)
if Slice.view<u8>(&capture.bytes, 0, capture.length) != b"port: 8080\nlimits:\n retries: 3\n" {
return 1
}
return 0
}YamlSchemaReader#
pub struct YamlSchemaReader<'document>A SchemaReader over a node of a parsed silk.yaml.document.YamlDocument.
When to use#
SchemaYaml.decode uses it. Use it directly to read a typed value from one node of a document
that the program parsed itself, such as one document of a stream from
YamlDocument.parseAll: call Schemas.read with it.
Details#
A text field also accepts a plain scalar that YAML reads as a number, a boolean, or null, and gets the text as written. Spans in the problems are byte positions in the parsed text.
Implementation YamlSchemaReader<'document>#
impl<'document> YamlSchemaReader<'document>Associated function make#
pub fn make(document: &'document YamlDocument, node: YamlNode) -> YamlSchemaReader<'document>Returns a reader of the value at node of document, which stops at the first problem.
Associated function collectingAll#
pub fn collectingAll(document: &'document YamlDocument, node: YamlNode) -> YamlSchemaReader<'document>Returns a reader of the value at node of document that records every problem instead of
stopping at the first. Read them with YamlSchemaReader.intoErrors.
Method intoErrors#
pub fn intoErrors(self: Self) -> List<SchemaError>Returns the problems the reader recorded, in the order they were found.
Implementation YamlSchemaReader<'document>#
impl<'document> YamlSchemaReader<'document>Implementation SchemaReader for YamlSchemaReader<'document>#
impl<'document> SchemaReader for YamlSchemaReader<'document>Operation path#
fn path(self: &mut Self) -> &mut SchemaPathReturns the path of the part being read.
Operation report#
effect fn report(self: &mut Self, issue: Issue) -> () ! Issue | OutOfMemoryError ? &mut AllocatorFails with the issue, or records it and returns when the reader collects every problem.
Operation collecting#
fn collecting(self: &Self) -> boolReturns whether the reader records every problem.
Operation lastSpan#
fn lastSpan(self: &Self) -> Option<Span>Returns the span of the last complete value read.
Operation lastKind#
fn lastKind(self: &Self) -> ValueKindReturns the kind of the last complete value read.
Operation mark#
effect fn mark(self: &mut Self) -> usize ! OutOfMemoryError ? &mut AllocatorRemembers the open mappings and sequences and the node being read.
Operation recover#
effect fn recover(self: &mut Self, mark: usize, skip: bool) -> () ! Issue | OutOfMemoryError ? &mut AllocatorReturns to the mark, closing the mappings and sequences opened since. With skip, the value
at the mark becomes the last one read.
Operation release#
fn release(self: &mut Self, mark: usize) -> ()Forgets the mark and every later one.
Operation boolean#
effect fn boolean(self: &mut Self) -> bool ! Issue | OutOfMemoryError ? &mut AllocatorReads true or false.
Operation signed#
effect fn signed(self: &mut Self) -> i64 ! Issue | OutOfMemoryError ? &mut AllocatorReads an integer as an i64.
Operation unsigned#
effect fn unsigned(self: &mut Self) -> u64 ! Issue | OutOfMemoryError ? &mut AllocatorReads an integer as a u64.
Operation float#
effect fn float(self: &mut Self) -> f64 ! Issue | OutOfMemoryError ? &mut AllocatorReads an integer or a float as an f64.
Operation text#
effect fn text(self: &mut Self) -> String ! Issue | OutOfMemoryError ? &mut AllocatorReads a string, or the text of a plain scalar that YAML reads as a number, a boolean, or null.
Operation null#
effect fn null(self: &mut Self) -> bool ! Issue | OutOfMemoryError ? &mut AllocatorReads past a null value and returns true, or returns false for another value.
Operation beginList#
effect fn beginList(self: &mut Self) -> () ! Issue | OutOfMemoryError ? &mut AllocatorStarts reading a sequence.
Operation nextElement#
effect fn nextElement(self: &mut Self) -> bool ! Issue | OutOfMemoryError ? &mut AllocatorReturns true at the next item, or ends the sequence and returns false.
Operation beginObject#
effect fn beginObject(self: &mut Self) -> () ! Issue | OutOfMemoryError ? &mut AllocatorStarts reading a mapping.
Operation member#
effect fn member(self: &mut Self, key: string) -> bool ! Issue | OutOfMemoryError ? &mut AllocatorFinds the member key of the mapping and leaves the reader at its value. A missing key leaves
the start of the mapping as the last span.
Operation rejectUnread#
effect fn rejectUnread(self: &mut Self, expected: string<'static>) -> () ! Issue | OutOfMemoryError ? &mut AllocatorReports every member no member call found, at its key.
Operation endObject#
effect fn endObject(self: &mut Self) -> () ! Issue | OutOfMemoryError ? &mut AllocatorEnds the mapping being read.
YamlSchemaWriter#
pub struct YamlSchemaWriterA SchemaWriter that writes block-style YAML to the ambient Writer.
When to use#
SchemaYaml.encode uses it. Use it directly to write several values as the documents of one
stream: call Schemas.write for each, nextDocument between them, and finish at the end.
Gotchas#
The text is kept in a 4 KiB buffer; call finish after the last value, or the end of the text
stays in it.
Implementation YamlSchemaWriter#
impl YamlSchemaWriterAssociated function make#
pub fn make() -> YamlSchemaWriterReturns a writer at the start of the first document.
Method nextDocument#
pub effect fn nextDocument(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterEnds the current document with a --- line, so that the next value starts a new document.
Errors#
WriterErrorif theWriterfails while the buffer is written out.
Method finish#
pub effect fn finish(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterWrites the rest of the buffer to the Writer. It does not flush the Writer.
Errors#
WriterErrorif theWriterfails. Bytes that it accepted before the failure stay written.
Implementation SchemaWriter for YamlSchemaWriter#
impl SchemaWriter for YamlSchemaWriterOperation boolean#
effect fn boolean(self: &mut Self, value: bool) -> () ! Issue | WriterError ? &mut WriterWrites true or false.
Operation signed#
effect fn signed(self: &mut Self, value: i64) -> () ! Issue | WriterError ? &mut WriterWrites the integer in decimal.
Operation unsigned#
effect fn unsigned(self: &mut Self, value: u64) -> () ! Issue | WriterError ? &mut WriterWrites the integer in decimal.
Operation float#
effect fn float(self: &mut Self, value: f64) -> () ! Issue | WriterError ? &mut WriterWrites the number, with .nan, .inf, and -.inf for the values that are not finite.
Operation text#
effect fn text(self: &mut Self, value: string) -> () ! Issue | WriterError ? &mut WriterWrites the string, quoted only when a reader would read it as something else.
Operation null#
effect fn null(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterWrites null.
Operation beginList#
effect fn beginList(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterStarts a sequence.
Operation element#
effect fn element(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterStarts the next item, with - .
Operation endList#
effect fn endList(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterEnds the sequence; an empty one is written as [].
Operation beginObject#
effect fn beginObject(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterStarts a mapping.
Operation key#
effect fn key(self: &mut Self, name: string) -> () ! Issue | WriterError ? &mut WriterWrites the key of the next entry and :.
Operation endObject#
effect fn endObject(self: &mut Self) -> () ! Issue | WriterError ? &mut WriterEnds the mapping; an empty one is written as {}.
Category: Data formats.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.