#![allow(dead_code)]
use std::sync::Arc;
use chrono::{DateTime, Utc};
use rpki::repository::x509::Time;
use rpki::rtr::payload::{
Aspa, PayloadRef, PayloadType, RouteOrigin, RouterKey
};
use rpki::rtr::server::PayloadSet;
use super::info::PayloadInfo;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct PayloadSnapshot {
origins: PayloadCollection<RouteOrigin>,
router_keys: PayloadCollection<RouterKey>,
aspas: PayloadCollection<Aspa>,
created: DateTime<Utc>,
refresh: Option<Time>,
}
impl Default for PayloadSnapshot {
fn default() -> Self {
PayloadSnapshot {
origins: Default::default(),
router_keys: Default::default(),
aspas: Default::default(),
created: Utc::now(),
refresh: None
}
}
}
impl PayloadSnapshot {
pub fn new(
origins: impl Iterator<Item = (RouteOrigin, PayloadInfo)>,
router_keys: impl Iterator<Item = (RouterKey, PayloadInfo)>,
aspas: impl Iterator<Item = (Aspa, PayloadInfo)>,
refresh: Option<Time>
) -> Self {
Self {
origins: PayloadCollection::from_iter(origins),
router_keys: PayloadCollection::from_iter(router_keys),
aspas: PayloadCollection::from_iter(aspas),
created: Utc::now(),
refresh,
}
}
pub fn created(&self) -> DateTime<Utc> {
self.created
}
pub fn refresh(&self) -> Option<Time> {
self.refresh
}
pub fn payload(
&self
) -> impl Iterator<Item = PayloadRef<'_>> {
self.origins.iter_payload().chain(
self.router_keys.iter_payload()
).chain(
self.aspas.iter_payload()
)
}
pub fn origin_refs(
&self
) -> impl Iterator<Item = (&RouteOrigin, &PayloadInfo)> + '_ {
self.origins.iter()
}
pub fn origins(
&self
) -> impl Iterator<Item = (RouteOrigin, &PayloadInfo)> + '_ {
self.origins.iter().map(|(origin, info)| (*origin, info))
}
pub fn origin_payload(
&self
) -> impl Iterator<Item = PayloadRef<'_>> {
self.origins.iter_payload()
}
pub fn router_keys(
&self
) -> impl Iterator<Item = (&RouterKey, &PayloadInfo)> + '_ {
self.router_keys.iter()
}
pub fn router_key_payload(
&self
) -> impl Iterator<Item = PayloadRef<'_>> {
self.router_keys.iter_payload()
}
pub fn aspas(
&self
) -> impl Iterator<Item = (&Aspa, &PayloadInfo)> + '_ {
self.aspas.iter()
}
pub fn aspa_payload(
&self
) -> impl Iterator<Item = PayloadRef<'_>> {
self.aspas.iter_payload()
}
pub fn arc_iter(self: Arc<Self>) -> SnapshotArcIter {
SnapshotArcIter::new(self)
}
pub fn arc_origin_iter(self: Arc<Self>) -> SnapshotArcOriginIter {
SnapshotArcOriginIter::new(self)
}
pub fn arc_router_key_iter(self: Arc<Self>) -> SnapshotArcRouterKeyIter {
SnapshotArcRouterKeyIter::new(self)
}
pub fn arc_aspa_iter(self: Arc<Self>) -> SnapshotArcAspaIter {
SnapshotArcAspaIter::new(self)
}
}
impl AsRef<PayloadSnapshot> for PayloadSnapshot {
fn as_ref(&self) -> &Self {
self
}
}
#[derive(Clone, Debug)]
struct PayloadCollection<P> {
vec: Vec<(P, PayloadInfo)>,
}
impl<P> Default for PayloadCollection<P> {
fn default() -> Self {
Self { vec: Default::default() }
}
}
impl<P> PayloadCollection<P> {
pub fn from_vec(mut vec: Vec<(P, PayloadInfo)>) -> Self
where P: Ord {
vec.sort_unstable_by(|left, right| left.0.cmp(&right.0));
Self { vec}
}
pub fn len(&self) -> usize {
self.vec.len()
}
pub fn get(&self, idx: usize) -> Option<(&P, &PayloadInfo)> {
self.vec.get(idx).map(|item| (&item.0, &item.1))
}
pub fn iter(&self) -> impl Iterator<Item = (&P, &PayloadInfo)> {
self.vec.iter().map(|item| (&item.0, &item.1))
}
pub fn iter_ref(
&self
) -> impl Iterator<Item = (PayloadRef<'_>, &PayloadInfo)>
where
for<'a> &'a P: Into<PayloadRef<'a>>
{
self.vec.iter().map(|item| ((&item.0).into(), &item.1))
}
pub fn iter_payload(&self) -> impl Iterator<Item = PayloadRef<'_>>
where for<'a> &'a P: Into<PayloadRef<'a>> {
self.vec.iter().map(|item| (&item.0).into())
}
}
impl<P: Ord> FromIterator<(P, PayloadInfo)> for PayloadCollection<P> {
fn from_iter<I: IntoIterator<Item = (P, PayloadInfo)>>(iter: I) -> Self {
Self::from_vec(
iter.into_iter().collect()
)
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for PayloadCollection<RouteOrigin> {
fn arbitrary(
u: &mut arbitrary::Unstructured<'a>
) -> arbitrary::Result<Self> {
let mut vec = Vec::<(RouteOrigin, PayloadInfo)>::arbitrary(u)?;
vec.sort_unstable_by(|left, right| left.0.cmp(&right.0));
vec.dedup_by(|left, right| left.0 == right.0);
Ok(Self { vec })
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for PayloadCollection<RouterKey> {
fn arbitrary(
u: &mut arbitrary::Unstructured<'a>
) -> arbitrary::Result<Self> {
let mut vec = Vec::<(RouterKey, PayloadInfo)>::arbitrary(u)?;
vec.sort_unstable_by(|left, right| left.0.cmp(&right.0));
vec.dedup_by(|left, right| left.0 == right.0);
Ok(Self { vec })
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for PayloadCollection<Aspa> {
fn arbitrary(
u: &mut arbitrary::Unstructured<'a>
) -> arbitrary::Result<Self> {
let mut vec = Vec::<(Aspa, PayloadInfo)>::arbitrary(u)?;
vec.sort_unstable_by(|left, right| left.0.cmp(&right.0));
vec.dedup_by(|left, right| left.0.key() == right.0.key());
Ok(Self { vec })
}
}
#[derive(Clone, Debug)]
pub struct SnapshotArcIter {
snapshot: Arc<PayloadSnapshot>,
current_type: PayloadType,
next: usize,
}
impl SnapshotArcIter {
fn new(snapshot: Arc<PayloadSnapshot>) -> Self {
Self {
snapshot,
current_type: PayloadType::Origin,
next: 0,
}
}
pub fn next_with_info(
&mut self
) -> Option<(PayloadRef<'_>, &PayloadInfo)> {
if matches!(self.current_type, PayloadType::Origin) {
if let Some(res) = self.snapshot.origins.get(self.next) {
self.next += 1;
return Some((res.0.into(), res.1));
}
self.current_type = PayloadType::RouterKey;
self.next = 0;
}
if matches!(self.current_type, PayloadType::RouterKey) {
if let Some(res) = self.snapshot.router_keys.get(self.next) {
self.next += 1;
return Some((res.0.into(), res.1))
}
self.current_type = PayloadType::Aspa;
self.next = 0;
}
assert!(matches!(self.current_type, PayloadType::Aspa));
let res = self.snapshot.aspas.get(self.next)?;
self.next += 1;
Some((res.0.into(), res.1))
}
}
impl PayloadSet for SnapshotArcIter {
fn next(&mut self) -> Option<PayloadRef<'_>> {
self.next_with_info().map(|(res, _)| res)
}
}
#[derive(Clone, Debug)]
pub struct SnapshotArcOriginIter {
snapshot: Arc<PayloadSnapshot>,
next: usize
}
impl SnapshotArcOriginIter {
fn new(snapshot: Arc<PayloadSnapshot>) -> Self {
Self {
snapshot,
next: 0,
}
}
pub fn next_with_info(&mut self) -> Option<(RouteOrigin, &PayloadInfo)> {
let (origin, info) = self.snapshot.origins.get(self.next)?;
self.next += 1;
Some((*origin, info))
}
}
impl Iterator for SnapshotArcOriginIter {
type Item = RouteOrigin;
fn next(&mut self) -> Option<Self::Item> {
self.next_with_info().map(|item| item.0)
}
}
#[derive(Clone, Debug)]
pub struct SnapshotArcRouterKeyIter {
snapshot: Arc<PayloadSnapshot>,
next: usize
}
impl SnapshotArcRouterKeyIter {
fn new(snapshot: Arc<PayloadSnapshot>) -> Self {
Self {
snapshot,
next: 0,
}
}
pub fn next_with_info(&mut self) -> Option<(&RouterKey, &PayloadInfo)> {
let res = self.snapshot.router_keys.get(self.next)?;
self.next += 1;
Some(res)
}
}
#[derive(Clone, Debug)]
pub struct SnapshotArcAspaIter {
snapshot: Arc<PayloadSnapshot>,
next: usize
}
impl SnapshotArcAspaIter {
fn new(snapshot: Arc<PayloadSnapshot>) -> Self {
Self {
snapshot,
next: 0,
}
}
pub fn next_with_info(&mut self) -> Option<(&Aspa, &PayloadInfo)> {
let res = self.snapshot.aspas.get(self.next)?;
self.next += 1;
Some(res)
}
}