gemini_genai_rs/buffer/
convert.rs

1//! Zero-copy audio sample format conversion.
2//!
3//! Provides utilities for converting between i16 PCM sample slices and raw byte
4//! slices using [`bytemuck`] (zero-copy reinterpret casts), and for wrapping
5//! owned byte vectors as shared [`Bytes`] handles for zero-copy fan-out.
6
7use bytes::Bytes;
8
9/// Convert a slice of i16 PCM samples to raw bytes (zero-copy via bytemuck).
10pub fn i16_to_bytes(samples: &[i16]) -> &[u8] {
11    bytemuck::cast_slice(samples)
12}
13
14/// Convert raw bytes to i16 PCM samples (zero-copy via bytemuck).
15///
16/// Returns `None` if the byte slice length is not a multiple of 2.
17pub fn bytes_to_i16(data: &[u8]) -> Option<&[i16]> {
18    bytemuck::try_cast_slice(data).ok()
19}
20
21/// Wrap raw bytes as a shared `Bytes` handle for zero-copy fan-out.
22///
23/// `Bytes::clone()` is O(1) — it bumps an internal `Arc` refcount instead of
24/// copying the data. Use this when the same audio chunk must be broadcast to
25/// multiple subscribers.
26pub fn into_shared(data: Vec<u8>) -> Bytes {
27    Bytes::from(data)
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn test_i16_to_bytes_round_trip() {
36        let samples: Vec<i16> = vec![0, 1, -1, i16::MAX, i16::MIN, 12345];
37        let raw = i16_to_bytes(&samples);
38        assert_eq!(raw.len(), samples.len() * 2);
39
40        let back = bytes_to_i16(raw).expect("round-trip should succeed");
41        assert_eq!(back, &samples[..]);
42    }
43
44    #[test]
45    fn test_bytes_to_i16_invalid_length() {
46        // Odd-length byte slice cannot be reinterpreted as &[i16]
47        let odd = vec![1u8, 2, 3];
48        assert!(bytes_to_i16(&odd).is_none());
49    }
50
51    #[test]
52    fn test_shared_bytes_clone_is_cheap() {
53        let original = vec![42u8; 4096];
54        let ptr = original.as_ptr();
55        let shared = into_shared(original);
56
57        // Clone should share the same backing allocation
58        let cloned = shared.clone();
59        assert_eq!(shared.as_ptr(), cloned.as_ptr());
60        // The data pointer may differ from the original Vec (Bytes may reallocate
61        // during From<Vec<u8>>), but the two Bytes handles must share the same
62        // underlying memory.
63        let _ = ptr; // original vec was consumed
64        assert_eq!(&shared[..], &cloned[..]);
65        assert_eq!(shared.len(), 4096);
66    }
67}