mod contract;
mod entity;
mod link;
mod manual;
mod protocol;
use switchback_traits::{ReferenceManual, Result, SwitchbackError};
use crate::pb;
pub const WIRE_VERSION: &str = "v1alpha1";
pub fn to_proto(manual: &ReferenceManual) -> Result<pb::ReferenceManual> {
validate_resolved_links(manual)?;
manual::reference_manual_to_proto(manual)
}
pub fn from_proto(manual: pb::ReferenceManual) -> Result<ReferenceManual> {
validate_wire_version(&manual.switchback_version)?;
manual::reference_manual_from_proto(manual)
}
fn validate_wire_version(version: &str) -> Result<()> {
if version.starts_with(WIRE_VERSION) {
Ok(())
} else {
Err(SwitchbackError::codec(format!(
"unsupported switchback_version {version:?}; expected prefix {WIRE_VERSION:?}"
)))
}
}
fn validate_resolved_links(manual: &ReferenceManual) -> Result<()> {
for module in &manual.modules {
for contract in &module.contracts {
for group in &contract.groups {
for entity in &group.entities {
for link in &entity.intra_links {
if matches!(link.target, switchback_traits::LinkTarget::Unresolved) {
return Err(SwitchbackError::codec(
"cannot serialize manual with unresolved intra-link",
));
}
}
}
}
}
}
Ok(())
}
pub(crate) fn opt_string(value: &Option<String>) -> String {
value.clone().unwrap_or_default()
}
pub(crate) fn string_opt(value: String) -> Option<String> {
if value.is_empty() { None } else { Some(value) }
}
pub(crate) fn codec_err(message: impl Into<String>) -> SwitchbackError {
SwitchbackError::codec(message)
}
pub(crate) fn missing_link_target() -> SwitchbackError {
codec_err("link target missing on wire")
}
pub(crate) fn missing_entity_body() -> SwitchbackError {
codec_err("entity body missing on wire")
}