silk.git.pkt_line.

Read and write pkt-lines, the length-prefixed framing of the Git wire protocol.

When to use#

Use PktLine.read to walk the packets of a Git protocol message, such as the body of a git-upload-pack response, and PktLine.appendData with PktLine.appendFlush and PktLine.appendDelimiter to build a request body. Most programs use silk.git.remote, which does this for you.

Details#

Each packet starts with four hexadecimal digits that give its length, the four digits included. 0000 is a flush packet, 0001 a delimiter, and 0002 a response end. A longer length is a data packet of at most 65516 payload bytes. PktLine.read returns a Packet of offsets into the input, so nothing is copied. PktLine.line returns the payload without its final LF, the form in which most Git text lines are sent.

Errors#

  • PktLineError for a length that is not four hexadecimal digits, is 3, or runs past the input, and for a payload that is too long to write.

  • OutOfMemoryError from the append functions.

Examples#

Write two packets and read them back#

silk
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.collections.bytes { Bytes }
import silk.core.effect { Effect }
import silk.core.result { Result }
import silk.git.pkt_line { Packet, PacketKind, PktLine, PktLineError }

effect fn roundTrip() -> bool ! PktLineError | OutOfMemoryError ? &mut Allocator {
  let mut body = Bytes.make()
  run PktLine.appendData(&mut body, b"command=ls-refs\n")
  run PktLine.appendFlush(&mut body)
  let input = Bytes.asSlice(&body)
  let first = match PktLine.read(input, 0) {
    Result<Packet, PktLineError>.Success { value } => value
    Result<Packet, PktLineError>.Failure { error } => { fail move error }
  }
  let line = PktLine.line(input, &first)
  let second = match PktLine.read(input, first.next) {
    Result<Packet, PktLineError>.Success { value } => value
    Result<Packet, PktLineError>.Failure { error } => { fail move error }
  }
  let flushed = match second.kind {
    PacketKind.Flush => true
    _ => false
  }
  return line.length == 15 && flushed && second.next == input.length
}

pub effect fn main() -> i32 ! PktLineError | OutOfMemoryError {
  let mut allocator = Allocator.systemAllocatorProvider()
  if run roundTrip() |> Effect.provideMut<Allocator>(&mut allocator) {
    return 0
  }
  return 1
}

Import as PktLine with import silk.git.pkt_line { PktLine }.

Public declarations: 5.

MAX_PAYLOAD#

silk
pub const MAX_PAYLOAD: usize

The largest payload of one data packet, in bytes: 65520 minus the four length digits.

PacketKind#

silk
pub enum PacketKind

What a Packet is.

Data#

silk
Data

A data packet, 0005 or longer. Its payload is from start to end.

Flush#

silk
Flush

The flush packet 0000, which ends a message or a section.

Delimiter#

silk
Delimiter

The delimiter packet 0001, which separates sections in protocol version 2.

ResponseEnd#

silk
ResponseEnd

The response-end packet 0002, which ends a stateless response in protocol version 2.

Implementation Debug for PacketKind#

silk
impl Debug for PacketKind

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant, such as Flush.

Packet#

silk
pub struct Packet

One packet, as offsets into the input that PktLine.read read.

Details#

The payload is from start to end, after the four length digits. A packet that is not Data has an empty payload. The next packet starts at next.

Field kind#

silk
pub kind: PacketKind

What the packet is.

Field start#

silk
pub start: usize

The offset of the first payload byte.

Field end#

silk
pub end: usize

The offset after the last payload byte.

Field next#

silk
pub next: usize

The offset after the packet, where the next one starts.

Implementation Copy for Packet#

silk
impl Copy for Packet

PktLineError#

silk
pub union PktLineError

The reason that a PktLine function rejected its input.

Truncated#

silk
Truncated

The input ends inside the packet that starts at offset.

Field offset#

silk
pub offset: usize

The offset of the packet.

InvalidLength#

silk
InvalidLength

The length at offset is not four hexadecimal digits, or it is 3, which no packet has.

Field offset#

silk
pub offset: usize

The offset of the packet.

PayloadTooLong#

silk
PayloadTooLong

A payload to write is longer than MAX_PAYLOAD bytes.

Implementation Debug for PktLineError#

silk
impl Debug for PktLineError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the variant and its offset, such as Truncated { offset: 4 }.

PktLine#

silk
pub struct PktLine

Functions that read and write pkt-lines.

Implementation PktLine#

silk
impl PktLine

Associated function read#

silk
pub fn read(input: &[u8], offset: usize) -> Result<Packet, PktLineError>

Returns the packet that starts at offset of input.

Details#

The four length digits can be upper or lower case. Nothing is copied: the Packet holds offsets into input. Read the next packet at packet.next.

Errors#

  • Truncated if fewer than four bytes start at offset, or the payload runs past the end.

  • InvalidLength if the length is not four hexadecimal digits, or it is 3.

Associated function payload#

silk
pub fn payload<'a>(input: &'a [u8], packet: &Packet) -> &'a [u8]

Returns the payload of packet in input. It is empty for a packet that is not Data.

Associated function line#

silk
pub fn line<'a>(input: &'a [u8], packet: &Packet) -> &'a [u8]

Returns the payload of packet in input without its final LF, if it has one.

When to use#

Use it for the text lines of the protocol, which a sender may end with LF or not.

Associated function appendData#

silk
pub effect fn appendData(output: &mut Bytes, payload: &[u8]) -> ()
    ! PktLineError | OutOfMemoryError
    ? &mut Allocator

Appends a data packet with payload to output: its four length digits in lower case, then the payload.

Errors#

  • PayloadTooLong if payload has more than MAX_PAYLOAD bytes. output does not change.

  • OutOfMemoryError if the Allocator cannot grow output.

Associated function appendFlush#

silk
pub effect fn appendFlush(output: &mut Bytes) -> ()
    ! OutOfMemoryError
    ? &mut Allocator

Appends the flush packet 0000 to output.

Errors#

  • OutOfMemoryError if the Allocator cannot grow output.

Associated function appendDelimiter#

silk
pub effect fn appendDelimiter(output: &mut Bytes) -> ()
    ! OutOfMemoryError
    ? &mut Allocator

Appends the delimiter packet 0001 to output.

Errors#

  • OutOfMemoryError if the Allocator cannot grow output.

Category: Version control.

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.

View the source of this page