feat(assets): implement AssetFile with seeking, buffering, and reading mechanics
This commit is contained in:
parent
436be80d30
commit
f07b5e7d6a
5 changed files with 90 additions and 0 deletions
52
crates/molotov-core/src/assets/asset.rs
Normal file
52
crates/molotov-core/src/assets/asset.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
use super::types::{SEEK_CUR, SEEK_END, SEEK_SET};
|
||||
use std::ffi::c_void;
|
||||
|
||||
pub struct AssetFile {
|
||||
data: Vec<u8>,
|
||||
cursor: usize,
|
||||
}
|
||||
|
||||
impl AssetFile {
|
||||
pub fn new(data: Vec<u8>) -> Self {
|
||||
Self { data, cursor: 0 }
|
||||
}
|
||||
|
||||
pub fn length(&self) -> i64 {
|
||||
self.data.len() as i64
|
||||
}
|
||||
|
||||
pub fn remaining_length(&self) -> i64 {
|
||||
self.data.len().saturating_sub(self.cursor) as i64
|
||||
}
|
||||
|
||||
pub fn get_buffer(&self) -> *const c_void {
|
||||
self.data.as_ptr() as *const c_void
|
||||
}
|
||||
|
||||
pub fn read(&mut self, buf: &mut [u8]) -> usize {
|
||||
let available = self.data.len().saturating_sub(self.cursor);
|
||||
let to_read = buf.len().min(available);
|
||||
if to_read > 0 {
|
||||
buf[..to_read].copy_from_slice(&self.data[self.cursor..self.cursor + to_read]);
|
||||
self.cursor += to_read;
|
||||
}
|
||||
to_read
|
||||
}
|
||||
|
||||
pub fn seek(&mut self, offset: i64, whence: i32) -> i64 {
|
||||
let new_pos: i64 = match whence {
|
||||
SEEK_SET => offset,
|
||||
SEEK_CUR => self.cursor as i64 + offset,
|
||||
SEEK_END => self.data.len() as i64 + offset,
|
||||
_ => return -1,
|
||||
};
|
||||
|
||||
if new_pos >= 0 && (new_pos as usize) <= self.data.len() {
|
||||
self.cursor = new_pos as usize;
|
||||
self.cursor as i64
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
3
crates/molotov-core/src/assets/mod.rs
Normal file
3
crates/molotov-core/src/assets/mod.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
pub mod asset;
|
||||
pub mod types;
|
||||
10
crates/molotov-core/src/assets/types.rs
Normal file
10
crates/molotov-core/src/assets/types.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pub const AASSET_MODE_UNKNOWN: i32 = 0;
|
||||
pub const AASSET_MODE_RANDOM: i32 = 1;
|
||||
pub const AASSET_MODE_STREAMING: i32 = 2;
|
||||
pub const AASSET_MODE_BUFFER: i32 = 3;
|
||||
|
||||
pub const SEEK_SET: i32 = 0;
|
||||
pub const SEEK_CUR: i32 = 1;
|
||||
pub const SEEK_END: i32 = 2;
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
pub mod assets;
|
||||
pub mod audio;
|
||||
pub mod dynamic;
|
||||
pub mod elf;
|
||||
|
|
|
|||
24
crates/molotov-core/tests/asset_read_test.rs
Normal file
24
crates/molotov-core/tests/asset_read_test.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
use molotov_core::assets::asset::AssetFile;
|
||||
|
||||
#[test]
|
||||
fn test_asset_read_and_seek_flow() {
|
||||
let data = b"ROBLOX_ASSET_CONTENT_12345".to_vec();
|
||||
let mut asset = AssetFile::new(data);
|
||||
|
||||
assert_eq!(asset.length(), 26);
|
||||
assert_eq!(asset.remaining_length(), 26);
|
||||
|
||||
let mut buf = [0u8; 6];
|
||||
assert_eq!(asset.read(&mut buf), 6);
|
||||
assert_eq!(&buf, b"ROBLOX");
|
||||
assert_eq!(asset.remaining_length(), 20);
|
||||
|
||||
// Seek to offset 7 (SEEK_SET = 0)
|
||||
assert_eq!(asset.seek(7, 0), 7);
|
||||
assert_eq!(asset.remaining_length(), 19);
|
||||
|
||||
let mut next_buf = [0u8; 5];
|
||||
assert_eq!(asset.read(&mut next_buf), 5);
|
||||
assert_eq!(&next_buf, b"ASSET");
|
||||
}
|
||||
Reference in a new issue