sysl

Module

sysl.encoding

Fixed-width integers to and from bytes, at both byte orders.

Import import sysl.encoding

These are free functions at concrete widths, and that is exactly why they can exist. math/integer.sysl deliberately leaves swap_bytes out of the Bits trait, because every member of that trait must be total over every integer type and a u24 or a u4 has no byte order at all – a member working at u32 and not at u24 would turn a bound that was supposed to have proven an operation into a failure at somebody else’s instantiation. Nothing here is a trait member, so nothing here reopens that: get_u32_le names its width, and the widths that have a whole number of bytes are the only ones written.

Unsigned only. The signed read of the same bytes is a cast at the call site, and doubling a twelve-function surface to spare one cast is not a trade worth making.

Reading answers Option and writing answers bool, rather than trapping on a slice that is too short. Walking a buffer whose length came from somewhere else is the ordinary use, and running off the end of one is an expected condition there rather than a program’s mistake.

Index

base64_decode base64_decoded_len base64_encode base64_string get_u16_be get_u16_le get_u32_be get_u32_le get_u64_be get_u64_le hex_decode hex_decoded_len hex_encode hex_string put_u16_be put_u16_le put_u32_be put_u32_le put_u64_be put_u64_le Alphabet DecodeError Display for DecodeError

Functions

base64_decode

base64_decode(text: []const u8, out: []u8) -> Result[usize, DecodeError]

The bytes the text spells, written into out, and how many there were.

Six bits at a time into an accumulator, rather than a four-character group at a time, because the unpadded spellings end mid-group and a group-at-a-time reader needs a special case for each of them. Whole bytes fall out of the accumulator as they complete, and the two or four leftover bits at the end are the padding bits, which are discarded.

base64_decoded_len

base64_decoded_len(text: []const u8) -> usize

How many bytes base64_decode will write, so a caller can size the slice it lends. Trailing padding is discounted, so this answers the same number for the padded and unpadded spellings of one input.

base64_encode

base64_encode(bytes: []const u8, out: *Writer, alphabet: Alphabet, pad: bool)

Three bytes become four characters. The tail – one or two bytes left over – becomes two or three characters, padded out to four with = when padding was asked for.

base64_string

base64_string(bytes: []const u8, alphabet: Alphabet, pad: bool) -> string

The same, gathered into a string. Every character emitted is ASCII, so the bytes are valid UTF-8 by construction.

get_u16_be

get_u16_be(b: []const u8) -> Option[u16]

get_u16_le

get_u16_le(b: []const u8) -> Option[u16]

get_u32_be

get_u32_be(b: []const u8) -> Option[u32]

get_u32_le

get_u32_le(b: []const u8) -> Option[u32]

get_u64_be

get_u64_be(b: []const u8) -> Option[u64]

get_u64_le

get_u64_le(b: []const u8) -> Option[u64]

hex_decode

hex_decode(text: []const u8, out: []u8) -> Result[usize, DecodeError]

The bytes the text spells, written into out, and how many there were.

hex_decoded_len

hex_decoded_len(text: []const u8) -> usize

How many bytes hex_decode will write, so a caller can size the slice it lends.

Answers for the length alone and does not look at the content: a text of odd length has no whole number of bytes in it and hex_decode refuses it, but the halving is still the right size to have reserved.

hex_encode

hex_encode(bytes: []const u8, out: *Writer)

Two characters per byte, written straight through to the sink.

hex_string

hex_string(bytes: []const u8) -> string

The same, gathered into a string. Every byte emitted above is an ASCII digit, so the result is valid UTF-8 by construction and needs no validating pass.

put_u16_be

put_u16_be(b: []u8, v: u16) -> bool

put_u16_le

put_u16_le(b: []u8, v: u16) -> bool

put_u32_be

put_u32_be(b: []u8, v: u32) -> bool

put_u32_le

put_u32_le(b: []u8, v: u32) -> bool

put_u64_be

put_u64_be(b: []u8, v: u64) -> bool

put_u64_le

put_u64_le(b: []u8, v: u64) -> bool

Types

Alphabet

enum Alphabet
    Standard
    UrlSafe

Which of RFC 4648’s two alphabets. They differ only in the last two characters: +/ reads badly in a URL and in a filename, which is the whole reason the second exists.

DecodeError

enum DecodeError
    BadByte(at: usize)
    BadLength
    BadPadding(at: usize)
    Short(needed: usize)

Why a decode refused, at the granularity a caller can act on.

A type of its own rather than sysl.text‘s ParseError, which is about reading a number out of text. Two of that type’s four variants – Overflow and BadBase – can never occur here, and a caller matching on it would be told cases exist that cannot. The shape is copied deliberately: the variants are separated by what a caller would do about each and not by taxonomy.

BadByte and BadPadding carry the offset for the reason ParseError.BadDigit and Utf8Error do – a message naming where is worth writing and cannot be reconstructed afterwards. Short carries the length that would have been enough, so a caller can resize and retry in one step rather than discovering the requirement one byte at a time.

Implementations

Display for DecodeError

impl Display for DecodeError

The rendering, so that a refusal can be printed without matching on it.

Search

Esc
to navigate to open Esc to close