refactor: move firmware workspace under firmware
This commit is contained in:
1 parent
153b0bf262
commit
f03fc119a4
222 files changed
+56
-13
No files matched your search
@@ -0,0 +1,501 @@
|
||||
//! Generated Kaptan-dialect message translation.
|
||||
|
||||
use kaptan_config::{
|
||||
ApplyPolicy, ConfigState, ConfigValue, FieldDescriptor, FieldId, Generation, ValidationRule,
|
||||
ValueKind,
|
||||
};
|
||||
use kaptan_log::KaptanError;
|
||||
use kaptan_mavlink::message::Message;
|
||||
use kaptan_mavlink::message::kaptan::{
|
||||
KAPTAN_CONFIG_DESCRIPTOR_DATA, KAPTAN_CONFIG_INFO_DATA, KAPTAN_CONFIG_RESULT_DATA,
|
||||
KAPTAN_CONFIG_VALUE_DATA, KaptanConfigError, KaptanConfigOperation, KaptanConfigPolicy,
|
||||
KaptanConfigResult, KaptanConfigState, KaptanConfigValueKind, KaptanConfigValueSource,
|
||||
MavMessage,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ConfigCommand, ConfigReply, Operation, ProtocolError, ResultKind, Target, ValueSource,
|
||||
service::{ConfigInfo, ValueResponse},
|
||||
};
|
||||
|
||||
/// Rejects a generated message that is not a Kaptan configuration command.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, KaptanError)]
|
||||
pub enum DecodeError {
|
||||
/// The message belongs to a response, telemetry, or another service.
|
||||
UnsupportedMessage,
|
||||
/// A wire field identity used a reserved sentinel.
|
||||
InvalidFieldId,
|
||||
/// The message used an unknown value-source discriminator.
|
||||
InvalidValueSource,
|
||||
/// A boolean setter used a representation other than zero or one.
|
||||
InvalidBoolean,
|
||||
/// A configuration request used a broadcast/zero target endpoint.
|
||||
InvalidTarget,
|
||||
}
|
||||
|
||||
/// Converts one generated custom request into a transport-neutral command.
|
||||
///
|
||||
/// This only decodes a validated MAVLink payload. An authenticated ingress must
|
||||
/// still wrap the result in [`crate::Authorized`] before dispatch.
|
||||
pub fn decode_command(message: &MavMessage) -> Result<ConfigCommand, DecodeError> {
|
||||
if matches!(message.target_system_id(), Some(0))
|
||||
|| matches!(message.target_component_id(), Some(0))
|
||||
{
|
||||
return Err(DecodeError::InvalidTarget);
|
||||
}
|
||||
match message {
|
||||
MavMessage::KAPTAN_CONFIG_INFO_REQUEST(data) => Ok(ConfigCommand::InfoRequest {
|
||||
request_id: data.request_id,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_DESCRIPTOR_REQUEST(data) => {
|
||||
Ok(ConfigCommand::DescriptorRequest {
|
||||
request_id: data.request_id,
|
||||
first: data.first,
|
||||
count: data.count,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
})
|
||||
}
|
||||
MavMessage::KAPTAN_CONFIG_VALUE_REQUEST(data) => Ok(ConfigCommand::ValueRequest {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
field: field_id(data.field_id)?,
|
||||
source: value_source(data.source)?,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_IMPORT_BEGIN(data) => Ok(ConfigCommand::ImportBegin {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
length: data.length,
|
||||
schema_id: data.schema_id,
|
||||
crc32c: data.crc32c,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_IMPORT_CHUNK(data) => Ok(ConfigCommand::ImportChunk {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
transfer_id: data.transfer_id,
|
||||
offset: data.offset,
|
||||
length: data.length,
|
||||
data: data.data,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_IMPORT_FINISH(data) => Ok(ConfigCommand::ImportFinish {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
transfer_id: data.transfer_id,
|
||||
expected_revision: data.expected_revision,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_BEGIN(data) => Ok(ConfigCommand::Begin {
|
||||
request_id: data.request_id,
|
||||
expected_generation: data.expected_generation,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_SET_F32(data) => Ok(ConfigCommand::Set {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
field: field_id(data.field_id)?,
|
||||
value: ConfigValue::F32(data.value),
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_SET_BOOL(data) => Ok(ConfigCommand::Set {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
field: field_id(data.field_id)?,
|
||||
value: ConfigValue::Bool(boolean(data.value)?),
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_SET_I32(data) => Ok(ConfigCommand::Set {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
field: field_id(data.field_id)?,
|
||||
value: ConfigValue::I32(data.value),
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_SET_U32(data) => Ok(ConfigCommand::Set {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
field: field_id(data.field_id)?,
|
||||
value: ConfigValue::U32(data.value),
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_SET_U64(data) => Ok(ConfigCommand::Set {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
field: field_id(data.field_id)?,
|
||||
value: ConfigValue::U64(data.value),
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_SET_F64(data) => Ok(ConfigCommand::Set {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
field: field_id(data.field_id)?,
|
||||
value: ConfigValue::F64(data.value),
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_VALIDATE(data) => Ok(ConfigCommand::Validate {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_revision: data.expected_revision,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_COMMIT(data) => Ok(ConfigCommand::Commit {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
expected_generation: data.expected_generation,
|
||||
expected_revision: data.expected_revision,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
MavMessage::KAPTAN_CONFIG_ABORT(data) => Ok(ConfigCommand::Abort {
|
||||
request_id: data.request_id,
|
||||
session_id: data.session_id,
|
||||
target: Target::new(data.target_system, data.target_component),
|
||||
}),
|
||||
_ => Err(DecodeError::UnsupportedMessage),
|
||||
}
|
||||
}
|
||||
|
||||
const fn field_id(value: u16) -> Result<FieldId, DecodeError> {
|
||||
match FieldId::try_new(value) {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(DecodeError::InvalidFieldId),
|
||||
}
|
||||
}
|
||||
|
||||
const fn value_source(value: KaptanConfigValueSource) -> Result<ValueSource, DecodeError> {
|
||||
match value {
|
||||
KaptanConfigValueSource::KAPTAN_CONFIG_VALUE_SOURCE_ACTIVE => Ok(ValueSource::Active),
|
||||
KaptanConfigValueSource::KAPTAN_CONFIG_VALUE_SOURCE_COMMITTED => Ok(ValueSource::Committed),
|
||||
KaptanConfigValueSource::KAPTAN_CONFIG_VALUE_SOURCE_TRANSACTION => {
|
||||
Ok(ValueSource::Transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fn boolean(value: u8) -> Result<bool, DecodeError> {
|
||||
match value {
|
||||
0 => Ok(false),
|
||||
1 => Ok(true),
|
||||
_ => Err(DecodeError::InvalidBoolean),
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes one authoritative service completion.
|
||||
pub fn encode_result(reply: ConfigReply) -> KAPTAN_CONFIG_RESULT_DATA {
|
||||
KAPTAN_CONFIG_RESULT_DATA {
|
||||
generation: reply.generation,
|
||||
request_id: reply.request_id,
|
||||
session_id: reply.session_id,
|
||||
transfer_id: reply.transfer_id,
|
||||
revision: reply.revision,
|
||||
primary_field: reply.primary_field(),
|
||||
related_field: reply.related_field(),
|
||||
validation_rule: reply.validation_rule(),
|
||||
operation: operation(reply.operation),
|
||||
result: result(reply.result),
|
||||
error: error(reply.error),
|
||||
config_state: state(reply.state),
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes configuration protocol/schema status for a Kaptan control station.
|
||||
pub fn encode_info(info: ConfigInfo) -> KAPTAN_CONFIG_INFO_DATA {
|
||||
KAPTAN_CONFIG_INFO_DATA {
|
||||
active_generation: info.active_generation.map_or(0, Generation::get),
|
||||
committed_generation: info.committed_generation.map_or(0, Generation::get),
|
||||
request_id: info.request_id,
|
||||
schema_id: info.schema_id,
|
||||
profile_format: info.profile_format,
|
||||
field_count: info.field_count,
|
||||
protocol_major: 1,
|
||||
protocol_minor: 0,
|
||||
config_state: state(info.state),
|
||||
capability_flags: info.capability_flags,
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes self-describing metadata for one schema field.
|
||||
pub fn encode_descriptor(
|
||||
request_id: u32,
|
||||
descriptor_index: u16,
|
||||
descriptor: FieldDescriptor,
|
||||
) -> KAPTAN_CONFIG_DESCRIPTOR_DATA {
|
||||
KAPTAN_CONFIG_DESCRIPTOR_DATA {
|
||||
minimum_bits: descriptor.minimum.map_or(0, ConfigValue::raw_bits),
|
||||
maximum_bits: descriptor.maximum.map_or(0, ConfigValue::raw_bits),
|
||||
default_bits: descriptor.default.raw_bits(),
|
||||
request_id,
|
||||
descriptor_index,
|
||||
field_id: descriptor.id.get(),
|
||||
display_key: descriptor.display_key.into(),
|
||||
unit: descriptor.unit.into(),
|
||||
value_kind: value_kind(descriptor.kind),
|
||||
apply_policy: policy(descriptor.apply_policy),
|
||||
flags: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes a typed scalar read response for the Kaptan control station.
|
||||
pub fn encode_value(value: ValueResponse) -> KAPTAN_CONFIG_VALUE_DATA {
|
||||
KAPTAN_CONFIG_VALUE_DATA {
|
||||
value_bits: value.value.raw_bits(),
|
||||
request_id: value.request_id,
|
||||
session_id: value.session_id,
|
||||
revision: value.revision,
|
||||
field_id: value.field.get(),
|
||||
value_kind: value_kind(value.value.kind()),
|
||||
}
|
||||
}
|
||||
|
||||
const fn value_kind(kind: ValueKind) -> KaptanConfigValueKind {
|
||||
match kind {
|
||||
ValueKind::Bool => KaptanConfigValueKind::KAPTAN_CONFIG_VALUE_KIND_BOOL,
|
||||
ValueKind::I32 => KaptanConfigValueKind::KAPTAN_CONFIG_VALUE_KIND_I32,
|
||||
ValueKind::U32 => KaptanConfigValueKind::KAPTAN_CONFIG_VALUE_KIND_U32,
|
||||
ValueKind::U64 => KaptanConfigValueKind::KAPTAN_CONFIG_VALUE_KIND_U64,
|
||||
ValueKind::F32 => KaptanConfigValueKind::KAPTAN_CONFIG_VALUE_KIND_F32,
|
||||
ValueKind::F64 => KaptanConfigValueKind::KAPTAN_CONFIG_VALUE_KIND_F64,
|
||||
}
|
||||
}
|
||||
|
||||
const fn policy(policy: ApplyPolicy) -> KaptanConfigPolicy {
|
||||
match policy {
|
||||
ApplyPolicy::Live => KaptanConfigPolicy::KAPTAN_CONFIG_POLICY_LIVE,
|
||||
ApplyPolicy::DisarmedReset => KaptanConfigPolicy::KAPTAN_CONFIG_POLICY_DISARMED_RESET,
|
||||
ApplyPolicy::RestartRequired => KaptanConfigPolicy::KAPTAN_CONFIG_POLICY_RESTART_REQUIRED,
|
||||
}
|
||||
}
|
||||
|
||||
const fn operation(operation: Operation) -> KaptanConfigOperation {
|
||||
match operation {
|
||||
Operation::Query => KaptanConfigOperation::KAPTAN_CONFIG_OPERATION_QUERY,
|
||||
Operation::Begin => KaptanConfigOperation::KAPTAN_CONFIG_OPERATION_BEGIN,
|
||||
Operation::Set => KaptanConfigOperation::KAPTAN_CONFIG_OPERATION_SET,
|
||||
Operation::Validate => KaptanConfigOperation::KAPTAN_CONFIG_OPERATION_VALIDATE,
|
||||
Operation::Commit => KaptanConfigOperation::KAPTAN_CONFIG_OPERATION_COMMIT,
|
||||
Operation::Abort => KaptanConfigOperation::KAPTAN_CONFIG_OPERATION_ABORT,
|
||||
Operation::Import => KaptanConfigOperation::KAPTAN_CONFIG_OPERATION_IMPORT,
|
||||
}
|
||||
}
|
||||
|
||||
const fn result(result: ResultKind) -> KaptanConfigResult {
|
||||
match result {
|
||||
ResultKind::Accepted => KaptanConfigResult::KAPTAN_CONFIG_RESULT_ACCEPTED,
|
||||
ResultKind::CommittedRestartRequired => {
|
||||
KaptanConfigResult::KAPTAN_CONFIG_RESULT_COMMITTED_RESTART_REQUIRED
|
||||
}
|
||||
ResultKind::Rejected => KaptanConfigResult::KAPTAN_CONFIG_RESULT_REJECTED,
|
||||
}
|
||||
}
|
||||
|
||||
const fn state(state: ConfigState) -> KaptanConfigState {
|
||||
match state {
|
||||
ConfigState::Active => KaptanConfigState::KAPTAN_CONFIG_STATE_ACTIVE,
|
||||
ConfigState::Editing => KaptanConfigState::KAPTAN_CONFIG_STATE_EDITING,
|
||||
ConfigState::RestartRequired => KaptanConfigState::KAPTAN_CONFIG_STATE_RESTART_REQUIRED,
|
||||
}
|
||||
}
|
||||
|
||||
const fn error(error: Option<ProtocolError>) -> KaptanConfigError {
|
||||
match error {
|
||||
None => KaptanConfigError::KAPTAN_CONFIG_ERROR_NONE,
|
||||
Some(ProtocolError::BadTarget) => KaptanConfigError::KAPTAN_CONFIG_ERROR_BAD_TARGET,
|
||||
Some(ProtocolError::AuthorizationDenied) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_AUTHORIZATION_DENIED
|
||||
}
|
||||
Some(ProtocolError::GenerationConflict) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_GENERATION_CONFLICT
|
||||
}
|
||||
Some(ProtocolError::SessionBusy) => KaptanConfigError::KAPTAN_CONFIG_ERROR_SESSION_BUSY,
|
||||
Some(ProtocolError::InvalidSession) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_INVALID_SESSION
|
||||
}
|
||||
Some(ProtocolError::RequestConflict) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_REQUEST_CONFLICT
|
||||
}
|
||||
Some(ProtocolError::StaleRevision) => KaptanConfigError::KAPTAN_CONFIG_ERROR_STALE_REVISION,
|
||||
Some(ProtocolError::BadState) => KaptanConfigError::KAPTAN_CONFIG_ERROR_BAD_STATE,
|
||||
Some(ProtocolError::UnknownField(_)) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_UNKNOWN_FIELD
|
||||
}
|
||||
Some(ProtocolError::TypeMismatch(_)) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_TYPE_MISMATCH
|
||||
}
|
||||
Some(ProtocolError::Violation(violation)) => match violation.rule() {
|
||||
ValidationRule::NonFinite => KaptanConfigError::KAPTAN_CONFIG_ERROR_NON_FINITE,
|
||||
ValidationRule::BelowMinimum | ValidationRule::Zero => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_BELOW_MINIMUM
|
||||
}
|
||||
ValidationRule::AboveMaximum => KaptanConfigError::KAPTAN_CONFIG_ERROR_ABOVE_MAXIMUM,
|
||||
ValidationRule::Inconsistent => KaptanConfigError::KAPTAN_CONFIG_ERROR_CROSS_FIELD,
|
||||
ValidationRule::UnsupportedCapability => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_UNSUPPORTED_CAPABILITY
|
||||
}
|
||||
ValidationRule::UnsupportedFormat => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_UNSUPPORTED_FORMAT
|
||||
}
|
||||
},
|
||||
Some(ProtocolError::StorageFailure) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_STORAGE_FAILURE
|
||||
}
|
||||
Some(ProtocolError::CborMalformed) => KaptanConfigError::KAPTAN_CONFIG_ERROR_CBOR_MALFORMED,
|
||||
Some(ProtocolError::CborTooLarge) => KaptanConfigError::KAPTAN_CONFIG_ERROR_CBOR_TOO_LARGE,
|
||||
Some(ProtocolError::BlobCrc) => KaptanConfigError::KAPTAN_CONFIG_ERROR_BLOB_CRC,
|
||||
Some(ProtocolError::SchemaMismatch) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_SCHEMA_MISMATCH
|
||||
}
|
||||
Some(ProtocolError::ImportUnavailable) => {
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_IMPORT_UNAVAILABLE
|
||||
}
|
||||
Some(ProtocolError::Internal) => KaptanConfigError::KAPTAN_CONFIG_ERROR_INTERNAL,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use kaptan_config::{ConfigState, ConfigViolation, ValidationRule};
|
||||
use kaptan_mavlink::message::kaptan::{
|
||||
KAPTAN_CONFIG_INFO_REQUEST_DATA, KAPTAN_CONFIG_SET_F32_DATA, MavMessage,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use crate::CAPABILITY_CBOR_IMPORT;
|
||||
|
||||
#[test]
|
||||
fn generated_set_message_preserves_typed_value_and_identifiers() {
|
||||
let message = MavMessage::KAPTAN_CONFIG_SET_F32(KAPTAN_CONFIG_SET_F32_DATA {
|
||||
request_id: 7,
|
||||
session_id: 8,
|
||||
expected_revision: 9,
|
||||
field_id: 10,
|
||||
value: 1.5,
|
||||
target_system: 1,
|
||||
target_component: 2,
|
||||
});
|
||||
assert_eq!(
|
||||
decode_command(&message),
|
||||
Ok(ConfigCommand::Set {
|
||||
request_id: 7,
|
||||
session_id: 8,
|
||||
expected_revision: 9,
|
||||
field: FieldId::new(10),
|
||||
value: ConfigValue::F32(1.5),
|
||||
target: Target::new(1, 2),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generated_info_request_is_correlated_and_exactly_targeted() {
|
||||
let message = MavMessage::KAPTAN_CONFIG_INFO_REQUEST(KAPTAN_CONFIG_INFO_REQUEST_DATA {
|
||||
request_id: 31,
|
||||
target_system: 1,
|
||||
target_component: 2,
|
||||
});
|
||||
assert_eq!(
|
||||
decode_command(&message),
|
||||
Ok(ConfigCommand::InfoRequest {
|
||||
request_id: 31,
|
||||
target: Target::new(1, 2),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generated_config_requests_reject_broadcast_targets() {
|
||||
let zero_system = MavMessage::KAPTAN_CONFIG_SET_F32(KAPTAN_CONFIG_SET_F32_DATA {
|
||||
request_id: 7,
|
||||
session_id: 8,
|
||||
expected_revision: 9,
|
||||
field_id: 10,
|
||||
value: 1.5,
|
||||
target_system: 0,
|
||||
target_component: 2,
|
||||
});
|
||||
let zero_component = MavMessage::KAPTAN_CONFIG_SET_F32(KAPTAN_CONFIG_SET_F32_DATA {
|
||||
request_id: 7,
|
||||
session_id: 8,
|
||||
expected_revision: 9,
|
||||
field_id: 10,
|
||||
value: 1.5,
|
||||
target_system: 1,
|
||||
target_component: 0,
|
||||
});
|
||||
assert_eq!(
|
||||
decode_command(&zero_system),
|
||||
Err(DecodeError::InvalidTarget)
|
||||
);
|
||||
assert_eq!(
|
||||
decode_command(&zero_component),
|
||||
Err(DecodeError::InvalidTarget)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn result_encodes_exact_validation_identity() {
|
||||
let reply = ConfigReply {
|
||||
request_id: 1,
|
||||
session_id: 2,
|
||||
transfer_id: 0,
|
||||
revision: 3,
|
||||
generation: 4,
|
||||
operation: Operation::Set,
|
||||
result: ResultKind::Rejected,
|
||||
error: Some(ProtocolError::Violation(ConfigViolation::field(
|
||||
FieldId::new(11),
|
||||
ValidationRule::NonFinite,
|
||||
))),
|
||||
state: ConfigState::Editing,
|
||||
};
|
||||
let encoded = encode_result(reply);
|
||||
assert_eq!(encoded.primary_field, 11);
|
||||
assert_eq!(encoded.validation_rule, ValidationRule::NonFinite.code());
|
||||
assert_eq!(
|
||||
encoded.error,
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_NON_FINITE
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unavailable_import_has_its_own_structured_error_code() {
|
||||
let reply = ConfigReply {
|
||||
request_id: 1,
|
||||
session_id: 0,
|
||||
transfer_id: 0,
|
||||
revision: 0,
|
||||
generation: 0,
|
||||
operation: Operation::Import,
|
||||
result: ResultKind::Rejected,
|
||||
error: Some(ProtocolError::ImportUnavailable),
|
||||
state: ConfigState::Active,
|
||||
};
|
||||
assert_eq!(
|
||||
encode_result(reply).error,
|
||||
KaptanConfigError::KAPTAN_CONFIG_ERROR_IMPORT_UNAVAILABLE
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn info_preserves_service_capabilities() {
|
||||
let info = encode_info(ConfigInfo {
|
||||
request_id: 7,
|
||||
active_generation: None,
|
||||
committed_generation: None,
|
||||
schema_id: [0; 16],
|
||||
profile_format: 1,
|
||||
field_count: 23,
|
||||
state: ConfigState::Active,
|
||||
capability_flags: CAPABILITY_CBOR_IMPORT,
|
||||
});
|
||||
assert_eq!(info.request_id, 7);
|
||||
assert_eq!(info.capability_flags, CAPABILITY_CBOR_IMPORT);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user