~/bend-docscommunity

trace_context.bend checks

raw source on the hub · import 0xb6eebf6253ee268a21f3e308b12cacba/trace_context.bend as Trace_context

bend-trace-context: the pure Trace Context core ===============================================

This file is the package's public entry for everything that performs no host effect: the strict traceparent v00 codec, validated trace and span IDs, local and remote contexts, the machine that turns source words into IDs, validated limits, the Level 2 tracestate parser, tracestate updates and emission, outgoing contexts, the extraction of a received message's context, the injection and forwarding of a context into an outgoing message's carrier, and the operations that continue or start a service's operation for a received message and give each message it sends a child of it. generation.bend adds the host's cryptographic source on top of it, and native_http.bend the header maps of bend-kit's native HTTP package. The claims this code must satisfy are stated in LAWS.bend and proved in PROOF.bend, beside this file. The tests in tests/*.bend here and the repository's consumer in tests/consumer exercise it through the same public names.

The normative reference is W3C Trace Context Level 2, Candidate Recommendation Draft of 2024-03-28 ("W3C" below, with section numbers). The approved specification is issue #1 of the repository ("spec #1").

Contents

Types every data type of the codec, contexts and generation, declared first Strict v00 codec Parse.*, TraceParentV00.* Identifiers and contexts TraceId, SpanId, contexts, children, restarts Identifiers from source words U32.to_hex, TraceId.from_words, ... Generation machine Draw.*, Step.*, Generation.*, Context.*_with, Source.tape Error messages Error.show, ContextError.show, ... Limits Limits.new, Limits.default, accessors Tracestate keys and values, states and lookups, budgets, and the reading machine behind TraceState.parse Tracestate updates and emission TraceState.set, remove, size and truncate Outgoing contexts OutgoingContext, a local context with the state it sends, and its Emission Extraction Context.extract, TraceParent.read, incoming and base contexts, diagnostics Injection Context.inject and the Injection it writes, Context.clear Forwarding Context.forward, ForwardError Continuing or starting Context.continue_or_start_with, Reception, FailurePolicy, Service, ServicePlan Sending Context.send_with, Sent, SendPlan

The public names are documented in packages/trace-context/README.md. Names in the Parse, Draw, Step, Tape, Scan, Member, Value, Budget, Utf8, Entries, StateChar, Carrier, Text, Read, Extract, Forward, Policy, Serve and Send namespaces are internal: Bend lets any module import them, but they are not a compatibility contract.

Notes for readers new to Bend -----------------------------

- type T is Data: declares a type whose values may be copied. Each indented line is a constructor with its fields, such as Some{value}. - A field whose type is an equation, such as evidence: {StateKey.is_valid(text) == True{} : Bool}, stores a proof. A value can only be built together with that proof, so the rule holds for every value a program handles, and code that receives one never checks it again. The checker verifies the proof when the program is compiled. The .checked helpers turn the result of a run-time check into such a proof: they receive the Bool and an equation stating what it is, and matching on the Bool refines that equation to ... == True{} in the accepting case. - Result<&2, &2, E, T> is Done{value} or Fail{error}, and Maybe<&2, T> is Some{value} or None{}. The &2 arguments say that the values may be copied. - A parameter may be used at most once unless it is marked +x (reusable). -x is erased: only the checker sees it. ~f is a template: its argument is substituted at compile time, so it names top-level definitions only. - match may only inspect a parameter or a variable bound by a pattern, never a computed value, and definitions may not call each other in a cycle. Many helpers therefore receive a Bool computed by their caller and match on it: Scan.read(comma, ...) receives Char.is_eq(char, ','), for example. - In every recursive call, the first argument that changes must be structurally smaller, so every function terminates. A recursion whose depth could grow with received text is written as a tail call, which compiles to a loop: the JavaScript backend overflows its stack after a few thousand nested calls, and a received value may be 32 KiB long. The other recursions are bounded: at most 32 digits, 256 characters of a key or value, 32 entries, or the characters of a field name sought. - do Result<...>: sequences steps that may fail: x : T <- step stops at the first Fail, and the block ends with return v or with a last step.

3 imports
import Base
import ./src/hex.bend as Hex
import ./src/digits.bend as Digits

Types

type Field source · line 104 · raw

Data

The field that a ZeroId error names: the trace ID or parent ID of a traceparent value, or a supplied span ID.

type Error source · line 128 · raw

Data

Why the strict codec, TraceId.parse, SpanId.parse or TraceParent.read refused a text. Offsets count Bend characters (Unicode code points) from zero at the start of the text, and the first problem in reading order is reported. UnexpectedEnd{offset} the text ends where a character is required InvalidHex{offset} this character is not a lowercase hex digit ExpectedSeparator{offset} this character should be "-" TrailingInput{} characters follow a complete value ForbiddenVersion{} the version is ff, forbidden by W3C 3.2.2.1 UnsupportedVersion{version} a version other than 00, which the strict codec does not read (TraceParent.read reads versions 01 to fe by their known prefix) ZeroId{field} the named ID is all zero, forbidden by W3C 3.2.2.3 and 3.2.2.4 ControlCharacter{offset} this character is a control character other than a horizontal tab, which no field value may hold (RFC 9110, section 5.5); only TraceParent.read reports it, in the fields of a later version that it does not read

type ContextError source · line 140 · raw

Data

Why creating a context from supplied IDs was refused: a child reused its parent's span ID, or a restart reused the received trace ID.

type Parsed source · line 147 · raw

@-n:Nat -> Data

A sequence of n digits read from the front of a text, with the text that remains after it. The length n is part of the type, so a reader of 32 digits can only produce 32.

type TraceParentV00 source · line 155 · raw

Data

A strict traceparent v00 value (W3C 3.2.2): a trace ID of 32 digits and a parent ID of 16 digits, each with a proof that it is not all zero, and a flag byte of two digits. Length and alphabet are structural: a value with a wrong length or a non-hexadecimal digit cannot be built. All eight flag bits are kept, including the reserved ones, so the codec is exact.

type TraceId source · line 167 · raw

Data

A validated trace ID: 32 lowercase hexadecimal digits, not all zero (W3C 3.2.2.3). random records whether the random-trace-id flag (W3C 3.2.2.5.2) may be emitted for it. A parsed ID makes no such assertion: only its origin can justify one. Generation sets it, and a caller who knows the ID is random sets it with TraceId.assert_random.

type SpanId source · line 173 · raw

Data

A validated span ID: 16 lowercase hexadecimal digits, not all zero, the identifier of one operation. It is sent as the parent ID of traceparent (W3C 3.2.2.4).

type Sampling source · line 179 · raw

Data

How a child operation obtains its sampled indication (W3C 3.2.2.5.1): InheritSampled{} keeps the parent's and SetSampled{sampled} sets it. The indication communicates a decision; it does not record anything.

type RemoteContext source · line 187 · raw

Data

A context received from another participant. It identifies the sender's operation and keeps only the known flags: sampled and random-trace-id. It is built from a received value (RemoteContext.from_traceparent) and has its own type, so it cannot be sent as if it were this participant's operation.

type LocalContext source · line 192 · raw

Data

A context that identifies an operation of this participant: the one it sends in its own headers. The Context.* operations build it.

type Parent source · line 197 · raw

Data

The context whose trace a child operation continues: a received context or one of this participant's own operations.

type GenerationError source · line 204 · raw

Data

Why generating identifiers failed. A source failure carries the source's own code and message; exhaustion names the identifier whose eight candidates were all rejected.

type TraceWords source · line 211 · raw

Data

The words read so far for the current trace ID candidate, in arrival order. Four words complete a candidate.

type SpanWords source · line 219 · raw

Data

The words read so far for the current span ID candidate. Two words complete a candidate.

type SpanPlan source · line 231 · raw

Data

The generation machine below is shared by the IO operations and stated in the laws. Its types and Draw functions are internal: callers use the Context.*_with operations or generation.bend, and a host that feeds words itself uses Generation.

What a new local context needs besides its span ID: the trace ID it belongs to, its sampled indication, and for a child the parent's span ID, which the new span ID must not repeat.

type Draw source · line 238 · raw

Data

A generation in progress: drawing the trace ID or the span ID. remaining counts the further candidates allowed after the current one, so each identifier gets eight candidates in all. previous is the received trace ID that a restart must not reuse.

type Step source · line 244 · raw

Data

The state of a generation after each source word: it needs another word, it created a context, or it failed.

type Generation source · line 256 · raw

Data

A generation with its word budget, for a host that feeds it one word at a time instead of passing a source as a template, such as JavaScript code calling this module: the words it may still read (fuel) and the machine's step. Its fields are internal, like Step: Generation.root and its siblings build one. Context.root_with and its siblings drive the same values, and a host that feeds words while Generation.needs says so gets the pure driver's result (law generation_drive).

type LimitsError source · line 1068 · raw

Data

Why a limit configuration was refused. The first failing rule is reported: TraceParentInputTooSmall{} the traceparent input budget is below 55 TraceStateOutputTooSmall{} the tracestate output budget is below 512 TraceStateInputTooSmall{} the tracestate input budget is below the output budget

type Limits source · line 1086 · raw

Data

Budgets in UTF-8 octets. The input budgets bound a received traceparent value and a combined tracestate value; the output budget is the most an emitted tracestate may take. evidence is the proof of Limits.is_valid, so every Limits value follows the rules.

type EntryError source · line 1163 · raw

Data

Why a tracestate key, value or received member was refused: MissingEquals{} a nonempty member has no "=" InvalidKey{} the text before the first "=" is not a key InvalidValue{} the text after it, without trailing optional whitespace, is not a value

type StateKey source · line 1249 · raw

Data

A tracestate key, naming the vendor that owns an entry. evidence proves the Level 2 key grammar for text, so a StateKey is always valid: build one with StateKey.parse (the negative fixture tests/reject/invalid_state_key.bend shows that direct construction with a wrong text does not compile).

type StateValue source · line 1254 · raw

Data

A tracestate value, opaque to every other vendor. evidence proves the Level 2 value grammar for text. Leading spaces are part of the value.

type StateError source · line 1321 · raw

Data

Why a received tracestate value was discarded: StateTooLarge{} the combined value exceeds its input budget TooManyMembers{} a 33rd nonempty member was reached InvalidEntry{member, error} a member is invalid; member numbers the comma-separated members of the combined value from zero, empty members included Discarding the state never invalidates a valid traceparent (spec #1).

type StateEntry source · line 1327 · raw

Data

One vendor's entry: a key and its value.

type TraceState source · line 1377 · raw

Data

Ordered vendor state: at most 32 entries with distinct keys, leftmost first. evidence proves both properties, so every TraceState has them (law state_valid).

type Member source · line 1519 · raw

Data

Where reading the current member stands: before its key, with only optional whitespace so far; inside its key; or inside its value. Characters read are kept most recent first, so each one costs a single step.

type Scan source · line 1528 · raw

Data

A tracestate being read: the members ended so far, empty ones included; how many more nonempty members are allowed; the current member; and the first entry of each key, in reading order. Stopped holds the first problem found. The scan and its helpers are internal.

type Truncation source · line 1859 · raw

Data

What truncation to the output budget kept, and the keys of the entries it dropped, in their original order. Reporting the keys, not the values, tells which vendors lost their state without repeating opaque data.

type OutgoingContext source · line 1960 · raw

Data

A local context and the state sent with it.

type Emission source · line 1967 · raw

Data

The two header values an outgoing context emits, and the keys of the entries that truncation to the output budget dropped, in their original order. A context with no state emits the tracestate "", which Context.inject does not write.

type TraceParentError source · line 2076 · raw

Data

Why extraction refused a message's traceparent: RepeatedTraceParent{} the message has more than one traceparent field, or a value that joins several with a comma TraceParentTooLarge{} the value exceeds the traceparent input budget InvalidTraceParent{error} the value breaks the rules of its version; error is the first problem, as the codec reports it, with offsets counted from the first character after optional whitespace The received value itself is never included.

type ReceivedPair source · line 2089 · raw

Data

The original fields of an accepted message: its traceparent value, without the optional whitespace around it, and its tracestate field values as they came, in arrival order, none when it had no tracestate field. They are what Context.forward sends. The input budgets bound the pairs that extraction keeps (law received_bounds); a pair built directly with this constructor carries no such guarantee, so forwarding checks what it sends. A pair that extraction kept is refused only when it exceeds the output budget (law forward_extracted).

type IncomingContext source · line 2097 · raw

Data

A context extracted from a message: the sender's operation, the state that came with it, and the received pair when the whole pair was accepted. It is not this participant's operation: a service continues it with a child (Context.child_from_id with IncomingContext.parent), or forwards the received pair unchanged (Context.forward).

type BaseContext source · line 2103 · raw

Data

The context to continue from that extraction keeps when a message carries no usable traceparent: a context received earlier, or an operation of this participant with the state it sends.

type TraceParentOutcome source · line 2109 · raw

Data

What extraction found in the traceparent fields of a message: an accepted value, no field, or a refusal with its reason.

type StateOutcome source · line 2123 · raw

Data

What extraction did with the tracestate fields of a message: StateAbsent{} there was no tracestate field StateAccepted{} the fields were read into the incoming state, which may be empty StateDiscarded{error} the fields were refused as a whole; the incoming context has no state and the traceparent stays accepted StateIgnored{} the fields were not read, because the message has no accepted traceparent (W3C 3.3)

type Extraction source · line 2132 · raw

Data

The result of extracting a message: the context to continue from, if any, and what happened to each field. context is the incoming context of the message when its traceparent was accepted, and the base otherwise.

type Injection source · line 2637 · raw

Data

The carrier an injection writes, and the keys of the entries that truncation to the output budget dropped from the state, in their original order: diagnostics, kept apart from the carrier.

type ForwardError source · line 2738 · raw

Data

Why a received context could not be forwarded unchanged: NothingToForward{} it keeps no received pair: its tracestate was discarded when it was extracted ForwardTooLarge{} its tracestate fields, joined by commas, exceed the tracestate output budget InvalidForwardParent{error} its traceparent value is not one that TraceParent.read accepts InvalidForwardState{error} its tracestate fields are not ones that TraceState.parse_fields accepts A pair that extraction keeps always passes the last two checks (law forward_extracted); they refuse a pair built directly.

type Reception source · line 2855 · raw

Data

How a service takes the context that extraction keeps, the message's or the base: Continue{} continue it with a child Restart{} replace it with a new trace, as at a trust boundary: its trace ID is not reused, its state is discarded and the root defaults apply

type FailurePolicy source · line 2863 · raw

Data

What the operations do when generating an identifier fails: Lenient{} carry on without a new operation; the result says why Strict{} fail with the GenerationError, so that the caller can refuse the operation

type Origin source · line 2871 · raw

Data

How a service's operation came about: Continued{} a child of the context that extraction kept Started{} a root: extraction kept no context Restarted{} a new trace in place of the kept context (Restart{})

type Service source · line 2881 · raw

Data

The service's own operation for a received message, with the state it sends, or the error that left it without one. received is the message's incoming context when the service continues it, kept so that a message it sends can forward the received pair if generating fails; it is None{} for a root, a restart or a continued base.

type ServicePlan source · line 2945 · raw

Data

The service's operation as Context.continue_or_start_with decides it for a received message, before it reads any word: the generation to drive and what the generation's result makes of the service. ContinuePlan{generation, state, received} a child of the kept context, sending its state StartPlan{generation, origin, sampling} a root or a restart A host that feeds a generation one word at a time, such as JavaScript code calling this module, drives ServicePlan.generation and hands the result to ServicePlan.service (law hosted_service).

type Unforwarded source · line 3056 · raw

Data

Why a message without a new operation does not forward a received pair: NothingKept{} the service keeps no received context: its operation is, or was to be, a root, a restart or a child of a base ForwardFailed{error} Context.forward refused the received context with error

type Sent source · line 3068 · raw

Data

The context fields of one message and how they came about: Fresh{operation, injection} a new operation, injected with the service's state Forwarded{carrier, error} no operation could be generated (error); the received pair is forwarded unchanged NoContext{carrier, error, no operation could be generated, and no reason} pair was forwarded (reason): the context fields are cleared

type SendPlan source · line 3113 · raw

Data

A message's operation as Context.send_with decides it before it reads any word, with the limits and the carrier to send it with: SendChild{generation, limits, outgoing, received, carrier} a child of the service's operation, injected with the service's state SendFallback{error, limits, received, carrier} no operation, for a service without one: the fallback, reading no word A host that feeds a generation one word at a time drives SendPlan.generation and hands the result to SendPlan.sent (law hosted_send).

Definitions

def Parsed.prepend source · line 268 · raw

@-n:Nat -> @digit:0xb6eebf6253ee268a21f3e308b12cacba/src/hex.Digit -> @parsed:Parsed<n> -> Parsed<1n+n>

Put one more digit in front of a parsed sequence: n digits become 1 + n.

def Parse.digit_result source · line 275 · raw

@value:Maybe<&2, 0xb6eebf6253ee268a21f3e308b12cacba/src/hex.Digit> -> @offset:Nat -> Result<&2, &2, Error, 0xb6eebf6253ee268a21f3e308b12cacba/src/hex.Digit>

A decoded character, or InvalidHex at its offset when it is not a lowercase hexadecimal digit.

def Parse.digit source · line 284 · raw

@char:Char -> @offset:Nat -> Result<&2, &2, Error, 0xb6eebf6253ee268a21f3e308b12cacba/src/hex.Digit>

Decode one character as a lowercase hexadecimal digit.

def Parse.digits source · line 290 · raw

@n:Nat -> @text:String -> @offset:Nat -> Result<&2, &2, Error, Parsed<n>>

Consume exactly n characters as digits, keeping the unconsumed rest of the text. The recursion decreases n, so no length check or unchecked conversion is needed: the result's type already has length n.

def Parse.separator_result source · line 307 · raw

@tail:String -> @ok:Bool -> @offset:Nat -> Result<&2, &2, Error, String>

The rest of the text after a "-", or ExpectedSeparator at its offset.

def Parse.separator source · line 316 · raw

@text:String -> @offset:Nat -> Result<&2, &2, Error, String>

Read the "-" expected at offset.

def Parse.end source · line 325 · raw

@text:String -> Result<&2, &2, Error, Unit>

The value must end here. Only the first character after it is inspected, so an arbitrarily long suffix is refused without being read.

def Parse.version source · line 334 · raw

@digits:0xb6eebf6253ee268a21f3e308b12cacba/src/digits.Digits(2n) -> Result<&2, &2, Error, Unit>

The version digits: 00 is the only version the strict codec reads, ff is forbidden (W3C 3.2.2.1), and any other version is reported with its text.

def Parse.nonzero_result source · line 345 · raw

@-n:Nat -> @result:Maybe<&2, 0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<n>> -> @field:Field -> Result<&2, &2, Error, 0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<n>>

Attach the proof that digits are not all zero, or fail with ZeroId naming the field.

def Parse.nonzero source · line 354 · raw

@n:Nat -> @digits:0xb6eebf6253ee268a21f3e308b12cacba/src/digits.Digits(n) -> @field:Field -> Result<&2, &2, Error, 0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<n>>

Check that digits are not all zero (W3C 3.2.2.3, 3.2.2.4).

def Parse.flags source · line 359 · raw

@trace_id:0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<32n> -> @parent_id:0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<16n> -> @parsed:Parsed<2n> -> Result<&2, &2, Error, TraceParentV00>

The last field: the two flag digits, then the end of the text.

def Parse.parent source · line 369 · raw

@trace_id:0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<32n> -> @parsed:Parsed<16n> -> Result<&2, &2, Error, TraceParentV00>

After the trace ID: the parent ID, which must not be all zero, its "-" at offset 52 and the flag digits at offset 53.

def Parse.trace source · line 381 · raw

@parsed:Parsed<32n> -> Result<&2, &2, Error, TraceParentV00>

After the version: the trace ID, which must not be all zero, its "-" at offset 35 and the parent ID from offset 36.

def Parse.start source · line 392 · raw

@parsed:Parsed<2n> -> Result<&2, &2, Error, TraceParentV00>

After the two version digits: the version check, the "-" at offset 2 and the trace ID from offset 3.

def TraceParentV00.parse source · line 409 · raw

@text:String -> Result<&2, &2, Error, TraceParentV00>

Parse a strict traceparent v00 value: exactly "00-", 32 lowercase hexadecimal digits, "-", 16 digits, "-" and two digits; the IDs must not be all zero. No whitespace, case folding or suffix is accepted, and every flag byte is kept as received. This is the strict wire codec, not a complete W3C propagator: TraceParent.read and Context.extract apply the processing rules of W3C 3.2.4 and 4.1.2, such as reading later versions by their known prefix. Laws: roundtrip, inverse and formatted_length.

def TraceParentV00.format source · line 418 · raw

@context:TraceParentV00 -> String

The text of a strict v00 value: always 55 characters. It is total, because validity is carried by the argument's type, and it preserves every flag bit: it is the exact inverse of parse, not an outgoing-header policy (see LocalContext.to_traceparent for what a participant emits).

def TraceParentV00.is_sampled source · line 426 · raw

@context:TraceParentV00 -> Bool

Whether the sampled flag, bit 0 of the flag byte, is set (W3C 3.2.2.5.1).

def TraceParentV00.is_random source · line 434 · raw

@context:TraceParentV00 -> Bool

Whether the random-trace-id flag, bit 1, is set (W3C 3.2.2.5.2). It records the sender's assertion; it does not prove how the trace ID was generated.

def Parse.id.finish source · line 449 · raw

@n:Nat -> @parsed:Parsed<n> -> @field:Field -> Result<&2, &2, Error, 0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<n>>

The digits of a supplied ID must be the whole text, and not all zero.

def Parse.id source · line 458 · raw

@+n:Nat -> @text:String -> @field:Field -> Result<&2, &2, Error, 0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<n>>

A supplied ID is exactly n lowercase hexadecimal digits, not all zero.

def TraceId.parse source · line 467 · raw

@text:String -> Result<&2, &2, Error, TraceId>

Parse a supplied trace ID: exactly 32 lowercase hexadecimal digits, not all zero. Error offsets count from the start of the ID. The result makes no randomness assertion (laws trace_id_parse and trace_id_accepts).

def TraceId.assert_random source · line 475 · raw

@id:TraceId -> TraceId

Record the caller's assertion that these digits were generated randomly, so that the random-trace-id flag is emitted with them. The caller is responsible for the assertion; validation cannot establish it (law assert_random).

def TraceId.is_random source · line 481 · raw

@id:TraceId -> Bool

Whether the trace ID asserts that it was generated randomly.

def TraceId.to_string source · line 487 · raw

@id:TraceId -> String

The 32 lowercase hexadecimal digits of the trace ID.

def TraceId.is_eq source · line 494 · raw

@a:TraceId -> @b:TraceId -> Bool

Whether two trace IDs name the same trace. The randomness assertion is not part of the identifier, so it is ignored.

def SpanId.parse source · line 499 · raw

@text:String -> Result<&2, &2, Error, SpanId>

Parse a supplied span ID: exactly 16 lowercase hexadecimal digits, not all zero (laws span_id_parse and span_id_roundtrip).

def SpanId.to_string source · line 505 · raw

@id:SpanId -> String

The 16 lowercase hexadecimal digits of the span ID.

def SpanId.is_eq source · line 511 · raw

@a:SpanId -> @b:SpanId -> Bool

Whether two span IDs name the same operation.

def Sampling.resolve source · line 516 · raw

@sampling:Sampling -> @inherited:Bool -> Bool

The sampled indication a child receives: the inherited one, unless the caller set another (law sampling).

def RemoteContext.from_traceparent source · line 526 · raw

@value:TraceParentV00 -> RemoteContext

Interpret a received strict-v00 value as the sender's context. Bit 0 is sampled and bit 1 is random-trace-id; the reserved bits are not interpreted and do not travel with the context (law received_flags).

def RemoteContext.trace_id source · line 534 · raw

@context:RemoteContext -> TraceId

The trace the received context belongs to.

def RemoteContext.span_id source · line 540 · raw

@context:RemoteContext -> SpanId

The sender's operation: the parent ID of the received value.

def RemoteContext.is_sampled source · line 546 · raw

@context:RemoteContext -> Bool

The sender's sampled indication.

def LocalContext.trace_id source · line 552 · raw

@context:LocalContext -> TraceId

The trace this participant's operation belongs to.

def LocalContext.span_id source · line 558 · raw

@context:LocalContext -> SpanId

This participant's operation.

def LocalContext.is_sampled source · line 564 · raw

@context:LocalContext -> Bool

The sampled indication this participant sends.

def LocalContext.to_traceparent source · line 572 · raw

@context:LocalContext -> TraceParentV00

The participating representation of a local context: version 00, and flags limited to sampled (bit 0) and random-trace-id (bit 1), with every reserved bit zero (W3C 3.2.2.5.3; laws emitted_traceparent and emitted_projection).

def Parent.trace_id source · line 579 · raw

@parent:Parent -> TraceId

The trace a child continues.

def Parent.span_id source · line 587 · raw

@parent:Parent -> SpanId

The parent's operation, which a child must not reuse.

def Parent.is_sampled source · line 595 · raw

@parent:Parent -> Bool

The sampled indication a child inherits by default.

def Context.from_ids source · line 605 · raw

@trace_id:TraceId -> @span_id:SpanId -> @sampled:Bool -> LocalContext

Represent an operation the caller owns, with supplied IDs and an explicit sampled indication. The IDs must belong to that operation: validating their format cannot establish where they came from (law from_ids).

def Context.root_from_ids source · line 611 · raw

@trace_id:TraceId -> @span_id:SpanId -> LocalContext

Start a trace with supplied IDs. A new root is not sampled (spec #1: "New roots default to sampled 0"; law root). generation.bend provides Context.root, Context.child and Context.restart for generated IDs.

def Context.child_from_id.checked source · line 615 · raw

@trace_id:TraceId -> @span_id:SpanId -> @sampled:Bool -> @reused:Bool -> Result<&2, &2, ContextError, LocalContext>

The child, unless the span ID was found equal to the parent's.

def Context.child_from_id source · line 627 · raw

@+parent:Parent -> @+span_id:SpanId -> @sampling:Sampling -> Result<&2, &2, ContextError, LocalContext>

Continue the parent's trace with a new operation identified by a supplied span ID. The child keeps the trace ID and its randomness assertion, and its span ID must differ from the parent's (ReusedSpanId otherwise). Sampling is inherited unless set. Laws: child, child_reuse and child_accepts.

def Context.restart_from_ids.checked source · line 634 · raw

@trace_id:TraceId -> @span_id:SpanId -> @reused:Bool -> Result<&2, &2, ContextError, LocalContext>

The restarted root, unless the trace ID was found equal to the received one.

def Context.restart_from_ids source · line 646 · raw

@previous:RemoteContext -> @+trace_id:TraceId -> @span_id:SpanId -> Result<&2, &2, ContextError, LocalContext>

Start a new trace with supplied IDs instead of continuing a received context. The new trace ID must differ from the received one (ReusedTraceId otherwise), and the root defaults apply, sampled 0 included. Laws: restart, restart_reuse and restart_accepts.

def U32.to_hex source · line 660 · raw

@word:U32 -> String

The eight lowercase hexadecimal digits of a word, most significant first (laws hex_injective and word_hex).

def TraceId.from_digits source · line 664 · raw

@value:Maybe<&2, 0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<32n>> -> Maybe<&2, TraceId>

A trace ID from nonzero digits, with no randomness assertion.

def TraceId.from_words source · line 675 · raw

@first:U32 -> @second:U32 -> @third:U32 -> @fourth:U32 -> Maybe<&2, TraceId>

A trace ID from four words, read most significant first: the first word gives the first eight digits. Like a parsed ID it makes no randomness assertion; add one with TraceId.assert_random when the words are random. An all-zero candidate is None (laws trace_words and words_unasserted).

def SpanId.from_digits source · line 682 · raw

@value:Maybe<&2, 0xb6eebf6253ee268a21f3e308b12cacba/src/digits.NonZero<16n>> -> Maybe<&2, SpanId>

A span ID from nonzero digits.

def SpanId.from_words source · line 691 · raw

@first:U32 -> @second:U32 -> Maybe<&2, SpanId>

A span ID from two words, most significant first. An all-zero candidate is None (law span_words).

def Draw.root source · line 706 · raw

Step

A root draws its trace ID, then its span ID, and starts unsampled. Seven further candidates follow the first, eight in all.

def Draw.restart source · line 710 · raw

@previous:RemoteContext -> Step

A restart draws like a root but must not reuse the received trace ID.

def Draw.child source · line 715 · raw

@+parent:Parent -> @sampling:Sampling -> Step

A child keeps the parent's trace ID and draws a span ID other than the parent's.

def Draw.retry_trace source · line 721 · raw

@remaining:Nat -> @previous:Maybe<&2, TraceId> -> Step

Try another trace ID candidate, or fail once the eight are used.

def Draw.accept_trace source · line 730 · raw

@trace_id:TraceId -> Step

An accepted trace ID is followed by the span ID, with the root default sampled indication.

def Draw.reuse_trace source · line 734 · raw

@reused:Bool -> @id:TraceId -> @previous:TraceId -> @remaining:Nat -> Step

A trace ID candidate equal to the received one is retried.

def Draw.check_trace source · line 743 · raw

@candidate:Maybe<&2, TraceId> -> @previous:Maybe<&2, TraceId> -> @remaining:Nat -> Step

Check a complete trace ID candidate: zero and, for a restart, the received trace ID are retried; anything else is accepted.

def Draw.retry_span source · line 755 · raw

@remaining:Nat -> @plan:SpanPlan -> Step

Try another span ID candidate, or fail once the eight are used.

def Draw.accept_span source · line 763 · raw

@id:SpanId -> @plan:SpanPlan -> Step

An accepted span ID completes the new local context.

def Draw.reuse_span source · line 769 · raw

@reused:Bool -> @id:SpanId -> @plan:SpanPlan -> @remaining:Nat -> Step

A span ID candidate equal to the parent's is retried.

def Draw.check_span source · line 778 · raw

@candidate:Maybe<&2, SpanId> -> @plan:SpanPlan -> @remaining:Nat -> Step

Check a complete span ID candidate: zero and, for a child, the parent's span ID are retried; anything else is accepted.

def Draw.asserted source · line 791 · raw

@candidate:Maybe<&2, TraceId> -> Maybe<&2, TraceId>

Generation reads its words from a source trusted to be random, so each trace ID candidate asserts random-trace-id.

def Draw.feed source · line 801 · raw

@word:Result<&1, &1, Pair(U32, String), U32> -> @draw:Draw -> Step

Feed the next source word to the machine. A source error ends the generation at once with SourceFailure (law feed_failure); a word completes or extends the current candidate.

def Step.result source · line 824 · raw

@step:Step -> Result<&2, &2, GenerationError, LocalContext>

The result of a finished generation. A generation that has not finished would report the identifier it was drawing; the root_ends, child_ends and restart_ends laws show that the word budgets of the operations below make those cases unreachable.

def Step.is_finished source · line 836 · raw

@step:Step -> Bool

Whether a generation has ended, with or without a context.

def Tape.next source · line 847 · raw

@tape:List<&1, Result<&1, &1, Pair(U32, String), U32>> -> Pair(List<&1, Result<&1, &1, Pair(U32, String), U32>>, Result<&1, &1, Pair(U32, String), U32>)

A deterministic word source for tests and replay: each read takes the next result, and an empty tape fails with code 1, tape-exhausted.

def Draw.fed_by source · line 856 · raw

@-S:Type -> @got:Pair(S, Result<&1, &1, Pair(U32, String), U32>) -> @draw:Draw -> Pair(S, Step)

Feed a word that a source returned, keeping the source's next state.

def Draw.ended source · line 861 · raw

@result:Pair(List<&1, Result<&1, &1, Pair(U32, String), U32>>, Step) -> Bool

Whether the generation in a driver's result has ended.

def Draw.run source · line 868 · raw

@fuel:Nat -> @current:Pair(List<&1, Result<&1, &1, Pair(U32, String), U32>>, Step) -> Pair(List<&1, Result<&1, &1, Pair(U32, String), U32>>, Step)

Drive a generation from a tape, reading one word at a time and stopping as soon as it ends; unread words stay on the tape. fuel bounds the steps, which Bend requires for termination; the laws show the budgets suffice.

def Draw.outcome source · line 900 · raw

@-S:Type -> @done:Pair(S, Step) -> Pair(S, Result<&2, &2, GenerationError, LocalContext>)

The source's final state with the generation's result.

def Generation.root source · line 911 · raw

Generation

A root: at most 48 words, eight trace ID candidates of four words and eight span ID candidates of two.

def Generation.restart source · line 915 · raw

@previous:RemoteContext -> Generation

A restart replacing previous: at most 48 words, as a root.

def Generation.child source · line 919 · raw

@+parent:Parent -> @sampling:Sampling -> Generation

A child of parent: at most 16 words, eight span ID candidates.

def Generation.needs.of source · line 923 · raw

@fuel:Nat -> @step:Step -> Bool

Whether a step needs another word within fuel more words.

def Generation.needs source · line 936 · raw

@generation:Generation -> Bool

Whether the generation needs another word: it has not ended, and its budget allows one more.

def Generation.fed source · line 943 · raw

@fuel:Nat -> @step:Step -> @word:Result<&1, &1, Pair(U32, String), U32> -> Generation

The generation after word: the step it gives with one word less of budget, or, for a step that needs no word, the same step with none left.

def Generation.feed source · line 956 · raw

@generation:Generation -> @word:Result<&1, &1, Pair(U32, String), U32> -> Generation

Feed the generation the next word of its source (see Draw.feed). A generation that needs no word ignores it.

def Generation.result source · line 965 · raw

@generation:Generation -> Result<&2, &2, GenerationError, LocalContext>

The generation's result: the context it created, or why it failed. One that still needs a word once its budget is spent has exhausted its candidates; the root_ends, child_ends and restart_ends laws show that the budgets suffice.

def Source.tape source · line 1000 · raw

@tape:List<&1, Result<&1, &1, Pair(U32, String), U32>> -> IO(Pair(List<&1, Result<&1, &1, Pair(U32, String), U32>>, Result<&1, &1, Pair(U32, String), U32>))

A deterministic source that replays a tape of word results.

def Error.show source · line 1014 · raw

@error:Error -> String

The name of a codec or ID error, with its offset or, for an unsupported version, its two digits. ZeroId names the field: ZeroTraceId, ZeroParentId or ZeroSpanId.

def ContextError.show source · line 1038 · raw

@error:ContextError -> String

The name of a context creation error.

def GenerationError.show source · line 1047 · raw

@error:GenerationError -> String

The name of a generation error; a source failure adds the source's code and message.

def Limits.is_valid source · line 1078 · raw

@traceparent_input:Nat -> @tracestate_input:Nat -> @+tracestate_output:Nat -> Bool

The rules of a configuration, which must accept its own emitted representation: a traceparent input budget of at least 55 octets, the length of a v00 value, and a tracestate input budget no smaller than an output budget of at least 512 octets (spec #1, "Tracestate policy and resource bounds"; the 512-octet minimum comes from #8; law limits_bounds).

def Limits.error source · line 1095 · raw

@traceparent_input:Nat -> @tracestate_output:Nat -> LimitsError

The first rule a refused configuration breaks.

def Limits.new.checked source · line 1101 · raw

@traceparent_input:Nat -> @tracestate_input:Nat -> @tracestate_output:Nat -> @valid:Bool -> @evidence:{Limits.is_valid(traceparent_input, tracestate_input, tracestate_output) == valid : Bool} -> Result<&2, &2, LimitsError, Limits>

The configuration, when the check found it valid.

def Limits.new source · line 1112 · raw

@+traceparent_input:Nat -> @+tracestate_input:Nat -> @+tracestate_output:Nat -> Result<&2, &2, LimitsError, Limits>

Validate a configuration; budgets count UTF-8 octets (laws limits_new and limits_fields).

def Limits.default source · line 1120 · raw

Limits

32 KiB for each received value and 512 octets for an emitted tracestate (law default_limits). The 512-octet output budget is this package's capacity policy, not a W3C maximum.

def Limits.traceparent_input source · line 1124 · raw

@limits:Limits -> Nat

The most octets a received traceparent value may take.

def Limits.tracestate_input source · line 1131 · raw

@limits:Limits -> Nat

The most octets a combined tracestate value may take, including the commas that join repeated fields.

def Limits.tracestate_output source · line 1137 · raw

@limits:Limits -> Nat

The most octets an emitted tracestate may take.

def LimitsError.show source · line 1143 · raw

@error:LimitsError -> String

The name of a limits error.

def StateChar.in_range source · line 1169 · raw

@+code:U32 -> @low:U32 -> @high:U32 -> Bool

Whether a code point lies between two others, both included.

def StateChar.is_key_start source · line 1174 · raw

@char:Char -> Bool

lcalpha / DIGIT: a lowercase ASCII letter (%x61-7A) or a digit (%x30-39), the first character of a key.

def StateChar.is_key source · line 1180 · raw

@+char:Char -> Bool

keychar: lcalpha / DIGIT / "_" / "-" / "*" / "/" / "@".

def StateChar.is_value_end source · line 1186 · raw

@char:Char -> Bool

nblk-chr: %x21-2B / %x2D-3C / %x3E-7E, printable ASCII other than space, "," and "=". A value ends with one of these.

def StateChar.is_value source · line 1193 · raw

@+char:Char -> Bool

chr: %x20 / nblk-chr, a character of a value: nblk-chr or a space.

def StateChar.is_ows source · line 1197 · raw

@+char:Char -> Bool

OWS: a space or a horizontal tab (RFC 9110, section 5.6.3).

def StateKey.valid.rest source · line 1203 · raw

@text:String -> @room:Nat -> Bool

Every remaining character is a key character, and at most room remain. The recursion stops once the room is used up, so a huge invalid key is not read to its end.

def StateKey.is_valid source · line 1216 · raw

@text:String -> Bool

key = ( lcalpha / DIGIT ) 0*255( keychar ): 1 to 256 characters (W3C 3.3.2.2.1). Level 1's tenant@system restriction does not apply.

def StateValue.valid.go source · line 1225 · raw

@tail:String -> @char:Char -> @room:Nat -> Bool

char is a value character followed by tail, of which at most room characters are allowed; the last character is not a space.

def StateValue.is_valid source · line 1238 · raw

@text:String -> Bool

value = 0*255( chr ) nblk-chr: 1 to 256 printable ASCII characters other than "," and "=", the last of which is not a space (W3C 3.3.2.2.2).

def StateKey.parse.checked source · line 1258 · raw

@text:String -> @valid:Bool -> @evidence:{StateKey.is_valid(text) == valid : Bool} -> Result<&2, &2, EntryError, StateKey>

The key, when the check found the text valid.

def StateKey.parse source · line 1268 · raw

@+text:String -> Result<&2, &2, EntryError, StateKey>

Accept exactly a Level 2 key, or fail with InvalidKey. Nothing is trimmed or folded (laws key_parse, key_roundtrip and key_separators).

def StateKey.to_string source · line 1272 · raw

@key:StateKey -> String

The key's text.

def StateValue.parse.checked source · line 1278 · raw

@text:String -> @valid:Bool -> @evidence:{StateValue.is_valid(text) == valid : Bool} -> Result<&2, &2, EntryError, StateValue>

The value, when the check found the text valid.

def StateValue.parse source · line 1289 · raw

@+text:String -> Result<&2, &2, EntryError, StateValue>

Accept exactly a Level 2 value, leading spaces included, or fail with InvalidValue. No whitespace is trimmed here, so a trailing space is refused (laws value_parse, value_roundtrip and value_separators).

def StateValue.to_string source · line 1293 · raw

@value:StateValue -> String

The value's text.

def EntryError.show source · line 1299 · raw

@error:EntryError -> String

The name of an entry error.

def StateEntry.key source · line 1331 · raw

@entry:StateEntry -> StateKey

The entry's key.

def StateEntry.value source · line 1337 · raw

@entry:StateEntry -> StateValue

The entry's value.

def StateEntry.key_text source · line 1343 · raw

@entry:StateEntry -> String

The text of the entry's key.

def StateEntry.format source · line 1347 · raw

@entry:StateEntry -> String

key=value, as the entry is sent.

def Entries.has_key source · line 1353 · raw

@entries:List<&2, StateEntry> -> @+key:String -> Bool

Whether one of the entries has this key.

def Entries.unique source · line 1362 · raw

@entries:List<&2, StateEntry> -> @+seen:List<&2, StateEntry> -> Bool

No entry repeats the key of an entry before it; seen holds the entries already passed. This is the order in which the reading machine checks keys.

def TraceState.is_valid source · line 1371 · raw

@+entries:List<&2, StateEntry> -> Bool

Distinct keys and at most 32 entries (W3C 3.3.2 and 3.3.3).

def TraceState.empty source · line 1381 · raw

TraceState

The state with no entries. It formats as "".

def TraceState.entries source · line 1385 · raw

@state:TraceState -> List<&2, StateEntry>

The entries in order, leftmost first.

def TraceState.is_empty source · line 1391 · raw

@state:TraceState -> Bool

Whether the state has no entries.

def Entries.get.put source · line 1395 · raw

@entry:StateEntry -> @rest:Maybe<&2, StateValue> -> @hit:Bool -> Maybe<&2, StateValue>

The value of entry when its key matched, or the result for the rest.

def Entries.get source · line 1403 · raw

@entries:List<&2, StateEntry> -> @+key:String -> Maybe<&2, StateValue>

The value of the first entry with this key.

def TraceState.get source · line 1412 · raw

@state:TraceState -> @key:StateKey -> Maybe<&2, StateValue>

The value of the entry with this key, if there is one (laws get_entry and get_absent). The key is validated, so a lookup never needs to check it.

def Entries.format.rest source · line 1416 · raw

@entries:List<&2, StateEntry> -> String

Each entry after the first, preceded by its comma.

def Entries.format source · line 1424 · raw

@entries:List<&2, StateEntry> -> String

The entries as key=value, joined by commas.

def TraceState.format source · line 1434 · raw

@state:TraceState -> String

The normalized value: the entries in order, joined by commas, with no optional whitespace. The empty state formats as "" (laws state_roundtrip and first_wins).

def Utf8.width source · line 1446 · raw

@char:Char -> Nat

The UTF-8 octets of a character. Bend characters are Unicode code points, so this is the size of the character's UTF-8 encoding: 1 to 4.

def Utf8.length source · line 1457 · raw

@text:String -> Nat

The UTF-8 octets of a text, in which the laws state every budget. Emission measures keys and values with it, at most 256 characters each; parsing measures received text with Utf8.left instead, which stops counting past the budget.

def Budget.take source · line 1466 · raw

@need:Nat -> @budget:Nat -> Maybe<&2, Nat>

What is left of a budget after taking need octets, or None when less remains.

def Utf8.left source · line 1478 · raw

@text:String -> @budget:Maybe<&2, Nat> -> Maybe<&2, Nat>

What is left of a budget after a text, or None once the text exceeds it. Measuring stops at the first character beyond the budget, and a None budget stays None.

def Utf8.left_more source · line 1489 · raw

@fields:List<&2, String> -> @budget:Maybe<&2, Nat> -> Maybe<&2, Nat>

Fields after the first are measured with the comma that joins them. Once the budget is exceeded, no further field is visited.

def Utf8.left_fields source · line 1500 · raw

@fields:List<&2, String> -> @budget:Maybe<&2, Nat> -> Maybe<&2, Nat>

What is left of a budget after repeated fields and the commas that join them.

def Value.restore.step source · line 1535 · raw

@kept:Bool -> @ows:Bool -> @char:Char -> @value:String -> Pair(Bool, String)

A value's characters arrive most recent first. Restoring them skips optional whitespace until the first other character, then keeps every character, so the value comes back in reading order without its trailing whitespace.

def Value.restore.go source · line 1548 · raw

@text:String -> @state:Pair(Bool, String) -> String

The restoring loop: one character at a time, with the state (whether a character was kept yet, the value so far).

def Value.restore source · line 1558 · raw

@text:String -> String

The value in reading order without its trailing optional whitespace.

def Member.start source · line 1564 · raw

@ows:Bool -> @equals:Bool -> @char:Char -> Member

A character of a member that has no key yet: optional whitespace is skipped, an "=" gives the member an empty key, which validation refuses, and anything else starts the key.

def Member.key source · line 1577 · raw

@equals:Bool -> @char:Char -> @text:String -> Member

A character inside a key: the first "=" ends the key, anything else extends it. Key characters are validated when the member ends.

def Member.push source · line 1586 · raw

@+char:Char -> @current:Member -> Member

A character other than a comma extends the current member. Inside a value every character is kept; validation refuses those the grammar excludes.

def Scan.validate source · line 1597 · raw

@key:String -> @value:String -> Result<&2, &2, EntryError, StateEntry>

Validate the key and value texts of a member that ended. An invalid key is reported before an invalid value.

def Entries.add.if source · line 1605 · raw

@entries:List<&2, StateEntry> -> @entry:StateEntry -> @present:Bool -> List<&2, StateEntry>

Keep the entries unchanged when the key was present; otherwise add the entry at the end.

def Entries.add source · line 1614 · raw

@+entries:List<&2, StateEntry> -> @+entry:StateEntry -> List<&2, StateEntry>

Keep only the first entry of each key (spec #1, "Preserve the first occurrence of a duplicate key").

def Scan.keep source · line 1619 · raw

@room:Nat -> @member:Nat -> @entry:StateEntry -> @entries:List<&2, StateEntry> -> Scan

A valid member counts toward the 32 allowed before duplicates are dropped (spec #1); with no room left, the state is discarded with TooManyMembers.

def Scan.entry source · line 1628 · raw

@parsed:Result<&2, &2, EntryError, StateEntry> -> @member:Nat -> @room:Nat -> @entries:List<&2, StateEntry> -> Scan

A member that ended: an invalid one stops reading with its number and reason; a valid one is counted and kept.

def Scan.close source · line 1640 · raw

@member:Nat -> @room:Nat -> @current:Member -> @entries:List<&2, StateEntry> -> Scan

The current member ends at a comma or with the value. An empty member, or one of optional whitespace only, is ignored but still numbered; a member without "=" is refused; otherwise its key and value are validated, trailing optional whitespace left out of the value.

def Scan.read source · line 1651 · raw

@comma:Bool -> @char:Char -> @member:Nat -> @room:Nat -> @current:Member -> @entries:List<&2, StateEntry> -> Scan

One character of a scan that is still reading: a comma ends the member, and anything else extends it.

def Scan.char source · line 1660 · raw

@+char:Char -> @scan:Scan -> Scan

Read one character, unless the scan has stopped.

def Scan.text source · line 1669 · raw

@text:String -> @scan:Scan -> Scan

Read a text one character at a time, stopping at the first problem. This is a loop (a tail call), so its depth does not grow with the text.

def Scan.more source · line 1679 · raw

@fields:List<&2, String> -> @scan:Scan -> Scan

Fields after the first are read after the comma that joins them.

def Scan.fields source · line 1687 · raw

@fields:List<&2, String> -> @scan:Scan -> Scan

Read repeated fields as their comma-joined combination.

def Scan.start source · line 1695 · raw

Scan

The scan of a new value: no member ended, 32 allowed, nothing kept.

def Scan.state source · line 1702 · raw

@entries:List<&2, StateEntry> -> @valid:Bool -> @evidence:{TraceState.is_valid(entries) == valid : Bool} -> Result<&2, &2, StateError, TraceState>

The scan keeps only the first entry of each key and stops at a 33rd member, so this check is not expected to fail: the laws prove it passes for normalized values, and the corpus exercises the rest. A failure would be reported as too many members.

def Scan.result source · line 1712 · raw

@scan:Scan -> Result<&2, &2, StateError, TraceState>

The state read, once the last member has ended. TraceState.is_valid is checked here to build the state's evidence.

def Scan.finish source · line 1720 · raw

@scan:Scan -> Result<&2, &2, StateError, TraceState>

The last member ends with the value.

def Scan.within source · line 1728 · raw

@fits:Maybe<&2, Nat> -> @fields:List<&2, String> -> Result<&2, &2, StateError, TraceState>

Read the fields only when they fit the budget.

def TraceState.parse_fields source · line 1747 · raw

@limits:Limits -> @+fields:List<&2, String> -> Result<&2, &2, StateError, TraceState>

Parse repeated tracestate field values, in arrival order, as their comma-joined combination (W3C 3.3.2). The combined value, joining commas included, must fit the tracestate input budget; a larger one is refused with StateTooLarge before any member is read, without measuring the rest. Then: empty members are ignored, and so is optional whitespace before a member and after its value; every nonempty member must be a valid entry (InvalidEntry) and counts toward the 32 allowed (TooManyMembers); the first entry of each key is kept. An error discards the whole state; a valid traceparent stays valid (spec #1). W3C 3.3: parse tracestate only for a message whose traceparent was parsed. Laws: fields_join, over_budget, within_budgets, first_wins and the others of section 10 of LAWS.bend.

def TraceState.parse source · line 1751 · raw

@limits:Limits -> @text:String -> Result<&2, &2, StateError, TraceState>

Parse one combined tracestate value; see TraceState.parse_fields.

def StateError.show source · line 1756 · raw

@error:StateError -> String

The name of a tracestate error; InvalidEntry adds the member number and the reason.

def Entries.unless source · line 1775 · raw

@-A:Data -> @skip:Bool -> @item:A -> @rest:List<&2, A> -> List<&2, A>

item followed by rest, unless skip is True: one step of a filter. Removing a key and listing the dropped keys both use it.

def Entries.without source · line 1783 · raw

@entries:List<&2, StateEntry> -> @+key:String -> List<&2, StateEntry>

The entries without the one whose key is key, in order.

def TraceState.from_entries.checked source · line 1794 · raw

@entries:List<&2, StateEntry> -> @fallback:TraceState -> @valid:Bool -> @evidence:{TraceState.is_valid(entries) == valid : Bool} -> TraceState

The state of these entries when the check finds them valid, fallback otherwise. Updates build their entries so that the check passes, which the laws prove; fallback keeps the function total without an unchecked conversion.

def TraceState.from_entries source · line 1803 · raw

@+entries:List<&2, StateEntry> -> @fallback:TraceState -> TraceState

The state of entries, checked, or fallback if the check fails.

def TraceState.set source · line 1811 · raw

@+state:TraceState -> @+key:StateKey -> @value:StateValue -> TraceState

Add or update the entry of key (W3C 3.5): it goes to the front with value, and the other entries follow in their order. At most 31 of them stay, so a new key in a full state removes the last entry, while updating a key that is present evicts nothing (laws set_entries, update_keeps_all, insert_entries and set_get).

def TraceState.remove source · line 1819 · raw

@+state:TraceState -> @key:StateKey -> TraceState

Delete the entry of key, if there is one; the other entries keep their order (W3C 3.5; laws remove_entries and remove_get). W3C asks participants not to delete keys other vendors generated: that breaks correlation in their systems.

def StateEntry.size source · line 1831 · raw

@entry:StateEntry -> Nat

The octets of key=value (law entry_size).

def Entries.size.rest source · line 1837 · raw

@entries:List<&2, StateEntry> -> Nat

The octets of each entry after the first, with its comma.

def Entries.size source · line 1845 · raw

@entries:List<&2, StateEntry> -> Nat

The octets of the entries joined by commas, as Entries.format writes them.

def TraceState.size source · line 1853 · raw

@state:TraceState -> Nat

The octets of TraceState.format(state) (law state_size).

def Truncation.kept source · line 1863 · raw

@truncation:Truncation -> TraceState

The state that fits the output budget.

def Truncation.dropped source · line 1870 · raw

@truncation:Truncation -> List<&2, StateKey>

The keys of the entries removed, in their original order; none when the state already fitted.

def StateEntry.is_large source · line 1877 · raw

@entry:StateEntry -> Bool

Whether the entry is larger than 128 octets. W3C 3.3.3.1 asks to remove such entries first.

def Entries.has_large source · line 1881 · raw

@entries:List<&2, StateEntry> -> Bool

Whether one of the entries is larger than 128 octets.

def Entries.drop_last_large source · line 1890 · raw

@entries:List<&2, StateEntry> -> List<&2, StateEntry>

The entries without the rightmost one larger than 128 octets: an entry stays when a large entry follows it.

def Entries.drop_last source · line 1899 · raw

@entries:List<&2, StateEntry> -> List<&2, StateEntry>

The entries without the rightmost one.

def Entries.shrink source · line 1909 · raw

@+entries:List<&2, StateEntry> -> List<&2, StateEntry>

One removal step (spec #1): the rightmost entry larger than 128 octets, or the rightmost entry when none is.

def Entries.truncate source · line 1917 · raw

@fuel:Nat -> @+budget:Nat -> @+entries:List<&2, StateEntry> -> List<&2, StateEntry>

Remove entries one step at a time while they take more than budget octets, and stop as soon as they fit. fuel bounds the steps. One per entry suffices: once every entry is removed, the empty list takes 0 octets, which fits any budget.

def Entries.dropped source · line 1926 · raw

@entries:List<&2, StateEntry> -> @+kept:List<&2, StateEntry> -> List<&2, StateKey>

The keys of the entries that kept lacks, in order.

def TraceState.truncate source · line 1940 · raw

@limits:Limits -> @state:TraceState -> Truncation

Fit a state to the output budget of limits by removing whole entries (W3C 3.3.3.1, spec #1): while the value is over the budget, remove the rightmost entry larger than 128 octets, or the rightmost entry when none is, and stop as soon as it fits. The surviving entries keep their order (laws truncate_steps, truncate_fits, truncate_whole, truncate_order and truncate_dropped).

def OutgoingContext.new source · line 1971 · raw

@context:LocalContext -> OutgoingContext

An outgoing context with no state yet, as for a new root.

def OutgoingContext.with_state source · line 1977 · raw

@context:LocalContext -> @state:TraceState -> OutgoingContext

An outgoing context that sends state, such as the state received with the parent of a child operation. The caller associates the state with this operation, as with Context.from_ids.

def OutgoingContext.context source · line 1981 · raw

@outgoing:OutgoingContext -> LocalContext

The local operation.

def OutgoingContext.state source · line 1987 · raw

@outgoing:OutgoingContext -> TraceState

The state sent with the operation.

def OutgoingContext.get source · line 1993 · raw

@outgoing:OutgoingContext -> @key:StateKey -> Maybe<&2, StateValue>

The value of the entry with this key, if there is one.

def OutgoingContext.set source · line 1998 · raw

@outgoing:OutgoingContext -> @key:StateKey -> @value:StateValue -> OutgoingContext

Add or update an entry (see TraceState.set); the context is unchanged (law outgoing_set).

def OutgoingContext.remove source · line 2005 · raw

@outgoing:OutgoingContext -> @key:StateKey -> OutgoingContext

Delete an entry (see TraceState.remove); the context is unchanged (law outgoing_remove).

def Emission.of source · line 2011 · raw

@context:LocalContext -> @truncation:Truncation -> Emission

The emission of a context and a truncated state.

def OutgoingContext.emit source · line 2020 · raw

@limits:Limits -> @outgoing:OutgoingContext -> Emission

The traceparent and tracestate values to send: the participating traceparent of the context, and the normalized value of the state truncated to the output budget of limits (laws emit_traceparent, emit_tracestate, emit_fits and emit_accepted).

def Emission.traceparent source · line 2026 · raw

@emission:Emission -> String

The traceparent value: always 55 characters.

def Emission.tracestate source · line 2032 · raw

@emission:Emission -> String

The tracestate value: at most the output budget in octets, "" for no state.

def Emission.dropped source · line 2038 · raw

@emission:Emission -> List<&2, StateKey>

The keys of the entries truncation dropped, in their original order.

def Header.name source · line 2142 · raw

@header:Header -> String

The field's name.

def Header.value source · line 2148 · raw

@header:Header -> String

The field's value.

def Carrier.named source · line 2159 · raw

@name:String -> @text:String -> Bool

Whether text is name without regard to ASCII case (W3C 3.2.1 and 3.3.1): each character of text, with the letters A to Z lowered, is the character of name at its position. Other characters are compared as they are, so a name that differs by more than ASCII case names another field. name is written in lowercase, and the comparison follows it, so a long field name is not read past it.

def Carrier.keep source · line 2171 · raw

@hit:Bool -> @value:String -> @found:List<&2, String> -> List<&2, String>

value before found when hit is True: one step of Carrier.values.

def Carrier.values.go source · line 2179 · raw

@carrier:List<&2, Header> -> @+name:String -> @found:List<&2, String> -> List<&2, String>

The values of the fields named name, most recent first, before found.

def Carrier.values source · line 2189 · raw

@carrier:List<&2, Header> -> @+name:String -> List<&2, String>

The values of the fields named name without regard to ASCII case, in their order: the loop collects them most recent first, and reversing, also a loop, puts them back in order.

def Text.drop_ows.go source · line 2203 · raw

@tail:String -> @head:Char -> @ows:Bool -> String

head followed by tail, without the optional whitespace at its start: ows says whether head is optional whitespace.

def Text.drop_ows source · line 2216 · raw

@text:String -> String

The text without the optional whitespace, spaces and horizontal tabs, at its start.

def Text.trim_ows source · line 2227 · raw

@text:String -> String

The text without the optional whitespace at its start and at its end (RFC 9110, section 5.5: "A field value does not include leading or trailing whitespace"). Reversing brings the end to the front, and reversing again brings it back.

def Text.has_comma.go source · line 2232 · raw

@text:String -> @found:Bool -> Bool

Whether the text contains a comma: found records whether one was seen before.

def Text.has_comma source · line 2242 · raw

@text:String -> Bool

Whether the text contains a comma.

def Text.is_control source · line 2249 · raw

@char:Char -> Bool

Whether a character is a control character other than a horizontal tab: U+0000 to U+0008, U+000A to U+001F or U+007F. No field value may hold one (RFC 9110, section 5.5); a carriage return or a line feed would end the field.

def Text.control.go source · line 2256 · raw

@text:String -> @+offset:Nat -> @found:Maybe<&2, Nat> -> Maybe<&2, Nat>

The offset of the first control character of text, counted from offset, unless found already holds one. This is a loop.

def Read.is_later source · line 2269 · raw

@digits:0xb6eebf6253ee268a21f3e308b12cacba/src/digits.Digits(2n) -> Result<&2, &2, Error, Bool>

Whether a value's version, from its two digits, is later than 00 and so read by its known prefix (W3C 3.2.2.1 and 3.2.4): Done{False{}} for 00, which the strict codec reads, Done{True{}} for 01 to fe, and a refusal for ff.

def Read.is_later.parsed source · line 2279 · raw

@parsed:Parsed<2n> -> Result<&2, &2, Error, Bool>

Whether the version whose two digits were read is later than 00.

def Read.clean source · line 2286 · raw

@found:Maybe<&2, Nat> -> Result<&2, &2, Error, Unit>

The fields a later version does not know, once searched for a control character: none, or the offset of the first.

def Read.extension source · line 2300 · raw

@rest:String -> Result<&2, &2, Error, Unit>

What may follow the flags of a later version: the end of the value, or a dash that starts fields this version does not know. Those fields are not read (W3C 3.2.4: "Vendors MUST NOT parse or assume anything about unknown fields"), except that a control character in them is refused with ControlCharacter at its offset: no field value may hold one (RFC 9110, section 5.5), and a value forwarded unchanged must not end a message's field. Any other character than a dash at offset 55 is ExpectedSeparator.

def Read.prefix source · line 2314 · raw

@+text:String -> Result<&2, &2, Error, TraceParentV00>

A later version is read by its known prefix (W3C 3.2.4 and 4.1.2): its first 55 characters are read as version 00, which checks the trace ID, the parent ID, the flags and the dashes between them at their own offsets, and then the value must end or continue with a dash. A value that ends before its 55th character, with no invalid character before, fails with UnexpectedEnd.

def Read.by_version source · line 2321 · raw

@later:Bool -> @text:String -> Result<&2, &2, Error, TraceParentV00>

Read a value by the rules of its version: later is False for 00.

def Read.known source · line 2329 · raw

@+text:String -> Result<&2, &2, Error, TraceParentV00>

The known fields of a value, read by the rules of its version.

def Read.invalid source · line 2336 · raw

@result:Result<&2, &2, Error, TraceParentV00> -> Result<&2, &2, TraceParentError, TraceParentV00>

A refusal of the codec, as a refused traceparent.

def Read.single source · line 2346 · raw

@combined:Bool -> @text:String -> Result<&2, &2, TraceParentError, TraceParentV00>

A value that joins several with a comma is refused as repeated fields; any other value is read by the rules of its version.

def Read.trimmed source · line 2354 · raw

@+text:String -> Result<&2, &2, TraceParentError, TraceParentV00>

A value without the whitespace around it, refused when it joins several.

def Read.within source · line 2359 · raw

@fits:Maybe<&2, Nat> -> @value:String -> Result<&2, &2, TraceParentError, TraceParentV00>

A value within its budget is read without the optional whitespace around it; a value over the budget is refused without being read further.

def TraceParent.read source · line 2386 · raw

@limits:Limits -> @+value:String -> Result<&2, &2, TraceParentError, TraceParentV00>

Read one received traceparent value by the rules of a participant, and return its known fields as a v00 value, flag byte included: - a value over the traceparent input budget of limits, counted in UTF-8 octets with its whitespace, is refused with TraceParentTooLarge; - optional whitespace around the value is removed (RFC 9110, section 5.5); - a value with a comma joins repeated fields and is refused with RepeatedTraceParent, even when the comma is in fields of a later version: no version defines a comma, and a host that joins repeated fields separates them with one (RFC 9110, section 5.3); - version 00 is read exactly by TraceParentV00.parse: 55 characters and nothing after them; - version ff is refused with ForbiddenVersion (W3C 3.2.2.1); - versions 01 to fe are read by their known prefix: the fields of version 00, followed by the end of the value or by a dash and fields that are not read, whatever they hold other than a comma or a control character, which is refused with ControlCharacter (W3C 3.2.4 and 4.1.2; RFC 9110, section 5.5). RemoteContext.from_traceparent then keeps the sampled and random-trace-id flags. Laws: read_v00, read_v00_exact, read_future, read_ff, read_comma, read_over_budget and read_within_budgets.

def Extract.ignored source · line 2398 · raw

@states:List<&2, String> -> StateOutcome

The state outcome when the tracestate fields are not read: absent without a field, ignored with one (W3C 3.3).

def Extract.kept source · line 2407 · raw

@base:Maybe<&2, BaseContext> -> @parent:TraceParentOutcome -> @states:List<&2, String> -> Extraction

The extraction of a message whose context is not read: the base is kept, with the traceparent outcome and the presence of tracestate fields.

def Extract.incoming source · line 2412 · raw

@remote:RemoteContext -> @state:TraceState -> @received:Maybe<&2, ReceivedPair> -> Maybe<&2, BaseContext>

The incoming context of an accepted message, as the context to continue from.

def Extract.parsed source · line 2420 · raw

@parsed:Result<&2, &2, StateError, TraceState> -> @remote:RemoteContext -> @text:String -> @states:List<&2, String> -> Extraction

An accepted message whose tracestate fields were parsed: an accepted state keeps the pair, which can be forwarded, and a refused one is discarded whole, keeping the traceparent (spec #1) but no pair, since the pair was not accepted whole.

def Extract.state source · line 2431 · raw

@+limits:Limits -> @+states:List<&2, String> -> @remote:RemoteContext -> @text:String -> Extraction

An accepted message with its tracestate field values, read in arrival order as their comma-joined combination (W3C 3.3.2).

def Extract.read source · line 2442 · raw

@read:Result<&2, &2, TraceParentError, TraceParentV00> -> @value:String -> @+limits:Limits -> @+states:List<&2, String> -> @base:Maybe<&2, BaseContext> -> Extraction

The extraction of a message whose only traceparent value value was read. The value is kept without the whitespace around it only once accepted, so a refused value is not read further.

def Extract.parents source · line 2452 · raw

@+limits:Limits -> @parents:List<&2, String> -> @+states:List<&2, String> -> @base:Maybe<&2, BaseContext> -> Extraction

The extraction of a message with these traceparent and tracestate field values.

def Context.extract source · line 2477 · raw

@+limits:Limits -> @+carrier:List<&2, Header> -> @base:Maybe<&2, BaseContext> -> Extraction

Extract the trace context of a received message from its carrier, with base as the context to keep when the message has no usable traceparent (spec #1, user stories 14, 15, 16, 24 and 25): - no traceparent field keeps the base, TraceParentAbsent{}; - more than one traceparent field, whatever the case of their names, is refused, and so is a single value that TraceParent.read refuses; the base is kept, TraceParentRejected{error}; - an accepted value gives the incoming context and replaces the base: its tracestate fields, whatever the case of their names, are read in arrival order as their comma-joined combination, within the tracestate input budget; refused fields are discarded whole, keeping the traceparent; - without an accepted traceparent, tracestate fields are not read. Laws: extract_absent, extract_repeated, extract_refused, extract_read, state_independent and received_bounds.

def Extraction.context source · line 2485 · raw

@extraction:Extraction -> Maybe<&2, BaseContext>

The context to continue from: this message's incoming context when its traceparent was accepted, the base otherwise.

def Extraction.parent source · line 2491 · raw

@extraction:Extraction -> TraceParentOutcome

What extraction found in the traceparent fields.

def Extraction.state source · line 2497 · raw

@extraction:Extraction -> StateOutcome

What extraction did with the tracestate fields.

def Extraction.incoming.base source · line 2503 · raw

@context:Maybe<&2, BaseContext> -> Maybe<&2, IncomingContext>

The incoming context an accepted message gives as its context.

def Extraction.incoming.of source · line 2512 · raw

@parent:TraceParentOutcome -> @context:Maybe<&2, BaseContext> -> Maybe<&2, IncomingContext>

This message's own context: the incoming context when its traceparent was accepted, None{} when extraction kept the base.

def Extraction.incoming source · line 2524 · raw

@extraction:Extraction -> Maybe<&2, IncomingContext>

The context this message carried, when its traceparent was accepted; None{} when extraction kept the base, even an incoming one.

def IncomingContext.context source · line 2530 · raw

@incoming:IncomingContext -> RemoteContext

The sender's operation.

def IncomingContext.state source · line 2537 · raw

@incoming:IncomingContext -> TraceState

The state received with it: empty when the message had none or when it was discarded.

def IncomingContext.received source · line 2544 · raw

@incoming:IncomingContext -> Maybe<&2, ReceivedPair>

The received pair, when the whole pair was accepted: None{} when the tracestate was discarded.

def IncomingContext.parent source · line 2550 · raw

@incoming:IncomingContext -> Parent

The received context as the parent of a child operation.

def ReceivedPair.traceparent source · line 2554 · raw

@pair:ReceivedPair -> String

The received traceparent value, without the whitespace around it.

def ReceivedPair.tracestate source · line 2560 · raw

@pair:ReceivedPair -> List<&2, String>

The received tracestate field values, in arrival order.

def BaseContext.parent source · line 2567 · raw

@base:BaseContext -> Parent

The base as the parent of a child operation: a received context or an operation of this participant.

def BaseContext.state source · line 2576 · raw

@base:BaseContext -> TraceState

The state that goes with the base: the state received with an incoming context, or the state an outgoing context sends.

def TraceParentError.show source · line 2584 · raw

@error:TraceParentError -> String

The name of a traceparent error; InvalidTraceParent adds the codec's error.

def TraceParentOutcome.show source · line 2594 · raw

@outcome:TraceParentOutcome -> String

The name of a traceparent outcome; a rejection adds its error.

def StateOutcome.show source · line 2604 · raw

@outcome:StateOutcome -> String

The name of a tracestate outcome; a discard adds its error.

def Extraction.show source · line 2618 · raw

@extraction:Extraction -> String

Both outcomes of an extraction, for a log line: "TraceParentAccepted, StateDiscarded InvalidEntry 1 MissingEquals" for example. No received value is included, so the line can be logged as it is.

def Carrier.is_context source · line 2642 · raw

@+name:String -> Bool

Whether a field name is traceparent or tracestate, without regard to ASCII case.

def Carrier.keep_unrelated source · line 2647 · raw

@context_field:Bool -> @header:Header -> @kept:List<&2, Header> -> List<&2, Header>

header before kept unless it is a context field (context_field): one step of Carrier.unrelated.go.

def Carrier.unrelated.go source · line 2657 · raw

@carrier:List<&2, Header> -> @kept:List<&2, Header> -> List<&2, Header>

The unrelated fields, those that are not context fields, most recent first, before kept. This is a loop, so a message with many fields needs no deep stack.

def Carrier.replace source · line 2666 · raw

@carrier:List<&2, Header> -> @fields:List<&2, Header> -> List<&2, Header>

The carrier's unrelated fields, followed by fields: reversing the loop's result onto fields, also a loop, puts them back in order.

def Carrier.context_fields source · line 2671 · raw

@traceparent:String -> @+tracestate:String -> List<&2, Header>

The context fields of a traceparent value and a tracestate value, with lowercase names; the tracestate field is left out when its value is empty.

def Context.clear source · line 2679 · raw

@carrier:List<&2, Header> -> List<&2, Header>

Remove every traceparent and tracestate field, whatever the case of its name, and keep the other fields in their order: the carrier of a message sent without context (spec #1, "Provide explicit context-field cleanup for the no-context path"). Law: clear_carrier.

def Injection.of source · line 2683 · raw

@carrier:List<&2, Header> -> @emission:Emission -> Injection

The injection of an emission into a carrier.

def Context.inject source · line 2697 · raw

@limits:Limits -> @outgoing:OutgoingContext -> @carrier:List<&2, Header> -> Injection

Write an outgoing context into a carrier as a participant: the context fields of the carrier are replaced by the emitted traceparent, version 00 with only the sampled and random-trace-id flags, and the emitted tracestate, truncated to the output budget of limits and left out when empty. The other fields keep their order, and injecting the same context into the carrier written gives that carrier again. A receiver that extracts the carrier with the same limits continues the injected operation with the truncated state. Laws: inject_carrier, inject_dropped, inject_idempotent and inject_extracted.

def Injection.carrier source · line 2701 · raw

@injection:Injection -> List<&2, Header>

The carrier to send.

def Injection.dropped source · line 2708 · raw

@injection:Injection -> List<&2, StateKey>

The keys of the entries truncation dropped, in their original order; none when the state fitted.

def Text.joined.go source · line 2746 · raw

@fields:List<&2, String> -> @done:String -> String

The fields joined by commas, most recent character first, after done: each field is reversed onto the comma before it. This is a loop.

def Text.joined source · line 2756 · raw

@fields:List<&2, String> -> String

The fields joined by commas into one value, as String.join(fields, ",") writes it. It is built by loops, so fields of any length need no deep stack.

def Forward.carrier source · line 2766 · raw

@carrier:List<&2, Header> -> @traceparent:String -> @tracestate:List<&2, String> -> List<&2, Header>

The carrier with its context fields replaced by a received pair: the traceparent value, and the tracestate fields joined into one value, left out when empty.

def Forward.state source · line 2770 · raw

@parsed:Result<&2, &2, StateError, TraceState> -> @carrier:List<&2, Header> -> @traceparent:String -> @tracestate:List<&2, String> -> Result<&2, &2, ForwardError, List<&2, Header>>

The last check of a forwarded pair: its tracestate fields parse.

def Forward.parent source · line 2779 · raw

@read:Result<&2, &2, TraceParentError, TraceParentV00> -> @+limits:Limits -> @carrier:List<&2, Header> -> @traceparent:String -> @+tracestate:List<&2, String> -> Result<&2, &2, ForwardError, List<&2, Header>>

The second check of a forwarded pair: its traceparent value reads back.

def Forward.fits source · line 2789 · raw

@fits:Maybe<&2, Nat> -> @+limits:Limits -> @carrier:List<&2, Header> -> @+traceparent:String -> @+tracestate:List<&2, String> -> Result<&2, &2, ForwardError, List<&2, Header>>

The first check of a forwarded pair: its tracestate fields, joined by commas, fit the output budget. Measuring stops past the budget.

def Forward.pair source · line 2798 · raw

@+limits:Limits -> @received:Maybe<&2, ReceivedPair> -> @carrier:List<&2, Header> -> Result<&2, &2, ForwardError, List<&2, Header>>

Forward the received pair, if there is one.

def Context.forward source · line 2818 · raw

@+limits:Limits -> @incoming:IncomingContext -> @carrier:List<&2, Header> -> Result<&2, &2, ForwardError, List<&2, Header>>

Forward a received context unchanged into a carrier: its context fields are replaced by the traceparent value of the received pair and by its tracestate fields joined into one field, and the other fields keep their order. The pair must be there, its tracestate must fit the output budget of limits whole, and both fields must read back under limits; otherwise forwarding fails with a ForwardError and writes nothing, so a received traceparent never travels with an edited or truncated tracestate (W3C 3.4). The pair of a context that extraction accepted is refused only when its tracestate exceeds the output budget, and forwarding again into the carrier written gives that carrier again. Laws: forward_carrier, forward_nothing, forward_too_large, forward_extracted and forward_idempotent.

def ForwardError.show source · line 2823 · raw

@error:ForwardError -> String

The name of a forwarding error; an invalid field adds its error.

def FailurePolicy.result source · line 2887 · raw

@policy:FailurePolicy -> @A:Data -> Data

The type an operation returns under policy: the value itself with Lenient{}, and the value or the GenerationError with Strict{}.

def Policy.apply source · line 2896 · raw

@policy:FailurePolicy -> @-A:Data -> @strict:(@_:A -> Result<&2, &2, GenerationError, A>) -> @value:A -> FailurePolicy.result(policy, A)

A value under policy: itself with Lenient{}, and what strict makes of it with Strict{}.

def Policy.apply.done source · line 2905 · raw

@-S:Type -> @policy:FailurePolicy -> @-A:Data -> @strict:(@_:A -> Result<&2, &2, GenerationError, A>) -> @done:Pair(S, A) -> Pair(S, FailurePolicy.result(policy, A))

The source's final state with a value under policy.

def Serve.start source · line 2913 · raw

@sampling:Sampling -> @+context:LocalContext -> LocalContext

A new trace's operation with the sampled indication that sampling resolves from the root default, not sampled: InheritSampled{} has nothing to inherit, and SetSampled{} sets its own.

def Serve.from_child source · line 2918 · raw

@state:TraceState -> @received:Maybe<&2, IncomingContext> -> @result:Result<&2, &2, GenerationError, LocalContext> -> Service

The service that a child of the kept context gives, with state, or Untraced with the error.

def Serve.from_start source · line 2928 · raw

@origin:Origin -> @sampling:Sampling -> @result:Result<&2, &2, GenerationError, LocalContext> -> Service

The service that a new trace gives: the sampling of Serve.start and no state, or Untraced with the error. A new trace keeps no received pair.

def Serve.replaced source · line 2952 · raw

@base:BaseContext -> RemoteContext

The context that a restart replaces, as Generation.restart takes it: an incoming base's received context, or an outgoing base's operation as another participant receives it. The new trace ID reuses neither.

def Serve.usable source · line 2961 · raw

@+base:BaseContext -> @received:Maybe<&2, IncomingContext> -> @reception:Reception -> @sampling:Sampling -> ServicePlan

Continue the kept context with a child, with its parent and state, or replace it with a new trace, as reception says.

def Serve.kept source · line 2970 · raw

@context:Maybe<&2, BaseContext> -> @received:Maybe<&2, IncomingContext> -> @reception:Reception -> @sampling:Sampling -> ServicePlan

Take the context that extraction keeps, or start a root without one.

def ServicePlan.new source · line 2979 · raw

@+extraction:Extraction -> @reception:Reception -> @sampling:Sampling -> ServicePlan

The plan of the service's operation for a message (see ServicePlan).

def ServicePlan.generation source · line 2983 · raw

@plan:ServicePlan -> Generation

The generation that the plan drives.

def ServicePlan.service source · line 2992 · raw

@plan:ServicePlan -> @result:Result<&2, &2, GenerationError, LocalContext> -> Service

The service that the result of the plan's generation gives, before the policy applies: its operation, or Untraced with the error.

def Serve.finish source · line 3000 · raw

@-S:Type -> @plan:ServicePlan -> @done:Pair(S, Result<&2, &2, GenerationError, LocalContext>) -> Pair(S, Service)

The source's final state with the service that the plan gives.

def Serve.strict source · line 3018 · raw

@service:Service -> Result<&2, &2, GenerationError, Service>

A service without an operation as the GenerationError that caused it.

def Send.forwarded source · line 3074 · raw

@result:Result<&2, &2, ForwardError, List<&2, Header>> -> @error:GenerationError -> @carrier:List<&2, Header> -> Sent

The fallback when a forwarding of the received pair was tried.

def Send.fallback source · line 3085 · raw

@+limits:Limits -> @received:Maybe<&2, IncomingContext> -> @error:GenerationError -> @+carrier:List<&2, Header> -> Sent

The fields a message carries when no operation could be generated: the received pair forwarded unchanged if it can be, and no context fields otherwise.

def Send.of source · line 3095 · raw

@+limits:Limits -> @+outgoing:OutgoingContext -> @received:Maybe<&2, IncomingContext> -> @+carrier:List<&2, Header> -> @result:Result<&2, &2, GenerationError, LocalContext> -> Sent

The message that a generated child gives: the child injected with the service's state, or the fallback.

def SendPlan.new source · line 3120 · raw

@limits:Limits -> @service:Service -> @sampling:Sampling -> @carrier:List<&2, Header> -> SendPlan

The plan of one message that the service sends (see SendPlan).

def SendPlan.generation source · line 3131 · raw

@plan:SendPlan -> Generation

The generation that the plan drives. A service without an operation has none to drive: its generation has already failed with the service's error, so that a host reads no word.

def SendPlan.sent source · line 3141 · raw

@plan:SendPlan -> @result:Result<&2, &2, GenerationError, LocalContext> -> Sent

The message that the result of the plan's generation gives, before the policy applies. The fallback of a service without an operation does not depend on it.

def Send.finish source · line 3149 · raw

@-S:Type -> @plan:SendPlan -> @done:Pair(S, Result<&2, &2, GenerationError, LocalContext>) -> Pair(S, Sent)

The source's final state with the message that the plan gives.

def Send.strict source · line 3161 · raw

@sent:Sent -> Result<&2, &2, GenerationError, Sent>

A message without a new operation as the GenerationError that caused it.

def Origin.show source · line 3182 · raw

@origin:Origin -> String

The name of an origin.

def Service.origin source · line 3192 · raw

@service:Service -> Maybe<&2, Origin>

How the service's operation came about; None{} without an operation.

def Service.outgoing source · line 3200 · raw

@service:Service -> Maybe<&2, OutgoingContext>

The service's operation with the state it sends; None{} without one.

def Service.error source · line 3208 · raw

@service:Service -> Maybe<&2, GenerationError>

Why the service has no operation; None{} with one.

def Service.set source · line 3218 · raw

@service:Service -> @key:StateKey -> @value:StateValue -> Service

Add or update an entry of the state that the service's operation sends, such as this participant's own (see OutgoingContext.set). A service without an operation is unchanged: it sends no state of its own.

def Service.remove source · line 3227 · raw

@service:Service -> @key:StateKey -> Service

Delete an entry of the state that the service's operation sends (see OutgoingContext.remove). A service without an operation is unchanged.

def Service.show source · line 3236 · raw

@service:Service -> String

The name of a service's origin, or Untraced with its error. It includes no received value.

def Unforwarded.show source · line 3244 · raw

@reason:Unforwarded -> String

Why no pair was forwarded: NothingKept, or the ForwardError's name.

def Sent.carrier source · line 3252 · raw

@sent:Sent -> List<&2, Header>

The fields to send with the message, in every case.

def Sent.operation source · line 3262 · raw

@sent:Sent -> Maybe<&2, LocalContext>

The new operation that the message carries; None{} for a fallback.

def Sent.error source · line 3272 · raw

@sent:Sent -> Maybe<&2, GenerationError>

Why no operation could be generated; None{} for a new operation.

def Sent.dropped source · line 3284 · raw

@sent:Sent -> List<&2, StateKey>

The keys that truncating the service's state to the output budget dropped from a new operation's message (see Injection.dropped); none for a fallback, which sends no state of its own.

def Send.fresh source · line 3295 · raw

@dropped:List<&2, StateKey> -> String

The name of a new operation's message, saying whether its state was truncated.

def Sent.show source · line 3305 · raw

@sent:Sent -> String

The name of a message's context: Fresh, saying whether its state was truncated, or for a fallback why no operation was generated and, without a forwarded pair, why none was forwarded. It includes no received value.

Templates

template Draw.read source · line 886 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @fuel:Nat -> @current:Pair(S, Step) -> IO(Pair(S, Step))

Drive a generation from any source. read returns the source's next state with each word, one word at a time, and the driver stops as soon as the generation ends; the final source state is handed back, so a caller can see what was read. fuel bounds the words read, as in Draw.run. Templates keep this driver free of any host effect: the effect, if any, lives in the source.

template Draw.finished source · line 905 · raw

@-S:Type -> @action:IO(Pair(S, Step)) -> IO(Pair(S, Result<&2, &2, GenerationError, LocalContext>))

Turn the driver's final step into the generation's result.

template Generation.run_with source · line 972 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @generation:Generation -> IO(Pair(S, Result<&2, &2, GenerationError, LocalContext>))

Drive a generation from a caller's source, one word at a time (Draw.read), and hand back the source's final state with the result.

template Context.root_with source · line 983 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> IO(Pair(S, Result<&2, &2, GenerationError, LocalContext>))

Generated contexts from a caller's source. read returns the source's next state with each word result. The source is trusted to be random: a generated trace ID asserts random-trace-id. A root or restart reads at most 48 words, and a child at most 16 (Generation.root and its siblings). Laws: root_tape, root_ends, root_exhaustion and generated_root.

template Context.child_with source · line 989 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @parent:Parent -> @sampling:Sampling -> IO(Pair(S, Result<&2, &2, GenerationError, LocalContext>))

A generated child of parent from a caller's source: at most 16 words. Laws: child_tape, child_ends, child_exhaustion and generated_child.

template Context.restart_with source · line 995 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @previous:RemoteContext -> IO(Pair(S, Result<&2, &2, GenerationError, LocalContext>))

A generated restart replacing previous from a caller's source: at most 48 words. Laws: restart_tape, restart_ends and generated_restart.

template Serve.run source · line 3006 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @+plan:ServicePlan -> IO(Pair(S, Service))

Drive the plan's generation from a caller's source.

template Serve.operation source · line 3013 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @+extraction:Extraction -> @reception:Reception -> @sampling:Sampling -> IO(Pair(S, Service))

The service for a message, before the policy applies.

template Context.continue_or_start_with source · line 3028 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @+extraction:Extraction -> @reception:Reception -> @sampling:Sampling -> @+policy:FailurePolicy -> IO(Pair(S, FailurePolicy.result(policy, Service)))

Give a service its own operation for a received message, from a caller's source (see the section's introduction). Laws: continue_usable, restart_usable, start_unusable and restart_keeps_nothing.

template Send.run source · line 3154 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @+plan:SendPlan -> IO(Pair(S, Sent))

Drive the plan's generation from a caller's source.

template Context.send_with source · line 3174 · raw

@-S:Type -> @-read:(@_:S -> IO(Pair(S, Result<&1, &1, Pair(U32, String), U32>))) -> @source:S -> @+limits:Limits -> @service:Service -> @sampling:Sampling -> @+policy:FailurePolicy -> @+carrier:List<&2, Header> -> IO(Pair(S, FailurePolicy.result(policy, Sent)))

Give one message that the service sends the context of a new operation, from a caller's source (see the section's introduction). carrier is the message's own fields; its old context fields are replaced in every case. Laws: send_operating, send_untraced and send_reports_generated.