use super::alert::{MsgType, Scope, Status};
use crate::delimited_items::InvalidItemError;
use crate::id::InvalidIdError;
use crate::protobuf::{Alert, InfoConversionError};
use crate::references::ReferenceError;
#[derive(thiserror::Error, Debug)]
pub enum AlertConversionError {
#[error("xmlns is invalid: {0:?}")]
Xmlns(String),
#[error("identifier is invalid: {0}")]
Identifier(InvalidIdError),
#[error("sender is invalid: {0}")]
Sender(InvalidIdError),
#[error("sent is invalid: {0}")]
Sent(chrono::ParseError),
#[error("status is invalid: {0}")]
Status(i32),
#[error("unrepresentable status: {0:?}")]
UnrepresentableStatus(super::alert::Status),
#[error("message type is invalid: {0}")]
MessageType(i32),
#[error("scope is invalid: {0}")]
Scope(i32),
#[error("scope is missing")]
ScopeMissing,
#[error("addresses contains an invalid item: {0}")]
Addresses(InvalidItemError),
#[error("references contains an invalid reference: {0}")]
References(ReferenceError),
#[error("incidents contains an invalid item: {0}")]
Incidents(InvalidItemError),
#[error("info is invalid: {0}")]
Info(InfoConversionError),
}
impl TryFrom<Alert> for crate::v1dot0::Alert {
type Error = AlertConversionError;
fn try_from(value: Alert) -> Result<Self, Self::Error> {
#[allow(deprecated)]
Ok(Self {
identifier: value
.identifier
.try_into()
.map_err(AlertConversionError::Identifier)?,
sender: value
.sender
.try_into()
.map_err(AlertConversionError::Sender)?,
password: value.password,
sent: value.sent.parse().map_err(AlertConversionError::Sent)?,
status: Status::from_i32(value.status)
.ok_or(AlertConversionError::Status(value.status))
.and_then(|v| {
v.try_into()
.map_err(AlertConversionError::UnrepresentableStatus)
})?,
message_type: MsgType::from_i32(value.msg_type)
.map(|v| v.into())
.ok_or(AlertConversionError::MessageType(value.msg_type))?,
source: value.source,
scope: {
let scope = value.scope.ok_or(AlertConversionError::ScopeMissing)?;
Scope::from_i32(scope)
.map(|v| v.into())
.ok_or(AlertConversionError::Scope(scope))?
},
restriction: value.restriction,
addresses: match value.addresses {
Some(v) => Some(v.try_into().map_err(AlertConversionError::Addresses)?),
None => None,
},
codes: value.code,
note: value.note,
references: match value.references {
Some(v) => Some(v.try_into().map_err(AlertConversionError::References)?),
None => None,
},
incidents: match value.incidents {
Some(v) => Some(v.try_into().map_err(AlertConversionError::Incidents)?),
None => None,
},
info: value
.info
.into_iter()
.map(|v| v.try_into())
.collect::<Result<_, _>>()
.map_err(AlertConversionError::Info)?,
})
}
}
impl From<crate::v1dot0::Alert> for Alert {
fn from(value: crate::v1dot0::Alert) -> Self {
#[allow(deprecated)]
Self {
xmlns: "http://www.incident.com/cap/1.0".into(),
identifier: value.identifier.into(),
sender: value.sender.into(),
password: value.password,
sent: value.sent.to_string(),
status: Status::from(value.status) as i32,
msg_type: MsgType::from(value.message_type) as i32,
source: value.source,
scope: Some(Scope::from(value.scope) as i32),
restriction: value.restriction,
addresses: value.addresses.map(|v| v.into()),
code: value.codes,
note: value.note,
references: value.references.map(|v| v.into()),
incidents: value.incidents.map(|v| v.into()),
info: value.info.into_iter().map(|v| v.into()).collect(),
}
}
}
impl TryFrom<Alert> for crate::v1dot1::Alert {
type Error = AlertConversionError;
fn try_from(value: Alert) -> Result<Self, Self::Error> {
Ok(Self {
identifier: value
.identifier
.try_into()
.map_err(AlertConversionError::Identifier)?,
sender: value
.sender
.try_into()
.map_err(AlertConversionError::Sender)?,
sent: value.sent.parse().map_err(AlertConversionError::Sent)?,
status: Status::from_i32(value.status)
.map(|v| v.into())
.ok_or(AlertConversionError::Status(value.status))?,
message_type: MsgType::from_i32(value.msg_type)
.map(|v| v.into())
.ok_or(AlertConversionError::MessageType(value.msg_type))?,
source: value.source,
scope: {
let scope = value.scope.ok_or(AlertConversionError::ScopeMissing)?;
Scope::from_i32(scope)
.map(|v| v.into())
.ok_or(AlertConversionError::Scope(scope))?
},
restriction: value.restriction,
addresses: match value.addresses {
Some(v) => Some(v.try_into().map_err(AlertConversionError::Addresses)?),
None => None,
},
codes: value.code,
note: value.note,
references: match value.references {
Some(v) => Some(v.try_into().map_err(AlertConversionError::References)?),
None => None,
},
incidents: match value.incidents {
Some(v) => Some(v.try_into().map_err(AlertConversionError::Incidents)?),
None => None,
},
info: value
.info
.into_iter()
.map(|v| v.try_into())
.collect::<Result<_, _>>()
.map_err(AlertConversionError::Info)?,
})
}
}
impl From<crate::v1dot1::Alert> for Alert {
fn from(value: crate::v1dot1::Alert) -> Self {
#[allow(deprecated)]
Self {
xmlns: "urn:oasis:names:tc:emergency:cap:1.1".into(),
identifier: value.identifier.into(),
sender: value.sender.into(),
password: None,
sent: value.sent.to_string(),
status: Status::from(value.status) as i32,
msg_type: MsgType::from(value.message_type) as i32,
source: value.source,
scope: Some(Scope::from(value.scope) as i32),
restriction: value.restriction,
addresses: value.addresses.map(|v| v.into()),
code: value.codes,
note: value.note,
references: value.references.map(|v| v.into()),
incidents: value.incidents.map(|v| v.into()),
info: value.info.into_iter().map(|v| v.into()).collect(),
}
}
}
impl TryFrom<Alert> for crate::v1dot2::Alert {
type Error = AlertConversionError;
fn try_from(value: Alert) -> Result<Self, Self::Error> {
Ok(Self {
identifier: value
.identifier
.try_into()
.map_err(AlertConversionError::Identifier)?,
sender: value
.sender
.try_into()
.map_err(AlertConversionError::Sender)?,
sent: value.sent.parse().map_err(AlertConversionError::Sent)?,
status: Status::from_i32(value.status)
.map(|v| v.into())
.ok_or(AlertConversionError::Status(value.status))?,
message_type: MsgType::from_i32(value.msg_type)
.map(|v| v.into())
.ok_or(AlertConversionError::MessageType(value.msg_type))?,
source: value.source,
scope: {
let scope = value.scope.ok_or(AlertConversionError::ScopeMissing)?;
Scope::from_i32(scope)
.map(|v| v.into())
.ok_or(AlertConversionError::Scope(scope))?
},
restriction: value.restriction,
addresses: match value.addresses {
Some(v) => Some(v.try_into().map_err(AlertConversionError::Addresses)?),
None => None,
},
codes: value.code,
note: value.note,
references: match value.references {
Some(v) => Some(v.try_into().map_err(AlertConversionError::References)?),
None => None,
},
incidents: match value.incidents {
Some(v) => Some(v.try_into().map_err(AlertConversionError::Incidents)?),
None => None,
},
info: value
.info
.into_iter()
.map(|v| v.try_into())
.collect::<Result<_, _>>()
.map_err(AlertConversionError::Info)?,
})
}
}
impl From<crate::v1dot2::Alert> for Alert {
fn from(value: crate::v1dot2::Alert) -> Self {
#[allow(deprecated)]
Self {
xmlns: "urn:oasis:names:tc:emergency:cap:1.2".into(),
identifier: value.identifier.into(),
sender: value.sender.into(),
password: None,
sent: value.sent.to_string(),
status: Status::from(value.status) as i32,
msg_type: MsgType::from(value.message_type) as i32,
source: value.source,
scope: Some(Scope::from(value.scope) as i32),
restriction: value.restriction,
addresses: value.addresses.map(|v| v.into()),
code: value.codes,
note: value.note,
references: value.references.map(|v| v.into()),
incidents: value.incidents.map(|v| v.into()),
info: value.info.into_iter().map(|v| v.into()).collect(),
}
}
}