use crate::wire::{ConversationId, DeliverySeq};
#[derive(Debug, Eq)]
pub struct ObserverProgressProjection {
conversation_id: ConversationId,
new_observer_progress: DeliverySeq,
source: Option<crate::lifecycle::checkpoint_codec::ObserverProjectionSource>,
}
impl PartialEq for ObserverProgressProjection {
fn eq(&self, other: &Self) -> bool {
self.conversation_id == other.conversation_id
&& self.new_observer_progress == other.new_observer_progress
}
}
impl ObserverProgressProjection {
#[cfg(any(test, feature = "test-support"))]
pub(in crate::lifecycle) const fn new(
conversation_id: ConversationId,
new_observer_progress: DeliverySeq,
) -> Self {
Self {
conversation_id,
new_observer_progress,
source: None,
}
}
pub(in crate::lifecycle) const fn sourced(
conversation_id: ConversationId,
new_observer_progress: DeliverySeq,
source: crate::lifecycle::checkpoint_codec::ObserverProjectionSource,
) -> Self {
Self::with_checkpoint_source(conversation_id, new_observer_progress, Some(source))
}
pub(in crate::lifecycle) const fn with_checkpoint_source(
conversation_id: ConversationId,
new_observer_progress: DeliverySeq,
source: Option<crate::lifecycle::checkpoint_codec::ObserverProjectionSource>,
) -> Self {
Self {
conversation_id,
new_observer_progress,
source,
}
}
#[doc(hidden)]
pub fn encode_checkpoint_source(
&self,
) -> Result<alloc::vec::Vec<u8>, crate::lifecycle::OwnerCheckpointRestoreError> {
crate::lifecycle::checkpoint_codec::encode_observer_source(
self.conversation_id,
self.new_observer_progress,
self.source
.ok_or(crate::lifecycle::OwnerCheckpointRestoreError::Field(
"observer_projection.native_source",
))?,
)
}
#[doc(hidden)]
#[must_use]
pub const fn checkpoint_source_participant_id(&self) -> Option<crate::wire::ParticipantId> {
match self.source {
Some(source) => Some(source.participant_id()),
None => None,
}
}
#[doc(hidden)]
#[must_use]
pub const fn checkpoint_source_binding_epoch(&self) -> Option<crate::wire::BindingEpoch> {
match self.source {
Some(source) => source.binding_epoch(),
None => None,
}
}
#[doc(hidden)]
#[must_use]
pub const fn checkpoint_source_kind(
&self,
) -> Option<crate::lifecycle::checkpoint_codec::ObserverProjectionCheckpointKind> {
match self.source {
Some(source) => Some(source.kind()),
None => None,
}
}
#[cfg(any(test, feature = "test-support"))]
#[must_use]
pub const fn for_test(
conversation_id: ConversationId,
new_observer_progress: DeliverySeq,
) -> Self {
Self::new(conversation_id, new_observer_progress)
}
#[must_use]
pub const fn conversation_id(&self) -> ConversationId {
self.conversation_id
}
#[must_use]
pub const fn new_observer_progress(&self) -> DeliverySeq {
self.new_observer_progress
}
}
impl ObserverProgressProjection {
#[must_use]
pub fn encode_checkpoint(&self) -> [u8; 16] {
let mut body = [0; 16];
body[..8].copy_from_slice(&self.conversation_id.to_be_bytes());
body[8..].copy_from_slice(&self.new_observer_progress.to_be_bytes());
body
}
pub fn restore_checkpoint(
body: &[u8],
source: Self,
) -> Result<Self, crate::lifecycle::OwnerCheckpointRestoreError> {
if body != source.encode_checkpoint() {
return Err(crate::lifecycle::OwnerCheckpointRestoreError::Field(
"observer_projection.source",
));
}
Ok(source)
}
}