#alert #cap #oasis #xml #public-safety

oasiscap

为OASIS通用警报协议(CAP)提供类型

2个不稳定版本

0.2.0 2022年3月17日
0.1.0 2022年2月18日

#2182 in 解析器实现

MIT/Apache

265KB
5K SLoC

oasiscap

为OASIS 通用警报协议提供类型。

示例

let alert: oasiscap::Alert = r#"
<?xml version = "1.0" encoding = "UTF-8"?>
<alert xmlns = "urn:oasis:names:tc:emergency:cap:1.2">
  <identifier>43b080713727</identifier>
  <sender>[email protected]</sender>
  <sent>2003-04-02T14:39:01-05:00</sent>
  <status>Actual</status>
  <msgType>Alert</msgType>
  <scope>Public</scope>
  <info>
    <!-- … -->
  </info>
</alert>
"#?;

match &alert {
    oasiscap::Alert::V1dot0(alert) => println!("CAP v1.0: {:?}", alert),
    oasiscap::Alert::V1dot1(alert) => println!("CAP v1.1: {:?}", alert),
    oasiscap::Alert::V1dot2(alert) => println!("CAP v1.2: {:?}", alert),
}

// Upgrade to the latest CAP version
let alert: oasiscap::v1dot2::Alert = alert.into_latest();

// Convert back to XML again
let alert_xml = alert.to_string();

一致性

CAP规范分为人类可读和机器可读两部分。CAP v1.2 § 4.2解释了

一个XML 1.0文档如果且仅如果满足以下条件才是符合CAP V1.2消息的

a) 根据以下模式有效,并且

b) 它的元素内容和属性值满足第3节中规定的所有附加强制性要求。

考虑以下<polygon>元素。机器可读的XML模式表明多边形只是一个字符串

<element name = "polygon" type = "xs:string" minOccurs = "0" maxOccurs = "unbounded"/>

人类可读的文档表明多边形是一个特定地理空间参考框架中闭合多边形的字符串描述,并在第3节中提出了以下要求

(1) 代码值:地理多边形由空格分隔的WGS 84坐标对列表表示。(见本节末尾的WGS 84注释)

(2) 至少必须有4个坐标对,并且第一和最后一个坐标对必须相同。

这个crate实现了第3节中的这些规则

use oasiscap::geo::Polygon;

// 4 points, where the last point is the first point, makes a Polygon:
assert!("1,1 2,2 3,3 1,1".parse::<Polygon>().is_ok());

// 4 points where the last point differs does not make a Polygon:
assert!("1,1 2,2 3,3 4,4".parse::<Polygon>().is_err());

// 3 points does not make a Polygon:
assert!("1,1 2,2 1,1".parse::<Polygon>().is_err());

// invalid WGS-84 coordinates do not make a Polygon:
assert!("100,100 200,200 300,300 100,100".parse::<Polygon>().is_err());

所有这些字符串都符合XML模式,但只有第一个字符串作为多边形有意义。因此,这个crate接受第一个字符串,拒绝其他字符串。

话虽如此,一些现实世界的CAP警报违反了第3节中的要求,但仍然有意义

<polygon></polygon>

多边形是可选的,因此元素可以并且应该完全省略。另一方面,空字符串根据XML模式是有效的,其意图明确,即使技术上不符合规范。因此,这个crate接受空的多边形元素作为省略多边形同义词,而不是返回错误。

这个crate的目的是始终解析符合规范的CAP消息,并始终生成符合规范的CAP消息。同时,这个crate的目的是为了保持意义而严格,而不是为了严格而严格。因此,它不会拒绝所有不符合规范的CAP消息,特别是对于常见的实现错误,这些错误有合理的、明确的解释。

性能

oasiscap 在正确性上优于速度,但仍然相当快速。在一个使用未指定版本的此库、Rust 和底层操作系统的行业标准开发者笔记本电脑上,从 XML 解析典型的 oasiscap::Alert 大约需要 55µs,每核心每秒的吞吐量约为 18,000 个警报。从典型的 oasiscap::Alert 生成 XML 大约需要 27µs,每核心每秒的吞吐量约为 38,000 个警报。

克隆仓库并运行 cargo bench 来查看它在你环境中的性能。

协议缓冲区

Google Public Alerts 在 Java 包名 com.google.publicalerts.cap 下定义了 CAP 协议缓冲区表示。当使用 prost 功能构建时,此包可选地提供 oasiscap::protobuf。这些数据类型与这些协议缓冲区消息类型完全对应。

协议缓冲区的表示比通常解析的 oasiscap 类型更宽松:时间戳可以没有时区,多边形不必闭合,必需字段可以缺失等。因此,此包还提供了转换

// Decoding from protobuf bytes can fail:
let protobuf_alert: oasiscap::protobuf::Alert = prost::Message::decode(
    protobuf_encoded_bytes.as_slice()
)?;

// Converting to an `oasiscap::Alert` can fail:
let alert: oasiscap::Alert = protobuf_alert.try_into()?;

// Converting back to an `oasiscap::protobuf::Alert` cannot fail:
let alert: oasiscap::protobuf::Alert = alert.into();

// Nor can encoding protobuf bytes:
let protobuf_encoded_bytes = prost::Message::encode_to_vec(&alert);

协议缓冲区比 XML 提供显著更好的性能

  • &[u8]oasiscap::protobuf::Alert:2µs
  • oasiscap::protobuf::Alertoasiscap::Alert:2µs
  • oasiscap::Alertoasiscap::protobuf::Alert:1µs
  • oasiscap::protobuf::AlertVec<u8>:0.3µs

依赖关系

~6–16MB
~211K SLoC