oxihuman_core/
patch_buffer.rs1#![allow(dead_code)]
4
5#[allow(dead_code)]
7#[derive(Debug, Clone)]
8pub struct Patch {
9 pub offset: usize,
10 pub data: Vec<u8>,
11}
12
13#[allow(dead_code)]
14pub struct PatchBuffer {
15 patches: Vec<Patch>,
16 applied_count: u32,
17}
18
19#[allow(dead_code)]
20impl PatchBuffer {
21 pub fn new() -> Self {
22 Self {
23 patches: Vec::new(),
24 applied_count: 0,
25 }
26 }
27 pub fn add_patch(&mut self, offset: usize, data: &[u8]) {
28 self.patches.push(Patch {
29 offset,
30 data: data.to_vec(),
31 });
32 }
33 pub fn apply_to(&mut self, buf: &mut [u8]) -> u32 {
34 let mut applied = 0u32;
35 for p in &self.patches {
36 let end = (p.offset + p.data.len()).min(buf.len());
37 if p.offset < buf.len() {
38 let len = end - p.offset;
39 buf[p.offset..end].copy_from_slice(&p.data[..len]);
40 applied += 1;
41 }
42 }
43 self.applied_count += applied;
44 self.patches.clear();
45 applied
46 }
47 pub fn patch_count(&self) -> usize {
48 self.patches.len()
49 }
50 pub fn is_empty(&self) -> bool {
51 self.patches.is_empty()
52 }
53 pub fn applied_count(&self) -> u32 {
54 self.applied_count
55 }
56 pub fn total_bytes(&self) -> usize {
57 self.patches.iter().map(|p| p.data.len()).sum()
58 }
59 pub fn clear(&mut self) {
60 self.patches.clear();
61 }
62 pub fn patches(&self) -> &[Patch] {
63 &self.patches
64 }
65 pub fn max_offset(&self) -> usize {
66 self.patches
67 .iter()
68 .map(|p| p.offset + p.data.len())
69 .max()
70 .unwrap_or(0)
71 }
72}
73
74impl Default for PatchBuffer {
75 fn default() -> Self {
76 Self::new()
77 }
78}
79
80#[allow(dead_code)]
81pub fn new_patch_buffer() -> PatchBuffer {
82 PatchBuffer::new()
83}
84#[allow(dead_code)]
85pub fn pb_add(b: &mut PatchBuffer, offset: usize, data: &[u8]) {
86 b.add_patch(offset, data);
87}
88#[allow(dead_code)]
89pub fn pb_apply(b: &mut PatchBuffer, buf: &mut [u8]) -> u32 {
90 b.apply_to(buf)
91}
92#[allow(dead_code)]
93pub fn pb_count(b: &PatchBuffer) -> usize {
94 b.patch_count()
95}
96#[allow(dead_code)]
97pub fn pb_is_empty(b: &PatchBuffer) -> bool {
98 b.is_empty()
99}
100#[allow(dead_code)]
101pub fn pb_applied_count(b: &PatchBuffer) -> u32 {
102 b.applied_count()
103}
104#[allow(dead_code)]
105pub fn pb_total_bytes(b: &PatchBuffer) -> usize {
106 b.total_bytes()
107}
108#[allow(dead_code)]
109pub fn pb_clear(b: &mut PatchBuffer) {
110 b.clear();
111}
112#[allow(dead_code)]
113pub fn pb_max_offset(b: &PatchBuffer) -> usize {
114 b.max_offset()
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 #[test]
121 fn test_add_apply() {
122 let mut b = new_patch_buffer();
123 pb_add(&mut b, 2, &[9, 8]);
124 let mut buf = [0u8; 8];
125 pb_apply(&mut b, &mut buf);
126 assert_eq!(buf[2], 9);
127 assert_eq!(buf[3], 8);
128 }
129 #[test]
130 fn test_clears_after_apply() {
131 let mut b = new_patch_buffer();
132 pb_add(&mut b, 0, &[1]);
133 let mut buf = [0u8; 4];
134 pb_apply(&mut b, &mut buf);
135 assert!(pb_is_empty(&b));
136 }
137 #[test]
138 fn test_applied_count() {
139 let mut b = new_patch_buffer();
140 pb_add(&mut b, 0, &[1]);
141 let mut buf = [0u8; 4];
142 pb_apply(&mut b, &mut buf);
143 assert_eq!(pb_applied_count(&b), 1);
144 }
145 #[test]
146 fn test_patch_count() {
147 let mut b = new_patch_buffer();
148 pb_add(&mut b, 0, &[1]);
149 pb_add(&mut b, 1, &[2]);
150 assert_eq!(pb_count(&b), 2);
151 }
152 #[test]
153 fn test_total_bytes() {
154 let mut b = new_patch_buffer();
155 pb_add(&mut b, 0, &[1, 2, 3]);
156 assert_eq!(pb_total_bytes(&b), 3);
157 }
158 #[test]
159 fn test_out_of_bounds_skipped() {
160 let mut b = new_patch_buffer();
161 pb_add(&mut b, 100, &[1, 2]);
162 let mut buf = [0u8; 4];
163 let n = pb_apply(&mut b, &mut buf);
164 assert_eq!(n, 0);
165 }
166 #[test]
167 fn test_clear() {
168 let mut b = new_patch_buffer();
169 pb_add(&mut b, 0, &[1]);
170 pb_clear(&mut b);
171 assert!(pb_is_empty(&b));
172 }
173 #[test]
174 fn test_max_offset() {
175 let mut b = new_patch_buffer();
176 pb_add(&mut b, 5, &[1, 2, 3]);
177 assert_eq!(pb_max_offset(&b), 8);
178 }
179 #[test]
180 fn test_empty_initially() {
181 let b = new_patch_buffer();
182 assert!(pb_is_empty(&b));
183 }
184 #[test]
185 fn test_multiple_patches() {
186 let mut b = new_patch_buffer();
187 pb_add(&mut b, 0, &[0xAA]);
188 pb_add(&mut b, 3, &[0xBB]);
189 let mut buf = [0u8; 8];
190 pb_apply(&mut b, &mut buf);
191 assert_eq!(buf[0], 0xAA);
192 assert_eq!(buf[3], 0xBB);
193 }
194}