use super::*;
use crate::schema::graph::SchemaGraph;
use crate::schema::wit::{
DecodeError, EncodeError, GraphDecoder, GraphEncoder, decode_graph, decode_value_by_ref,
encode_graph, encode_value,
};
#[cfg(all(feature = "guest", not(feature = "host")))]
pub mod wire {
pub use crate::schema::wit::guest::generated::golem::tool::common::*;
}
#[cfg(all(feature = "host", not(feature = "guest")))]
pub mod wire {
pub use crate::schema::wit::host::generated::golem::tool::common::*;
}
#[derive(Debug)]
pub enum ToolWitError {
Encode(EncodeError),
Decode(DecodeError),
}
impl std::fmt::Display for ToolWitError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ToolWitError::Encode(e) => write!(f, "tool schema encode error: {e}"),
ToolWitError::Decode(e) => write!(f, "tool schema decode error: {e}"),
}
}
}
impl std::error::Error for ToolWitError {}
impl From<EncodeError> for ToolWitError {
fn from(e: EncodeError) -> Self {
ToolWitError::Encode(e)
}
}
impl From<DecodeError> for ToolWitError {
fn from(e: DecodeError) -> Self {
ToolWitError::Decode(e)
}
}
pub fn encode_tool(tool: &Tool) -> Result<wire::Tool, ToolWitError> {
wire::Tool::try_from(tool)
}
pub fn decode_tool(tool: wire::Tool) -> Result<Tool, ToolWitError> {
Tool::try_from(&tool)
}
pub fn tool_middleware_to_wit(
middleware: &ToolMiddleware,
) -> Result<wire::ToolMiddleware, ToolWitError> {
let scope = match &middleware.scope {
ToolMiddlewareScope::Monomorphic(scope) => {
wire::ToolMiddlewareScope::Monomorphic(wire::MonomorphicScope {
presented: encode_tool(&scope.presented)?,
expected: scope.expected.as_ref().map(encode_tool).transpose()?,
})
}
ToolMiddlewareScope::Universal => wire::ToolMiddlewareScope::Universal,
};
Ok(wire::ToolMiddleware {
name: middleware.name.clone(),
version: middleware.version.clone(),
aliases: middleware.aliases.clone(),
doc: wire::Doc::from(&middleware.doc),
scope,
parameter_schema: encode_graph(&middleware.parameter_schema)?,
})
}
pub fn tool_middleware_from_wit(
middleware: wire::ToolMiddleware,
) -> Result<ToolMiddleware, ToolWitError> {
let scope = match middleware.scope {
wire::ToolMiddlewareScope::Monomorphic(scope) => {
ToolMiddlewareScope::Monomorphic(Box::new(MonomorphicToolMiddlewareScope {
presented: decode_tool(scope.presented)?,
expected: scope.expected.map(decode_tool).transpose()?,
}))
}
wire::ToolMiddlewareScope::Universal => ToolMiddlewareScope::Universal,
};
Ok(ToolMiddleware {
name: middleware.name,
version: middleware.version,
aliases: middleware.aliases,
doc: Doc::from(&middleware.doc),
scope,
parameter_schema: decode_graph(&middleware.parameter_schema)?,
})
}
fn decode_tool_value(
value: &crate::schema::wit::wire::SchemaValueTree,
) -> Result<SchemaValue, DecodeError> {
decode_value_by_ref(value)
}
impl From<&Doc> for wire::Doc {
fn from(d: &Doc) -> Self {
wire::Doc {
summary: d.summary.clone(),
description: d.description.clone(),
examples: d.examples.iter().map(wire::Example::from).collect(),
}
}
}
impl From<&wire::Doc> for Doc {
fn from(d: &wire::Doc) -> Self {
Doc {
summary: d.summary.clone(),
description: d.description.clone(),
examples: d.examples.iter().map(Example::from).collect(),
}
}
}
impl From<&Example> for wire::Example {
fn from(e: &Example) -> Self {
wire::Example {
title: e.title.clone(),
body: e.body.clone(),
}
}
}
impl From<&wire::Example> for Example {
fn from(e: &wire::Example) -> Self {
Example {
title: e.title.clone(),
body: e.body.clone(),
}
}
}
impl From<&FlagSpec> for wire::FlagSpec {
fn from(f: &FlagSpec) -> Self {
wire::FlagSpec {
long: f.long.clone(),
short: f.short,
aliases: f.aliases.clone(),
doc: wire::Doc::from(&f.doc),
shape: wire::FlagShape::from(&f.shape),
env_var: f.env_var.clone(),
}
}
}
impl From<&wire::FlagSpec> for FlagSpec {
fn from(f: &wire::FlagSpec) -> Self {
FlagSpec {
long: f.long.clone(),
short: f.short,
aliases: f.aliases.clone(),
doc: Doc::from(&f.doc),
shape: FlagShape::from(&f.shape),
env_var: f.env_var.clone(),
}
}
}
impl From<&FlagShape> for wire::FlagShape {
fn from(s: &FlagShape) -> Self {
match s {
FlagShape::BoolFlag(b) => wire::FlagShape::BoolFlag(wire::BoolFlagShape::from(b)),
FlagShape::CountFlag(m) => wire::FlagShape::CountFlag(*m),
}
}
}
impl From<&wire::FlagShape> for FlagShape {
fn from(s: &wire::FlagShape) -> Self {
match s {
wire::FlagShape::BoolFlag(b) => FlagShape::BoolFlag(BoolFlagShape::from(b)),
wire::FlagShape::CountFlag(m) => FlagShape::CountFlag(*m),
}
}
}
impl From<&BoolFlagShape> for wire::BoolFlagShape {
fn from(b: &BoolFlagShape) -> Self {
wire::BoolFlagShape {
default: b.default,
negatable: b.negatable,
}
}
}
impl From<&wire::BoolFlagShape> for BoolFlagShape {
fn from(b: &wire::BoolFlagShape) -> Self {
BoolFlagShape {
default: b.default,
negatable: b.negatable,
}
}
}
impl From<&Repetition> for wire::Repetition {
fn from(r: &Repetition) -> Self {
match r {
Repetition::Repeated => wire::Repetition::Repeated,
Repetition::Delimited(c) => wire::Repetition::Delimited(*c),
Repetition::Either(c) => wire::Repetition::Either(*c),
}
}
}
impl From<&wire::Repetition> for Repetition {
fn from(r: &wire::Repetition) -> Self {
match r {
wire::Repetition::Repeated => Repetition::Repeated,
wire::Repetition::Delimited(c) => Repetition::Delimited(*c),
wire::Repetition::Either(c) => Repetition::Either(*c),
}
}
}
impl From<&DuplicateKeyPolicy> for wire::DuplicateKeyPolicy {
fn from(p: &DuplicateKeyPolicy) -> Self {
match p {
DuplicateKeyPolicy::Reject => wire::DuplicateKeyPolicy::Reject,
DuplicateKeyPolicy::LastWins => wire::DuplicateKeyPolicy::LastWins,
}
}
}
impl From<&wire::DuplicateKeyPolicy> for DuplicateKeyPolicy {
fn from(p: &wire::DuplicateKeyPolicy) -> Self {
match p {
wire::DuplicateKeyPolicy::Reject => DuplicateKeyPolicy::Reject,
wire::DuplicateKeyPolicy::LastWins => DuplicateKeyPolicy::LastWins,
}
}
}
impl From<&Quantifier> for wire::Quantifier {
fn from(q: &Quantifier) -> Self {
match q {
Quantifier::All => wire::Quantifier::All,
Quantifier::Any => wire::Quantifier::Any,
}
}
}
impl From<&wire::Quantifier> for Quantifier {
fn from(q: &wire::Quantifier) -> Self {
match q {
wire::Quantifier::All => Quantifier::All,
wire::Quantifier::Any => Quantifier::Any,
}
}
}
impl From<&StreamSpec> for wire::StreamSpec {
fn from(s: &StreamSpec) -> Self {
wire::StreamSpec {
doc: wire::Doc::from(&s.doc),
mime: s.mime.clone(),
required: s.required,
}
}
}
impl From<&wire::StreamSpec> for StreamSpec {
fn from(s: &wire::StreamSpec) -> Self {
StreamSpec {
doc: Doc::from(&s.doc),
mime: s.mime.clone(),
required: s.required,
}
}
}
impl From<&Formatter> for wire::Formatter {
fn from(f: &Formatter) -> Self {
wire::Formatter {
name: f.name.clone(),
doc: wire::Doc::from(&f.doc),
}
}
}
impl From<&wire::Formatter> for Formatter {
fn from(f: &wire::Formatter) -> Self {
Formatter {
name: f.name.clone(),
doc: Doc::from(&f.doc),
}
}
}
impl From<&ErrorKind> for wire::ErrorKind {
fn from(k: &ErrorKind) -> Self {
match k {
ErrorKind::UsageError => wire::ErrorKind::UsageError,
ErrorKind::RuntimeError => wire::ErrorKind::RuntimeError,
}
}
}
impl From<&wire::ErrorKind> for ErrorKind {
fn from(k: &wire::ErrorKind) -> Self {
match k {
wire::ErrorKind::UsageError => ErrorKind::UsageError,
wire::ErrorKind::RuntimeError => ErrorKind::RuntimeError,
}
}
}
impl From<&CommandAnnotations> for wire::CommandAnnotations {
fn from(a: &CommandAnnotations) -> Self {
wire::CommandAnnotations {
read_only: a.read_only,
destructive: a.destructive,
idempotent: a.idempotent,
open_world: a.open_world,
}
}
}
impl From<&wire::CommandAnnotations> for CommandAnnotations {
fn from(a: &wire::CommandAnnotations) -> Self {
CommandAnnotations {
read_only: a.read_only,
destructive: a.destructive,
idempotent: a.idempotent,
open_world: a.open_world,
}
}
}
fn encode_constraint(c: &Constraint) -> Result<wire::Constraint, ToolWitError> {
Ok(match c {
Constraint::RequiresAll(rs) => wire::Constraint::RequiresAll(encode_refs(rs)?),
Constraint::AllOrNone(rs) => wire::Constraint::AllOrNone(encode_refs(rs)?),
Constraint::RequiresAny(rs) => wire::Constraint::RequiresAny(encode_refs(rs)?),
Constraint::MutexGroups(gs) => wire::Constraint::MutexGroups(
gs.iter()
.map(encode_ref_group)
.collect::<Result<Vec<_>, _>>()?,
),
Constraint::Implies(i) => wire::Constraint::Implies(wire::ImpliesC {
lhs_quant: wire::Quantifier::from(&i.lhs_quant),
lhs: encode_refs(&i.lhs)?,
rhs_quant: wire::Quantifier::from(&i.rhs_quant),
rhs: encode_refs(&i.rhs)?,
}),
Constraint::Forbids(f) => wire::Constraint::Forbids(wire::ForbidsC {
lhs_quant: wire::Quantifier::from(&f.lhs_quant),
lhs: encode_refs(&f.lhs)?,
rhs: encode_refs(&f.rhs)?,
}),
})
}
fn encode_ref_group(g: &RefGroup) -> Result<wire::RefGroup, ToolWitError> {
Ok(wire::RefGroup {
refs: encode_refs(&g.refs)?,
})
}
fn encode_ref(r: &Ref) -> Result<wire::Ref, ToolWitError> {
Ok(match r {
Ref::Present(name) => wire::Ref::Present(name.clone()),
Ref::ValueIs(v) => wire::Ref::ValueIs(encode_value_is_ref(v)?),
})
}
fn encode_value_is_ref(v: &ValueIsRef) -> Result<wire::ValueIsRef, ToolWitError> {
Ok(wire::ValueIsRef {
name: v.name.clone(),
value: encode_value(&v.value)?,
})
}
fn encode_refs(rs: &[Ref]) -> Result<Vec<wire::Ref>, ToolWitError> {
rs.iter().map(encode_ref).collect()
}
impl TryFrom<&Tool> for wire::Tool {
type Error = ToolWitError;
fn try_from(tool: &Tool) -> Result<Self, Self::Error> {
let mut enc = GraphEncoder::new(&tool.schema.defs)?;
let commands = encode_command_tree(&mut enc, &tool.commands)?;
let schema = enc.finish();
Ok(Self {
version: tool.version.clone(),
requires_filesystem: tool.requires_filesystem,
commands,
schema,
})
}
}
fn encode_command_tree(
enc: &mut GraphEncoder,
ct: &CommandTree,
) -> Result<wire::CommandTree, ToolWitError> {
Ok(wire::CommandTree {
nodes: ct
.nodes
.iter()
.map(|n| encode_command_node(enc, n))
.collect::<Result<Vec<_>, _>>()?,
})
}
fn encode_command_node(
enc: &mut GraphEncoder,
n: &CommandNode,
) -> Result<wire::CommandNode, ToolWitError> {
Ok(wire::CommandNode {
name: n.name.clone(),
aliases: n.aliases.clone(),
doc: wire::Doc::from(&n.doc),
globals: encode_globals(enc, &n.globals)?,
subcommands: n.subcommands.iter().map(|c| c.0).collect(),
body: n
.body
.as_ref()
.map(|b| encode_command_body(enc, b))
.transpose()?,
})
}
fn encode_globals(enc: &mut GraphEncoder, g: &Globals) -> Result<wire::Globals, ToolWitError> {
Ok(wire::Globals {
options: g
.options
.iter()
.map(|o| encode_option_spec(enc, o))
.collect::<Result<Vec<_>, _>>()?,
flags: g.flags.iter().map(wire::FlagSpec::from).collect(),
})
}
fn encode_command_body(
enc: &mut GraphEncoder,
b: &CommandBody,
) -> Result<wire::CommandBody, ToolWitError> {
Ok(wire::CommandBody {
positionals: encode_positionals(enc, &b.positionals)?,
options: b
.options
.iter()
.map(|o| encode_option_spec(enc, o))
.collect::<Result<Vec<_>, _>>()?,
flags: b.flags.iter().map(wire::FlagSpec::from).collect(),
constraints: b
.constraints
.iter()
.map(encode_constraint)
.collect::<Result<Vec<_>, _>>()?,
stdin: b.stdin.as_ref().map(wire::StreamSpec::from),
stdout: b.stdout.as_ref().map(wire::StreamSpec::from),
stderr: b.stderr.as_ref().map(wire::StreamSpec::from),
result: b
.result
.as_ref()
.map(|r| encode_result_spec(enc, r))
.transpose()?,
errors: b
.errors
.iter()
.map(|e| encode_error_case(enc, e))
.collect::<Result<Vec<_>, _>>()?,
annotations: b.annotations.as_ref().map(wire::CommandAnnotations::from),
})
}
fn encode_positionals(
enc: &mut GraphEncoder,
p: &Positionals,
) -> Result<wire::Positionals, ToolWitError> {
Ok(wire::Positionals {
fixed: p
.fixed
.iter()
.map(|x| encode_positional(enc, x))
.collect::<Result<Vec<_>, _>>()?,
tail: p
.tail
.as_ref()
.map(|t| encode_tail_positional(enc, t))
.transpose()?,
})
}
fn encode_positional(
enc: &mut GraphEncoder,
p: &Positional,
) -> Result<wire::Positional, ToolWitError> {
Ok(wire::Positional {
name: p.name.clone(),
doc: wire::Doc::from(&p.doc),
value_name: p.value_name.clone(),
type_: enc.encode_type(&p.type_)?,
default: p.default.as_ref().map(encode_value).transpose()?,
required: p.required,
accepts_stdio: p.accepts_stdio,
})
}
fn encode_tail_positional(
enc: &mut GraphEncoder,
t: &TailPositional,
) -> Result<wire::TailPositional, ToolWitError> {
Ok(wire::TailPositional {
name: t.name.clone(),
doc: wire::Doc::from(&t.doc),
value_name: t.value_name.clone(),
item_type: enc.encode_type(&t.item_type)?,
min: t.min,
max: t.max,
separator: t.separator.clone(),
verbatim: t.verbatim,
accepts_stdio: t.accepts_stdio,
})
}
fn encode_option_spec(
enc: &mut GraphEncoder,
o: &OptionSpec,
) -> Result<wire::OptionSpec, ToolWitError> {
Ok(wire::OptionSpec {
long: o.long.clone(),
short: o.short,
aliases: o.aliases.clone(),
doc: wire::Doc::from(&o.doc),
value_name: o.value_name.clone(),
shape: encode_option_shape(enc, &o.shape)?,
default: o.default.as_ref().map(encode_value).transpose()?,
required: o.required,
env_var: o.env_var.clone(),
})
}
fn encode_option_shape(
enc: &mut GraphEncoder,
s: &OptionShape,
) -> Result<wire::OptionShape, ToolWitError> {
Ok(match s {
OptionShape::Scalar(ty) => wire::OptionShape::Scalar(enc.encode_type(ty)?),
OptionShape::OptionalScalar(ty) => wire::OptionShape::OptionalScalar(enc.encode_type(ty)?),
OptionShape::RepeatableList(r) => {
wire::OptionShape::RepeatableList(wire::RepeatableListShape {
repetition: wire::Repetition::from(&r.repetition),
item_type: enc.encode_type(&r.item_type)?,
})
}
OptionShape::RepeatableMap(r) => {
wire::OptionShape::RepeatableMap(wire::RepeatableMapShape {
repetition: wire::Repetition::from(&r.repetition),
map_type: enc.encode_type(&r.map_type)?,
duplicate_key_policy: wire::DuplicateKeyPolicy::from(&r.duplicate_key_policy),
})
}
})
}
fn encode_result_spec(
enc: &mut GraphEncoder,
r: &ResultSpec,
) -> Result<wire::ResultSpec, ToolWitError> {
Ok(wire::ResultSpec {
type_: enc.encode_type(&r.type_)?,
doc: wire::Doc::from(&r.doc),
formatters: r.formatters.iter().map(wire::Formatter::from).collect(),
default_formatter: r.default_formatter.clone(),
})
}
fn encode_error_case(
enc: &mut GraphEncoder,
e: &ErrorCase,
) -> Result<wire::ErrorCase, ToolWitError> {
Ok(wire::ErrorCase {
name: e.name.clone(),
doc: wire::Doc::from(&e.doc),
kind: wire::ErrorKind::from(&e.kind),
exit_code: e.exit_code,
payload: e.payload.as_ref().map(|p| enc.encode_type(p)).transpose()?,
})
}
impl TryFrom<&wire::Tool> for Tool {
type Error = ToolWitError;
fn try_from(w: &wire::Tool) -> Result<Self, Self::Error> {
let dec = GraphDecoder::new(&w.schema)?;
let mut schema = SchemaGraph::empty();
schema.defs = dec.decode_defs()?;
let commands = decode_command_tree(&dec, &w.commands)?;
Ok(Self {
version: w.version.clone(),
requires_filesystem: w.requires_filesystem,
commands,
schema,
})
}
}
fn decode_command_tree(
dec: &GraphDecoder,
ct: &wire::CommandTree,
) -> Result<CommandTree, ToolWitError> {
Ok(CommandTree {
nodes: ct
.nodes
.iter()
.map(|n| decode_command_node(dec, n))
.collect::<Result<Vec<_>, _>>()?,
})
}
fn decode_command_node(
dec: &GraphDecoder,
n: &wire::CommandNode,
) -> Result<CommandNode, ToolWitError> {
Ok(CommandNode {
name: n.name.clone(),
aliases: n.aliases.clone(),
doc: Doc::from(&n.doc),
globals: decode_globals(dec, &n.globals)?,
subcommands: n.subcommands.iter().map(|c| CommandIndex(*c)).collect(),
body: n
.body
.as_ref()
.map(|b| decode_command_body(dec, b))
.transpose()?,
})
}
fn decode_globals(dec: &GraphDecoder, g: &wire::Globals) -> Result<Globals, ToolWitError> {
Ok(Globals {
options: g
.options
.iter()
.map(|o| decode_option_spec(dec, o))
.collect::<Result<Vec<_>, _>>()?,
flags: g.flags.iter().map(FlagSpec::from).collect(),
})
}
fn decode_command_body(
dec: &GraphDecoder,
b: &wire::CommandBody,
) -> Result<CommandBody, ToolWitError> {
Ok(CommandBody {
positionals: decode_positionals(dec, &b.positionals)?,
options: b
.options
.iter()
.map(|o| decode_option_spec(dec, o))
.collect::<Result<Vec<_>, _>>()?,
flags: b.flags.iter().map(FlagSpec::from).collect(),
constraints: b
.constraints
.iter()
.map(decode_constraint)
.collect::<Result<Vec<_>, _>>()?,
stdin: b.stdin.as_ref().map(StreamSpec::from),
stdout: b.stdout.as_ref().map(StreamSpec::from),
stderr: b.stderr.as_ref().map(StreamSpec::from),
result: b
.result
.as_ref()
.map(|r| decode_result_spec(dec, r))
.transpose()?,
errors: b
.errors
.iter()
.map(|e| decode_error_case(dec, e))
.collect::<Result<Vec<_>, _>>()?,
annotations: b.annotations.as_ref().map(CommandAnnotations::from),
})
}
fn decode_positionals(
dec: &GraphDecoder,
p: &wire::Positionals,
) -> Result<Positionals, ToolWitError> {
Ok(Positionals {
fixed: p
.fixed
.iter()
.map(|x| decode_positional(dec, x))
.collect::<Result<Vec<_>, _>>()?,
tail: p
.tail
.as_ref()
.map(|t| decode_tail_positional(dec, t))
.transpose()?,
})
}
fn decode_positional(dec: &GraphDecoder, p: &wire::Positional) -> Result<Positional, ToolWitError> {
Ok(Positional {
name: p.name.clone(),
doc: Doc::from(&p.doc),
value_name: p.value_name.clone(),
type_: dec.decode_type_at(p.type_)?,
default: p.default.as_ref().map(decode_tool_value).transpose()?,
required: p.required,
accepts_stdio: p.accepts_stdio,
})
}
fn decode_tail_positional(
dec: &GraphDecoder,
t: &wire::TailPositional,
) -> Result<TailPositional, ToolWitError> {
Ok(TailPositional {
name: t.name.clone(),
doc: Doc::from(&t.doc),
value_name: t.value_name.clone(),
item_type: dec.decode_type_at(t.item_type)?,
min: t.min,
max: t.max,
separator: t.separator.clone(),
verbatim: t.verbatim,
accepts_stdio: t.accepts_stdio,
})
}
fn decode_option_spec(
dec: &GraphDecoder,
o: &wire::OptionSpec,
) -> Result<OptionSpec, ToolWitError> {
Ok(OptionSpec {
long: o.long.clone(),
short: o.short,
aliases: o.aliases.clone(),
doc: Doc::from(&o.doc),
value_name: o.value_name.clone(),
shape: decode_option_shape(dec, &o.shape)?,
default: o.default.as_ref().map(decode_tool_value).transpose()?,
required: o.required,
env_var: o.env_var.clone(),
})
}
fn decode_option_shape(
dec: &GraphDecoder,
s: &wire::OptionShape,
) -> Result<OptionShape, ToolWitError> {
Ok(match s {
wire::OptionShape::Scalar(ty) => OptionShape::Scalar(dec.decode_type_at(*ty)?),
wire::OptionShape::OptionalScalar(ty) => {
OptionShape::OptionalScalar(dec.decode_type_at(*ty)?)
}
wire::OptionShape::RepeatableList(r) => OptionShape::RepeatableList(RepeatableListShape {
repetition: Repetition::from(&r.repetition),
item_type: dec.decode_type_at(r.item_type)?,
}),
wire::OptionShape::RepeatableMap(r) => OptionShape::RepeatableMap(RepeatableMapShape {
repetition: Repetition::from(&r.repetition),
map_type: dec.decode_type_at(r.map_type)?,
duplicate_key_policy: DuplicateKeyPolicy::from(&r.duplicate_key_policy),
}),
})
}
fn decode_constraint(c: &wire::Constraint) -> Result<Constraint, ToolWitError> {
Ok(match c {
wire::Constraint::RequiresAll(rs) => Constraint::RequiresAll(decode_refs(rs)?),
wire::Constraint::AllOrNone(rs) => Constraint::AllOrNone(decode_refs(rs)?),
wire::Constraint::RequiresAny(rs) => Constraint::RequiresAny(decode_refs(rs)?),
wire::Constraint::MutexGroups(gs) => Constraint::MutexGroups(
gs.iter()
.map(decode_ref_group)
.collect::<Result<Vec<_>, _>>()?,
),
wire::Constraint::Implies(i) => Constraint::Implies(ImpliesC {
lhs_quant: Quantifier::from(&i.lhs_quant),
lhs: decode_refs(&i.lhs)?,
rhs_quant: Quantifier::from(&i.rhs_quant),
rhs: decode_refs(&i.rhs)?,
}),
wire::Constraint::Forbids(f) => Constraint::Forbids(ForbidsC {
lhs_quant: Quantifier::from(&f.lhs_quant),
lhs: decode_refs(&f.lhs)?,
rhs: decode_refs(&f.rhs)?,
}),
})
}
fn decode_refs(rs: &[wire::Ref]) -> Result<Vec<Ref>, ToolWitError> {
rs.iter().map(decode_ref).collect()
}
fn decode_ref_group(g: &wire::RefGroup) -> Result<RefGroup, ToolWitError> {
Ok(RefGroup {
refs: decode_refs(&g.refs)?,
})
}
fn decode_ref(r: &wire::Ref) -> Result<Ref, ToolWitError> {
Ok(match r {
wire::Ref::Present(name) => Ref::Present(name.clone()),
wire::Ref::ValueIs(v) => Ref::ValueIs(ValueIsRef {
name: v.name.clone(),
value: decode_tool_value(&v.value)?,
}),
})
}
fn decode_result_spec(
dec: &GraphDecoder,
r: &wire::ResultSpec,
) -> Result<ResultSpec, ToolWitError> {
Ok(ResultSpec {
type_: dec.decode_type_at(r.type_)?,
doc: Doc::from(&r.doc),
formatters: r.formatters.iter().map(Formatter::from).collect(),
default_formatter: r.default_formatter.clone(),
})
}
fn decode_error_case(dec: &GraphDecoder, e: &wire::ErrorCase) -> Result<ErrorCase, ToolWitError> {
Ok(ErrorCase {
name: e.name.clone(),
doc: Doc::from(&e.doc),
kind: ErrorKind::from(&e.kind),
exit_code: e.exit_code,
payload: e
.payload
.as_ref()
.map(|p| dec.decode_type_at(*p))
.transpose()?,
})
}
#[cfg(test)]
mod tests;