krabka_verified/restore/
rewritten_record.rs1#[cfg(creusot)]
2use super::{kafka_record_timestamp, restore_record_placeable};
3use {
4 super::{
5 RestoreBatchFrame, RestoreLayout, RestoreProducer, RestoreRecordDeltas,
6 restore_record_coordinates,
7 },
8 creusot_std::prelude::*,
9};
10
11#[cfg(creusot)]
13#[cfg_attr(test, mutants::skip)]
14#[logic(open)]
15pub fn legal_producer(producer: RestoreProducer) -> bool {
25 pearlite! {
26 if producer.control {
27 non_idempotent_producer(producer)
28 || (producer.transactional
29 && producer.producer_id@ >= 0
30 && producer.producer_epoch@ >= 0
31 && producer.base_sequence@ == -1)
32 } else {
33 non_idempotent_producer(producer)
34 || (producer.producer_id@ >= 0
35 && producer.producer_epoch@ >= 0
36 && producer.base_sequence@ >= 0)
37 }
38 }
39}
40
41#[cfg(creusot)]
43#[cfg_attr(test, mutants::skip)]
44#[logic(open)]
45pub fn non_idempotent_producer(producer: RestoreProducer) -> bool {
47 pearlite! {
48 !producer.transactional
49 && producer.producer_id@ == -1
50 && producer.producer_epoch@ == -1
51 && producer.base_sequence@ == -1
52 }
53}
54
55#[cfg(creusot)]
57#[cfg_attr(test, mutants::skip)]
58#[logic(open)]
59pub fn legal_header(layout: RestoreLayout, control: bool) -> bool {
66 pearlite! {
67 layout.base_offset@ >= 0
68 && layout.last_offset_delta@ >= 0
69 && layout.records_count@ >= 0
70 && (control ==> layout.last_offset_delta@ == 0 && layout.records_count@ <= 1)
71 && layout.base_offset@ + layout.last_offset_delta@ + 1 <= i64::MAX@
72 }
73}
74
75#[ensures(match result {
78 Some(frontier) => legal_header(layout, producer.control)
79 && legal_producer(producer)
80 && frontier@ == layout.base_offset@ + layout.last_offset_delta@ + 1,
81 None => !(legal_header(layout, producer.control) && legal_producer(producer)),
82})]
83#[must_use]
84pub fn restore_rewritten_batch_header(
85 layout: RestoreLayout,
86 producer: RestoreProducer,
87) -> Option<i64> {
88 let non_idempotent = !producer.transactional
89 && producer.producer_id == -1
90 && producer.producer_epoch == -1
91 && producer.base_sequence == -1;
92 let producer_legal = if producer.control {
93 non_idempotent
94 || (producer.transactional
95 && producer.producer_id >= 0
96 && producer.producer_epoch >= 0
97 && producer.base_sequence == -1)
98 } else {
99 non_idempotent
100 || (producer.producer_id >= 0
101 && producer.producer_epoch >= 0
102 && producer.base_sequence >= 0)
103 };
104 if !producer_legal
105 || layout.base_offset < 0
106 || layout.last_offset_delta < 0
107 || layout.records_count < 0
108 || (producer.control && (layout.last_offset_delta != 0 || layout.records_count > 1))
109 {
110 return None;
111 }
112
113 layout
114 .base_offset
115 .checked_add(i64::from(layout.last_offset_delta))?
116 .checked_add(1)
117}
118
119#[cfg(creusot)]
121#[cfg_attr(test, mutants::skip)]
122#[logic(open)]
123pub fn restore_rewrite_record_legal(
129 previous_offset_delta: Option<i32>,
130 frame: RestoreBatchFrame,
131 record: RestoreRecordDeltas,
132) -> bool {
133 pearlite! {
134 restore_record_placeable(frame, record)
135 && match previous_offset_delta {
136 Some(previous) => previous@ < record.offset_delta@,
137 None => true,
138 }
139 && kafka_record_timestamp(frame, record) <= frame.max_timestamp@
140 }
141}
142
143#[ensures(match result {
146 Some((offset, timestamp)) => restore_rewrite_record_legal(previous_offset_delta, frame, record)
147 && offset@ == frame.base_offset@ + record.offset_delta@
148 && timestamp@ == kafka_record_timestamp(frame, record),
149 None => !restore_rewrite_record_legal(previous_offset_delta, frame, record),
150})]
151#[must_use]
152pub fn restore_rewritten_record(
153 previous_offset_delta: Option<i32>,
154 frame: RestoreBatchFrame,
155 record: RestoreRecordDeltas,
156) -> Option<(i64, i64)> {
157 if previous_offset_delta.is_some_and(|previous| previous >= record.offset_delta) {
158 return None;
159 }
160 let coordinates = restore_record_coordinates(frame, record)?;
161 if coordinates.1 > frame.max_timestamp {
162 None
163 } else {
164 Some(coordinates)
165 }
166}