cu29_runtime/
continuity.rs1use alloc::vec::Vec;
4use bincode::{Decode, Encode};
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode)]
7pub enum SourceGapReason {
8 RlcWindowExpired,
9 SessionEnded,
10 LateJoin,
11 RecoveryPoint,
13}
14
15#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)]
19pub enum StreamContinuityRecord<B = Vec<u8>> {
20 Manifest { record: B },
22 Gap {
23 first_id: u64,
24 last_id: u64,
25 reason: SourceGapReason,
26 },
27 RecoveryPoint { copperlist_id: u64, record: B },
29 Finished { next_copperlist_id: u64 },
31}
32
33pub fn validate_replay_continuity(
36 expected: u64,
37 actual: u64,
38 keyframe: Option<u64>,
39) -> cu29_traits::CuResult<()> {
40 if keyframe.is_some_and(|boundary| boundary != actual) {
41 return Err("Replay keyframe does not match the CopperList boundary".into());
42 }
43 if actual != expected && keyframe != Some(actual) {
44 return Err("Replay cannot cross an unhealed CopperList gap without a keyframe".into());
45 }
46 Ok(())
47}