///|
priv struct WireRawAttribute {
flags : Int32
code : Int32
value : Array[Int32]
} derive(@json.FromJson)
///|
priv struct WireAttributes {
origin : Int32?
path : Array[AsSegment]
wire_path : Array[AsSegment]
as4_path : Array[AsSegment]
next_hop : String?
med : UInt32?
local_pref : UInt32?
atomic_aggregate : Bool
aggregator : Aggregator?
wire_aggregator : Aggregator?
as4_aggregator : Aggregator?
raw_attributes : Array[WireRawAttribute]
communities : Array[UInt32]
large_communities : Array[(UInt32, UInt32, UInt32)]
other : Array[WireRawAttribute]
} derive(@json.FromJson)
///|
fn wire_raw(
values : Array[WireRawAttribute],
) -> Array[RawAttribute] raise ParseError {
values.map(value => {
if value.flags < 0 ||
value.flags > 255 ||
value.code < 0 ||
value.code > 255 ||
value.value.any(fn(n) { n < 0 || n > 255 }) {
raise Invalid(0, "原始属性字节超出范围")
}
{
flags: value.flags,
code: value.code,
value: Bytes::from_array(value.value.map(fn(n) { n.to_byte() })),
}
})
}
///|
fn WireAttributes::attributes(
self : WireAttributes,
) -> Attributes raise ParseError {
for segment in self.path + self.wire_path + self.as4_path {
if segment.kind < 1 || segment.kind > 4 {
raise Invalid(0, "AS 路径分段类型无效")
}
}
if self.origin is Some(n) && (n < 0 || n > 2) {
raise Invalid(0, "ORIGIN 值无效")
}
{
origin: self.origin,
path: self.path,
wire_path: self.wire_path,
as4_path: self.as4_path,
next_hop: self.next_hop,
med: self.med,
local_pref: self.local_pref,
atomic_aggregate: self.atomic_aggregate,
aggregator: self.aggregator,
wire_aggregator: self.wire_aggregator,
as4_aggregator: self.as4_aggregator,
raw_attributes: wire_raw(self.raw_attributes),
communities: self.communities,
large_communities: self.large_communities,
other: wire_raw(self.other),
}
}
///|
priv struct WireSemanticSnapshot {
active : Bool
attributes : WireAttributes
} derive(@json.FromJson)
///|
priv struct WireSemanticChange {
prefix : String
kind : String
before : WireSemanticSnapshot?
after : WireSemanticSnapshot
churn_count : Int32?
} derive(@json.FromJson)
///|
/// 从结构化前后状态重算键,仍调用核心规范化逻辑,不信任输入自带的关联键。
fn semantic_change_from_json(text : String) -> Change raise ParseError {
let wire : WireSemanticChange = @json.from_json(@json.parse(text)) catch {
_ => raise Invalid(0, "变化前后状态 JSON 无效")
}
let after = wire.after.attributes.attributes()
let before = match wire.before {
Some(snapshot) =>
Some({
timestamp: 0U,
microseconds: None,
active: snapshot.active,
attributes: snapshot.attributes.attributes(),
source: None,
})
None => None
}
let change : Change = {
schema_version: "2.0",
timestamp: 0U,
microseconds: None,
prefix: wire.prefix,
path_id: None,
peer_asn: 0U,
peer_ip: "",
outbound: false,
kind: wire.kind,
source: None,
before,
after: {
timestamp: 0U,
microseconds: None,
active: wire.after.active,
attributes: after,
source: None,
},
diff: route_diff(after, after),
churn_count: wire.churn_count,
correlation_key: None,
}
change
}
///|
pub fn correlation_key_from_json(text : String) -> String raise ParseError {
semantic_change_from_json(text).correlation_key()
}
///|
/// 去重比关联规则更严格:比较完整规范化属性,而非只比较某一类变化的键。
pub fn correlation_semantics_from_json(
text : String,
) -> String raise ParseError {
let change = semantic_change_from_json(text)
Json::object({
"key": @json.parse(change.correlation_key()) catch {
_ => Json::null()
},
"before": change.before
.map(fn(s) {
Json::object({
"active": Json(s.active),
"origin_as": Json(origin_as(s.attributes.path)),
"attributes": semantic_attributes(s.attributes).to_json(),
})
})
.unwrap_or(Json::null()),
"after": Json::object({
"active": Json(change.after.active),
"origin_as": Json(origin_as(change.after.attributes.path)),
"attributes": semantic_attributes(change.after.attributes).to_json(),
}),
"churn_count": Json(change.churn_count),
}).stringify()
}