Skip to main content

reddb_server/storage/primitives/
encoding.rs

1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
2
3#[derive(Debug)]
4pub struct DecodeError(pub &'static str);
5
6#[inline]
7pub fn write_varu32(buf: &mut Vec<u8>, mut value: u32) {
8    while value >= 0x80 {
9        buf.push((value as u8) | 0x80);
10        value >>= 7;
11    }
12    buf.push(value as u8);
13}
14
15#[inline]
16pub fn write_varu64(buf: &mut Vec<u8>, mut value: u64) {
17    while value >= 0x80 {
18        buf.push((value as u8) | 0x80);
19        value >>= 7;
20    }
21    buf.push(value as u8);
22}
23
24#[inline]
25pub fn write_vari32(buf: &mut Vec<u8>, value: i32) {
26    let zigzag = ((value << 1) ^ (value >> 31)) as u32;
27    write_varu32(buf, zigzag);
28}
29
30#[inline]
31pub fn write_vari64(buf: &mut Vec<u8>, value: i64) {
32    let zigzag = ((value << 1) ^ (value >> 63)) as u64;
33    write_varu64(buf, zigzag);
34}
35
36#[inline]
37pub fn read_varu32(bytes: &[u8], pos: &mut usize) -> Result<u32, DecodeError> {
38    let mut result = 0u32;
39    let mut shift = 0u32;
40    while *pos < bytes.len() {
41        let byte = bytes[*pos];
42        *pos += 1;
43        result |= ((byte & 0x7F) as u32) << shift;
44        if byte & 0x80 == 0 {
45            return Ok(result);
46        }
47        shift += 7;
48        if shift >= 35 {
49            return Err(DecodeError("varu32 overflow"));
50        }
51    }
52    Err(DecodeError("unexpected eof (varu32)"))
53}
54
55#[inline]
56pub fn read_varu64(bytes: &[u8], pos: &mut usize) -> Result<u64, DecodeError> {
57    let mut result = 0u64;
58    let mut shift = 0u32;
59    while *pos < bytes.len() {
60        let byte = bytes[*pos];
61        *pos += 1;
62        result |= ((byte & 0x7F) as u64) << shift;
63        if byte & 0x80 == 0 {
64            return Ok(result);
65        }
66        shift += 7;
67        if shift >= 70 {
68            return Err(DecodeError("varu64 overflow"));
69        }
70    }
71    Err(DecodeError("unexpected eof (varu64)"))
72}
73
74#[inline]
75pub fn read_vari32(bytes: &[u8], pos: &mut usize) -> Result<i32, DecodeError> {
76    let raw = read_varu32(bytes, pos)?;
77    Ok(((raw >> 1) as i32) ^ (-((raw & 1) as i32)))
78}
79
80#[inline]
81pub fn read_vari64(bytes: &[u8], pos: &mut usize) -> Result<i64, DecodeError> {
82    let raw = read_varu64(bytes, pos)?;
83    Ok(((raw >> 1) as i64) ^ (-((raw & 1) as i64)))
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
87pub struct IpKey {
88    pub bytes: [u8; 16],
89    pub len: u8,
90}
91
92impl IpKey {
93    pub fn from(addr: &IpAddr) -> Self {
94        match addr {
95            IpAddr::V4(v4) => {
96                let mut bytes = [0u8; 16];
97                bytes[..4].copy_from_slice(&v4.octets());
98                Self { bytes, len: 4 }
99            }
100            IpAddr::V6(v6) => {
101                let mut bytes = [0u8; 16];
102                bytes.copy_from_slice(&v6.octets());
103                Self { bytes, len: 16 }
104            }
105        }
106    }
107
108    pub fn to_ip(self) -> IpAddr {
109        if self.len == 4 {
110            IpAddr::V4(Ipv4Addr::new(
111                self.bytes[0],
112                self.bytes[1],
113                self.bytes[2],
114                self.bytes[3],
115            ))
116        } else {
117            IpAddr::V6(Ipv6Addr::from(self.bytes))
118        }
119    }
120}
121
122#[inline]
123pub fn write_ip(buf: &mut Vec<u8>, addr: &IpAddr) {
124    match addr {
125        IpAddr::V4(v4) => {
126            buf.push(0);
127            buf.extend_from_slice(&v4.octets());
128        }
129        IpAddr::V6(v6) => {
130            buf.push(1);
131            buf.extend_from_slice(&v6.octets());
132        }
133    }
134}
135
136#[inline]
137pub fn read_ip(bytes: &[u8], pos: &mut usize) -> Result<IpAddr, DecodeError> {
138    if *pos >= bytes.len() {
139        return Err(DecodeError("unexpected eof (ip tag)"));
140    }
141    let tag = bytes[*pos];
142    *pos += 1;
143    match tag {
144        0 => {
145            if *pos + 4 > bytes.len() {
146                return Err(DecodeError("unexpected eof (ipv4)"));
147            }
148            let mut octets = [0u8; 4];
149            octets.copy_from_slice(&bytes[*pos..*pos + 4]);
150            *pos += 4;
151            Ok(IpAddr::V4(Ipv4Addr::from(octets)))
152        }
153        1 => {
154            if *pos + 16 > bytes.len() {
155                return Err(DecodeError("unexpected eof (ipv6)"));
156            }
157            let mut octets = [0u8; 16];
158            octets.copy_from_slice(&bytes[*pos..*pos + 16]);
159            *pos += 16;
160            Ok(IpAddr::V6(Ipv6Addr::from(octets)))
161        }
162        _ => Err(DecodeError("invalid ip tag")),
163    }
164}
165
166#[inline]
167pub fn write_bytes(buf: &mut Vec<u8>, data: &[u8]) {
168    write_varu32(buf, data.len() as u32);
169    buf.extend_from_slice(data);
170}
171
172#[inline]
173pub fn read_bytes<'a>(bytes: &'a [u8], pos: &mut usize) -> Result<&'a [u8], DecodeError> {
174    let len = read_varu32(bytes, pos)? as usize;
175    if *pos + len > bytes.len() {
176        return Err(DecodeError("unexpected eof (bytes)"));
177    }
178    let slice = &bytes[*pos..*pos + len];
179    *pos += len;
180    Ok(slice)
181}
182
183#[inline]
184pub fn write_string(buf: &mut Vec<u8>, value: &str) {
185    write_bytes(buf, value.as_bytes());
186}
187
188#[inline]
189pub fn read_string<'a>(bytes: &'a [u8], pos: &mut usize) -> Result<&'a str, DecodeError> {
190    let data = read_bytes(bytes, pos)?;
191    std::str::from_utf8(data).map_err(|_| DecodeError("invalid utf8"))
192}
193
194/// Write f64 as little-endian bytes
195#[inline]
196pub fn write_f64(buf: &mut Vec<u8>, value: f64) {
197    buf.extend_from_slice(&value.to_le_bytes());
198}
199
200/// Read f64 from little-endian bytes
201#[inline]
202pub fn read_f64(bytes: &[u8], pos: &mut usize) -> Result<f64, DecodeError> {
203    if *pos + 8 > bytes.len() {
204        return Err(DecodeError("unexpected eof (f64)"));
205    }
206    let mut arr = [0u8; 8];
207    arr.copy_from_slice(&bytes[*pos..*pos + 8]);
208    *pos += 8;
209    Ok(f64::from_le_bytes(arr))
210}
211
212/// Write f32 as little-endian bytes
213#[inline]
214pub fn write_f32(buf: &mut Vec<u8>, value: f32) {
215    buf.extend_from_slice(&value.to_le_bytes());
216}
217
218/// Read f32 from little-endian bytes
219#[inline]
220pub fn read_f32(bytes: &[u8], pos: &mut usize) -> Result<f32, DecodeError> {
221    if *pos + 4 > bytes.len() {
222        return Err(DecodeError("unexpected eof (f32)"));
223    }
224    let mut arr = [0u8; 4];
225    arr.copy_from_slice(&bytes[*pos..*pos + 4]);
226    *pos += 4;
227    Ok(f32::from_le_bytes(arr))
228}
229
230#[cfg(test)]
231mod tests {
232    use super::*;
233
234    // ==================== VarInt Tests ====================
235
236    #[test]
237    fn test_varu32_single_byte() {
238        let mut buf = Vec::new();
239        write_varu32(&mut buf, 0);
240        assert_eq!(buf, vec![0]);
241
242        buf.clear();
243        write_varu32(&mut buf, 1);
244        assert_eq!(buf, vec![1]);
245
246        buf.clear();
247        write_varu32(&mut buf, 127);
248        assert_eq!(buf, vec![127]);
249    }
250
251    #[test]
252    fn test_varu32_multi_byte() {
253        let mut buf = Vec::new();
254        write_varu32(&mut buf, 128);
255        assert_eq!(buf, vec![0x80, 0x01]);
256
257        buf.clear();
258        write_varu32(&mut buf, 300);
259        let mut pos = 0;
260        assert_eq!(read_varu32(&buf, &mut pos).unwrap(), 300);
261
262        buf.clear();
263        write_varu32(&mut buf, 16384);
264        pos = 0;
265        assert_eq!(read_varu32(&buf, &mut pos).unwrap(), 16384);
266    }
267
268    #[test]
269    fn test_varu32_max() {
270        let mut buf = Vec::new();
271        write_varu32(&mut buf, u32::MAX);
272        let mut pos = 0;
273        assert_eq!(read_varu32(&buf, &mut pos).unwrap(), u32::MAX);
274    }
275
276    #[test]
277    fn test_varu32_roundtrip() {
278        let values = [
279            0,
280            1,
281            127,
282            128,
283            255,
284            256,
285            16383,
286            16384,
287            2097151,
288            2097152,
289            u32::MAX,
290        ];
291        for &val in &values {
292            let mut buf = Vec::new();
293            write_varu32(&mut buf, val);
294            let mut pos = 0;
295            assert_eq!(
296                read_varu32(&buf, &mut pos).unwrap(),
297                val,
298                "Failed for {}",
299                val
300            );
301        }
302    }
303
304    #[test]
305    fn test_varu64_roundtrip() {
306        let values = [0u64, 1, 127, 128, 255, 16384, u32::MAX as u64, u64::MAX];
307        for &val in &values {
308            let mut buf = Vec::new();
309            write_varu64(&mut buf, val);
310            let mut pos = 0;
311            assert_eq!(
312                read_varu64(&buf, &mut pos).unwrap(),
313                val,
314                "Failed for {}",
315                val
316            );
317        }
318    }
319
320    #[test]
321    fn test_vari32_roundtrip() {
322        let values = [0i32, 1, -1, 127, -128, i32::MAX, i32::MIN];
323        for &val in &values {
324            let mut buf = Vec::new();
325            write_vari32(&mut buf, val);
326            let mut pos = 0;
327            assert_eq!(
328                read_vari32(&buf, &mut pos).unwrap(),
329                val,
330                "Failed for {}",
331                val
332            );
333        }
334    }
335
336    #[test]
337    fn test_vari64_roundtrip() {
338        let values = [0i64, 1, -1, 127, -128, i64::MAX, i64::MIN];
339        for &val in &values {
340            let mut buf = Vec::new();
341            write_vari64(&mut buf, val);
342            let mut pos = 0;
343            assert_eq!(
344                read_vari64(&buf, &mut pos).unwrap(),
345                val,
346                "Failed for {}",
347                val
348            );
349        }
350    }
351
352    #[test]
353    fn test_varu32_eof() {
354        let buf = vec![0x80]; // Continuation bit set but no next byte
355        let mut pos = 0;
356        assert!(read_varu32(&buf, &mut pos).is_err());
357    }
358
359    #[test]
360    fn test_varu32_overflow() {
361        // More than 5 bytes with continuation bits
362        let buf = vec![0x80, 0x80, 0x80, 0x80, 0x80, 0x01];
363        let mut pos = 0;
364        assert!(read_varu32(&buf, &mut pos).is_err());
365    }
366
367    // ==================== IP Address Tests ====================
368
369    #[test]
370    fn test_ip_key_ipv4() {
371        let addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
372        let key = IpKey::from(&addr);
373        assert_eq!(key.len, 4);
374        assert_eq!(key.bytes[..4], [192, 168, 1, 1]);
375        assert_eq!(key.to_ip(), addr);
376    }
377
378    #[test]
379    fn test_ip_key_ipv6() {
380        let addr = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
381        let key = IpKey::from(&addr);
382        assert_eq!(key.len, 16);
383        assert_eq!(key.to_ip(), addr);
384    }
385
386    #[test]
387    fn test_ip_key_ordering() {
388        let ip1 = IpKey::from(&IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)));
389        let ip2 = IpKey::from(&IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)));
390        let ip3 = IpKey::from(&IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)));
391
392        assert!(ip1 < ip2);
393        assert!(ip2 < ip3);
394    }
395
396    #[test]
397    fn test_write_read_ip_v4() {
398        let addr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
399        let mut buf = Vec::new();
400        write_ip(&mut buf, &addr);
401
402        assert_eq!(buf.len(), 5); // 1 tag + 4 octets
403        assert_eq!(buf[0], 0); // IPv4 tag
404
405        let mut pos = 0;
406        let decoded = read_ip(&buf, &mut pos).unwrap();
407        assert_eq!(decoded, addr);
408    }
409
410    #[test]
411    fn test_write_read_ip_v6() {
412        let addr = IpAddr::V6(Ipv6Addr::LOCALHOST);
413        let mut buf = Vec::new();
414        write_ip(&mut buf, &addr);
415
416        assert_eq!(buf.len(), 17); // 1 tag + 16 octets
417        assert_eq!(buf[0], 1); // IPv6 tag
418
419        let mut pos = 0;
420        let decoded = read_ip(&buf, &mut pos).unwrap();
421        assert_eq!(decoded, addr);
422    }
423
424    #[test]
425    fn test_read_ip_invalid_tag() {
426        let buf = vec![2, 0, 0, 0, 0]; // Invalid tag
427        let mut pos = 0;
428        assert!(read_ip(&buf, &mut pos).is_err());
429    }
430
431    #[test]
432    fn test_read_ip_truncated_v4() {
433        let buf = vec![0, 192, 168]; // Only 2 octets
434        let mut pos = 0;
435        assert!(read_ip(&buf, &mut pos).is_err());
436    }
437
438    #[test]
439    fn test_read_ip_truncated_v6() {
440        let buf = vec![1, 0, 0, 0, 0, 0, 0, 0, 0]; // Only 8 octets
441        let mut pos = 0;
442        assert!(read_ip(&buf, &mut pos).is_err());
443    }
444
445    // ==================== Bytes/String Tests ====================
446
447    #[test]
448    fn test_write_read_bytes_empty() {
449        let mut buf = Vec::new();
450        write_bytes(&mut buf, &[]);
451
452        let mut pos = 0;
453        let decoded = read_bytes(&buf, &mut pos).unwrap();
454        assert!(decoded.is_empty());
455    }
456
457    #[test]
458    fn test_write_read_bytes_small() {
459        let data = b"hello";
460        let mut buf = Vec::new();
461        write_bytes(&mut buf, data);
462
463        let mut pos = 0;
464        let decoded = read_bytes(&buf, &mut pos).unwrap();
465        assert_eq!(decoded, data);
466    }
467
468    #[test]
469    fn test_write_read_bytes_large() {
470        let data: Vec<u8> = (0..1000).map(|i| (i % 256) as u8).collect();
471        let mut buf = Vec::new();
472        write_bytes(&mut buf, &data);
473
474        let mut pos = 0;
475        let decoded = read_bytes(&buf, &mut pos).unwrap();
476        assert_eq!(decoded, &data[..]);
477    }
478
479    #[test]
480    fn test_write_read_string() {
481        let s = "Hello, World! 🌍";
482        let mut buf = Vec::new();
483        write_string(&mut buf, s);
484
485        let mut pos = 0;
486        let decoded = read_string(&buf, &mut pos).unwrap();
487        assert_eq!(decoded, s);
488    }
489
490    #[test]
491    fn test_read_string_invalid_utf8() {
492        let mut buf = Vec::new();
493        write_varu32(&mut buf, 3);
494        buf.extend_from_slice(&[0xFF, 0xFE, 0xFD]); // Invalid UTF-8
495
496        let mut pos = 0;
497        assert!(read_string(&buf, &mut pos).is_err());
498    }
499
500    #[test]
501    fn test_read_bytes_truncated() {
502        let mut buf = Vec::new();
503        write_varu32(&mut buf, 100); // Says 100 bytes follow
504        buf.extend_from_slice(&[1, 2, 3]); // Only 3 bytes
505
506        let mut pos = 0;
507        assert!(read_bytes(&buf, &mut pos).is_err());
508    }
509
510    // ==================== Multiple Values Tests ====================
511
512    #[test]
513    fn test_multiple_values_sequential() {
514        let mut buf = Vec::new();
515
516        // Write multiple values
517        write_varu32(&mut buf, 42);
518        write_ip(&mut buf, &IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)));
519        write_string(&mut buf, "test");
520        write_vari32(&mut buf, -100);
521
522        // Read them back
523        let mut pos = 0;
524        assert_eq!(read_varu32(&buf, &mut pos).unwrap(), 42);
525        assert_eq!(
526            read_ip(&buf, &mut pos).unwrap(),
527            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))
528        );
529        assert_eq!(read_string(&buf, &mut pos).unwrap(), "test");
530        assert_eq!(read_vari32(&buf, &mut pos).unwrap(), -100);
531        assert_eq!(pos, buf.len()); // Should have consumed everything
532    }
533
534    #[test]
535    fn test_decode_error_display() {
536        let err = DecodeError("test error");
537        assert_eq!(err.0, "test error");
538    }
539}