use binread::io::{Read, Seek, SeekFrom};
use super::seek_contiguous;
use crate::error::Result;
use crate::traits::NtfsReadSeek;
#[derive(Clone, Debug)]
pub struct NtfsResidentAttributeValue<'f> {
data: &'f [u8],
position: u64,
stream_position: u64,
}
impl<'f> NtfsResidentAttributeValue<'f> {
pub(crate) fn new(data: &'f [u8], position: u64) -> Self {
Self {
data,
position,
stream_position: 0,
}
}
pub fn data(&self) -> &'f [u8] {
self.data
}
pub fn data_position(&self) -> Option<u64> {
if self.stream_position < self.len() {
Some(self.position + self.stream_position)
} else {
None
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn len(&self) -> u64 {
self.data.len() as u64
}
fn remaining_len(&self) -> u64 {
self.len().saturating_sub(self.stream_position)
}
}
impl<'f> NtfsReadSeek for NtfsResidentAttributeValue<'f> {
fn read<T>(&mut self, _fs: &mut T, buf: &mut [u8]) -> Result<usize>
where
T: Read + Seek,
{
if self.remaining_len() == 0 {
return Ok(0);
}
let bytes_to_read = usize::min(buf.len(), self.remaining_len() as usize);
let work_slice = &mut buf[..bytes_to_read];
let start = self.stream_position as usize;
let end = start + bytes_to_read;
work_slice.copy_from_slice(&self.data[start..end]);
self.stream_position += bytes_to_read as u64;
Ok(bytes_to_read)
}
fn seek<T>(&mut self, _fs: &mut T, pos: SeekFrom) -> Result<u64>
where
T: Read + Seek,
{
let length = self.len();
seek_contiguous(&mut self.stream_position, length, pos)
}
fn stream_position(&self) -> u64 {
self.stream_position
}
}