From 5ab4c082936ebc6163e7a5995840244964fe596d Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Sat, 7 Aug 2021 10:19:49 +0200 Subject: Use `ArrayVec` over heap-allocated `Vec` for some structured values. This greatly reduces the number of heap allocations when traversing an index. --- Cargo.toml | 3 ++- src/structured_values/file_name.rs | 12 ++++++++---- src/structured_values/volume_name.rs | 8 +++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90cfc1a..047e301 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +arrayvec = { version = "0.7.1", default-features = false } binread = { version = "2.1.1", features = ["const_generics"], default-features = false } byteorder = { version = "1.4.3", default-features = false } bitflags = "1.2.1" @@ -17,4 +18,4 @@ memoffset = "0.6.4" [features] default = ["std"] -std = ["binread/std", "byteorder/std"] +std = ["arrayvec/std", "binread/std", "byteorder/std"] diff --git a/src/structured_values/file_name.rs b/src/structured_values/file_name.rs index 0fdac97..24dbbde 100644 --- a/src/structured_values/file_name.rs +++ b/src/structured_values/file_name.rs @@ -10,7 +10,7 @@ use crate::structured_values::{ NtfsFileAttributeFlags, NtfsStructuredValue, NtfsStructuredValueFromSlice, }; use crate::time::NtfsTime; -use alloc::vec::Vec; +use arrayvec::ArrayVec; use binread::io::Cursor; use binread::{BinRead, BinReaderExt}; use core::mem; @@ -22,6 +22,10 @@ const FILE_NAME_HEADER_SIZE: usize = 66; /// The smallest FileName attribute has a name containing just a single character. const FILE_NAME_MIN_SIZE: usize = FILE_NAME_HEADER_SIZE + mem::size_of::(); +/// The "name" stored in the FileName attribute has an `u8` length field specifying the number of UTF-16 code points. +/// Hence, the name occupies up to 510 bytes. +const NAME_MAX_SIZE: usize = (u8::MAX as usize) * mem::size_of::(); + #[allow(unused)] #[derive(BinRead, Clone, Debug)] struct FileNameHeader { @@ -50,7 +54,7 @@ pub enum NtfsFileNamespace { #[derive(Clone, Debug)] pub struct NtfsFileName { header: FileNameHeader, - name: Vec, + name: ArrayVec, } impl NtfsFileName { @@ -104,7 +108,7 @@ impl NtfsFileName { debug_assert!(self.name.is_empty()); let start = FILE_NAME_HEADER_SIZE; let end = start + self.name_length(); - self.name.extend_from_slice(&data[start..end]); + self.name.try_extend_from_slice(&data[start..end]).unwrap(); } fn validate_name_length(&self, data_size: usize, position: u64) -> Result<()> { @@ -154,7 +158,7 @@ impl<'s> NtfsStructuredValueFromSlice<'s> for NtfsFileName { let mut file_name = Self { header, - name: Vec::new(), + name: ArrayVec::new(), }; file_name.validate_name_length(slice.len(), position)?; file_name.validate_namespace(position)?; diff --git a/src/structured_values/volume_name.rs b/src/structured_values/volume_name.rs index 77b2c8e..91ca1a2 100644 --- a/src/structured_values/volume_name.rs +++ b/src/structured_values/volume_name.rs @@ -5,7 +5,7 @@ use crate::attribute::NtfsAttributeType; use crate::error::{NtfsError, Result}; use crate::string::NtfsString; use crate::structured_values::{NtfsStructuredValue, NtfsStructuredValueFromSlice}; -use alloc::vec::Vec; +use arrayvec::ArrayVec; use core::mem; /// The smallest VolumeName attribute has a name containing just a single character. @@ -16,7 +16,7 @@ const VOLUME_NAME_MAX_SIZE: usize = 128 * mem::size_of::(); #[derive(Clone, Debug)] pub struct NtfsVolumeName { - name: Vec, + name: ArrayVec, } impl NtfsVolumeName { @@ -55,7 +55,9 @@ impl<'s> NtfsStructuredValueFromSlice<'s> for NtfsVolumeName { }); } - let name = slice.to_vec(); + let mut name = ArrayVec::new(); + name.try_extend_from_slice(slice).unwrap(); + Ok(Self { name }) } } -- cgit v1.2.3