Skip to main content

ToolResultCodec

Trait ToolResultCodec 

Source
pub trait ToolResultCodec: Send + Sync {
    // Required methods
    fn lift(&self, version: ProtocolVersion, wire: &Value) -> Option<ToolResult>;
    fn lower(
        &self,
        version: ProtocolVersion,
        value: ToolResult,
        policy: DegradePolicy,
        report: &mut TranslationReport,
    ) -> Result<Value, LowerError>;
}
Expand description

Reads and writes a ToolResult in one revision’s wire encoding.

Declared by the consumer — this module — and implemented by the codec layer, which is the only place that knows a revision’s generated types. The bridge names no wire type, so it could not implement this even if it wanted to.

§Why lift answers Option

None means this build does not read that shape, and it is a decision rather than a fault: the caller forwards the value untouched so a peer that does understand it still receives it. A build that had no wire types at all for the revision would answer None for everything, and the bridge would degrade into a pure pass-through rather than into a component that breaks a connection it never had to translate.

§Example

The smallest implementor that could exist. A production one is WireToolResults, which dispatches to the six per-revision codecs.

use protocol_droid::application::bridge::ToolResultCodec;
use protocol_droid::domain::ir::{LowerError, ToolResult, TranslationReport};
use protocol_droid::domain::{DegradePolicy, ProtocolVersion};
use serde_json::Value;

/// Reads nothing, so every reply through this codec passes through.
struct ReadsNothing;

impl ToolResultCodec for ReadsNothing {
    fn lift(&self, _version: ProtocolVersion, _wire: &Value) -> Option<ToolResult> {
        None
    }

    fn lower(
        &self,
        _version: ProtocolVersion,
        _value: ToolResult,
        _policy: DegradePolicy,
        _report: &mut TranslationReport,
    ) -> Result<Value, LowerError> {
        Ok(Value::Null)
    }
}

A Bridge holds its codec across an await while the reply is in flight, and a serving loop may drive several bridges at once, so a codec that is not Sync would make every one of those futures non-Send. The bound is on the port rather than on Bridge for one reason: this crate’s ports already require Send + Sync, and a codec that only worked on the current thread would not be a codec a bridge could hold.

Required Methods§

Source

fn lift(&self, version: ProtocolVersion, wire: &Value) -> Option<ToolResult>

The ToolResult wire holds at version, or None if this build does not read it.

Source

fn lower( &self, version: ProtocolVersion, value: ToolResult, policy: DegradePolicy, report: &mut TranslationReport, ) -> Result<Value, LowerError>

Writes value at version, recording anything the codec changed in report.

value arrives already lowered — the codec asks lower_tool_result itself rather than being handed a decision, which is why this is not a bare serialisation and why the report comes back from here.

§Errors

LowerError::FieldNotRepresentable when the value does not fit a shape version types — the typed-meta case.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<C: ToolResultCodec> ToolResultCodec for Arc<C>

Lets a shared codec be a codec.

Arc<T> satisfies none of this crate’s ports on its own — it is not a FrameSink and it is not a FrameSource either, for the same reason. A Bridge is usually held by a serving loop and a test wants to watch what it did, and an Arc is the only thing that gives both at once.

Source§

fn lift(&self, version: ProtocolVersion, wire: &Value) -> Option<ToolResult>

Source§

fn lower( &self, version: ProtocolVersion, value: ToolResult, policy: DegradePolicy, report: &mut TranslationReport, ) -> Result<Value, LowerError>

Implementors§