Skip to main content

reifydb_codec/frame/encoding/
rle.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use crate::error::DecodeError;
5
6pub fn try_rle_encode<T: PartialEq + Copy>(
7	slice: &[T],
8	elem_size: usize,
9	encode_value: fn(T, &mut Vec<u8>),
10) -> Option<Vec<u8>> {
11	if slice.is_empty() {
12		return None;
13	}
14
15	let mut run_count = 1usize;
16	let mut prev = slice[0];
17	for &v in &slice[1..] {
18		if v != prev {
19			run_count += 1;
20			prev = v;
21		}
22	}
23
24	let rle_size = run_count * (elem_size + 4);
25	let plain_size = slice.len() * elem_size;
26
27	if rle_size >= plain_size {
28		return None;
29	}
30
31	let mut buf = Vec::with_capacity(rle_size);
32	let mut current = slice[0];
33	let mut count: u32 = 1;
34
35	for &v in &slice[1..] {
36		if v == current {
37			count += 1;
38		} else {
39			encode_value(current, &mut buf);
40			buf.extend_from_slice(&count.to_le_bytes());
41			current = v;
42			count = 1;
43		}
44	}
45
46	encode_value(current, &mut buf);
47	buf.extend_from_slice(&count.to_le_bytes());
48
49	Some(buf)
50}
51
52pub fn decode_rle<T: Copy>(
53	data: &[u8],
54	row_count: usize,
55	elem_size: usize,
56	decode_value: fn(&[u8]) -> T,
57) -> Result<Vec<T>, DecodeError> {
58	let mut values = Vec::with_capacity(row_count);
59	let mut pos = 0;
60	let run_size = elem_size + 4;
61
62	while pos + run_size <= data.len() && values.len() < row_count {
63		let value = decode_value(&data[pos..]);
64		pos += elem_size;
65		let count = u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]) as usize;
66		pos += 4;
67
68		for _ in 0..count {
69			if values.len() >= row_count {
70				break;
71			}
72			values.push(value);
73		}
74	}
75
76	if values.len() != row_count {
77		return Err(DecodeError::InvalidData(format!(
78			"RLE decoded {} values but expected {}",
79			values.len(),
80			row_count
81		)));
82	}
83
84	Ok(values)
85}
86
87pub fn try_rle_encode_varlen(serialized: &[Vec<u8>]) -> Option<Vec<u8>> {
88	if serialized.is_empty() {
89		return None;
90	}
91
92	let mut rle_size = 4 + serialized[0].len() + 4;
93	let mut prev = &serialized[0];
94
95	for v in &serialized[1..] {
96		if v != prev {
97			rle_size += 4 + v.len() + 4;
98			prev = v;
99		}
100	}
101
102	let total_data: usize = serialized.iter().map(|v| v.len()).sum();
103	let plain_size = (serialized.len() + 1) * 4 + total_data;
104
105	if rle_size >= plain_size {
106		return None;
107	}
108
109	let mut buf = Vec::with_capacity(rle_size);
110	let mut current = &serialized[0];
111	let mut count: u32 = 1;
112
113	for v in &serialized[1..] {
114		if v == current {
115			count += 1;
116		} else {
117			buf.extend_from_slice(&(current.len() as u32).to_le_bytes());
118			buf.extend_from_slice(current);
119			buf.extend_from_slice(&count.to_le_bytes());
120			current = v;
121			count = 1;
122		}
123	}
124
125	buf.extend_from_slice(&(current.len() as u32).to_le_bytes());
126	buf.extend_from_slice(current);
127	buf.extend_from_slice(&count.to_le_bytes());
128
129	Some(buf)
130}
131
132pub fn decode_rle_varlen(data: &[u8], row_count: usize) -> Result<Vec<Vec<u8>>, DecodeError> {
133	let mut values = Vec::with_capacity(row_count);
134	let mut pos = 0;
135
136	while values.len() < row_count && pos + 4 <= data.len() {
137		let value_len = u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]) as usize;
138		pos += 4;
139
140		if pos + value_len + 4 > data.len() {
141			return Err(DecodeError::InvalidData("varlen RLE data truncated".to_string()));
142		}
143
144		let value = data[pos..pos + value_len].to_vec();
145		pos += value_len;
146
147		let count = u32::from_le_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]) as usize;
148		pos += 4;
149
150		for _ in 0..count {
151			if values.len() >= row_count {
152				break;
153			}
154			values.push(value.clone());
155		}
156	}
157
158	if values.len() != row_count {
159		return Err(DecodeError::InvalidData(format!(
160			"varlen RLE decoded {} values but expected {}",
161			values.len(),
162			row_count
163		)));
164	}
165
166	Ok(values)
167}
168
169pub fn try_rle_i32(slice: &[i32]) -> Option<Vec<u8>> {
170	try_rle_encode(slice, 4, |v, buf| buf.extend_from_slice(&v.to_le_bytes()))
171}
172
173pub fn try_rle_i64(slice: &[i64]) -> Option<Vec<u8>> {
174	try_rle_encode(slice, 8, |v, buf| buf.extend_from_slice(&v.to_le_bytes()))
175}
176
177pub fn try_rle_u64(slice: &[u64]) -> Option<Vec<u8>> {
178	try_rle_encode(slice, 8, |v, buf| buf.extend_from_slice(&v.to_le_bytes()))
179}
180
181pub fn decode_rle_i32(data: &[u8], row_count: usize) -> Result<Vec<i32>, DecodeError> {
182	decode_rle(data, row_count, 4, |b| i32::from_le_bytes([b[0], b[1], b[2], b[3]]))
183}
184
185pub fn decode_rle_i64(data: &[u8], row_count: usize) -> Result<Vec<i64>, DecodeError> {
186	decode_rle(data, row_count, 8, |b| i64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]))
187}
188
189pub fn decode_rle_u64(data: &[u8], row_count: usize) -> Result<Vec<u64>, DecodeError> {
190	decode_rle(data, row_count, 8, |b| u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]))
191}