fn from()

in rust/azure_iot_operations_protocol/src/rpc_command/invoker.rs [186:272]


    fn from(value: RemoteError) -> Self {
        // NOTE: We do not use the AIOProtocolError constructor functions, as they would
        // result in additional allocations (String -> &str -> String). Because there is no
        // Default implementation for AIOProtocolError (nor can there be), we will initialize a
        // "default" instance here, and update fields as necessary.
        let remote_error_clone = value.clone();
        let mut aio_error = AIOProtocolError {
            kind: AIOProtocolErrorKind::UnknownError,
            message: value.status_message,
            is_shallow: false, // Always false because a RemoteError implies network activity
            is_remote: true,   // Always true because it is a RemoteError
            nested_error: Some(Box::new(remote_error_clone)),
            header_name: None,
            header_value: None,
            timeout_name: None,
            timeout_value: None,
            property_name: None,
            property_value: None,
            command_name: None, // Will need to update this after return
            protocol_version: Some(value.protocol_version.to_string()),
            supported_protocol_major_versions: value.supported_protocol_major_versions,
        };

        match value.status_code {
            StatusCode::Ok | StatusCode::NoContent => {
                // NOTE: Could remove this by defining a subset of the StatusCode enums
                // e.g. FailureStatusCode, but that might be overkill
                unreachable!("Invalid status code for RemoteError")
            }
            StatusCode::BadRequest => {
                if value.invalid_property_name.is_some() && value.invalid_property_value.is_some() {
                    aio_error.kind = AIOProtocolErrorKind::HeaderInvalid;
                    aio_error.header_name = value.invalid_property_name;
                    aio_error.header_value = value.invalid_property_value;
                } else if value.invalid_property_name.is_some() {
                    aio_error.kind = AIOProtocolErrorKind::HeaderMissing;
                    aio_error.header_name = value.invalid_property_name;
                } else {
                    aio_error.kind = AIOProtocolErrorKind::PayloadInvalid;
                }
            }
            StatusCode::RequestTimeout => {
                aio_error.kind = AIOProtocolErrorKind::Timeout;
                aio_error.timeout_name = value.invalid_property_name;
                aio_error.timeout_value = value.invalid_property_value.and_then(|timeout_s| {
                    match timeout_s.parse::<iso8601_duration::Duration>() {
                        Ok(d) => d.to_std(),
                        Err(_) => None,
                    }
                });
            }
            StatusCode::UnsupportedMediaType => {
                aio_error.kind = AIOProtocolErrorKind::HeaderInvalid;
                aio_error.header_name = value.invalid_property_name;
                aio_error.header_value = value.invalid_property_value;
            }
            StatusCode::InternalServerError => {
                // TODO: We may want to narrow this logic a bit to cover only valid cases.
                // but for now, this is the same logic from prior iterations. When revisiting
                // errors, this may be able to be cleaned up more.
                if value.is_application_error {
                    aio_error.kind = AIOProtocolErrorKind::ExecutionException;
                    aio_error.property_name = value.invalid_property_name;
                    aio_error.property_value = value.invalid_property_value.map(Value::String);
                } else if value.invalid_property_name.is_some() {
                    aio_error.kind = AIOProtocolErrorKind::InternalLogicError;
                    aio_error.property_name = value.invalid_property_name;
                    aio_error.property_value = value.invalid_property_value.map(Value::String);
                } else {
                    aio_error.kind = AIOProtocolErrorKind::UnknownError;
                    // It is expected that value.invalid_property_name and
                    // value.invalid_property_value are None, but they are not set
                    // in order to ensure a None value.
                    // Not sure that this is entirely desirable.
                }
            }
            StatusCode::ServiceUnavailable => {
                aio_error.kind = AIOProtocolErrorKind::StateInvalid;
                aio_error.property_name = value.invalid_property_name;
                aio_error.property_value = value.invalid_property_value.map(Value::String);
            }
            StatusCode::VersionNotSupported => {
                aio_error.kind = AIOProtocolErrorKind::UnsupportedVersion;
            }
        }
        aio_error
    }