File
Blob: archive/fft-benchmark/firmware/crates/esp32-radio/src/platform/music.rs
| 1 | //! C allocates/frees PSRAM; Rust only borrows its immutable initialized contents. |
| 2 | use super::ffi; |
| 3 | use crate::error::{Error, Result}; |
| 4 | use std::{ptr::NonNull, slice}; |
| 5 | |
| 6 | #[derive(Debug)] |
| 7 | pub(crate) struct MusicBytes { |
| 8 | pointer: NonNull<u8>, |
| 9 | length: usize, |
| 10 | } |
| 11 | |
| 12 | impl MusicBytes { |
| 13 | pub(crate) fn load() -> Result<Self> { |
| 14 | let mut length = 0; |
| 15 | // SAFETY: length is writable for the call. On success C transfers a |
| 16 | // fresh, fully initialized PSRAM allocation with no remaining aliases. |
| 17 | let pointer = NonNull::new(unsafe { ffi::radio_music_load(&mut length) }) |
| 18 | .ok_or(Error::new("music partition could not be loaded"))?; |
| 19 | let bytes = Self { pointer, length }; |
| 20 | if length != 4 * 1024 * 1024 { |
| 21 | return Err(Error::new("unexpected music partition size")); |
| 22 | } |
| 23 | Ok(bytes) |
| 24 | } |
| 25 | pub(crate) fn as_slice(&self) -> &[u8] { |
| 26 | // SAFETY: C returned exactly length initialized bytes in one allocation, |
| 27 | // bounded to 4 MiB (< isize::MAX). No C aliases remain. The returned |
| 28 | // lifetime is tied to self, so Drop cannot free live Rust borrows. |
| 29 | unsafe { slice::from_raw_parts(self.pointer.as_ptr(), self.length) } |
| 30 | } |
| 31 | } |
| 32 | impl Drop for MusicBytes { |
| 33 | fn drop(&mut self) { |
| 34 | // SAFETY: sole allocation owner; borrows have ended; free on C's allocator. |
| 35 | unsafe { ffi::radio_music_free(self.pointer.as_ptr()) }; |
| 36 | } |
| 37 | } |