<commit_before>//! A byte-offset based string table.
//! Commonly used in ELF binaries, Unix archives, and even PE binaries.

use core::ops::Index;
use core::slice;
use core::str;
use core::fmt;
use scroll::{self, ctx, Pread};
#[cfg(feature = "std")]
use error;

/// A common string table format which is indexed by byte offsets (and not
/// member index). Constructed using [`parse`](#method.parse)
/// with your choice of delimiter. Please be careful.
pub struct Strtab<'a> {
    bytes: &'a[u8],
    delim: ctx::StrCtx,
}

#[inline(always)]
fn get_str(offset: usize, bytes: &[u8], delim: ctx::StrCtx) -> scroll::Result<&str> {
    bytes.pread_with::<&str>(offset, delim)
}

impl<'a> Strtab<'a> {
    /// Construct a new strtab with `bytes` as the backing string table, using `delim` as the delimiter between entries
    pub fn new (bytes: &'a [u8], delim: u8) -> Self {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: bytes }
    }
    /// Construct a strtab from a `ptr`, and a `size`, using `delim` as the delimiter
    pub unsafe fn from_raw(ptr: *const u8, size: usize, delim: u8) -> Strtab<'a> {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: slice::from_raw_parts(ptr, size) }
    }
    #[cfg(feature = "std")]
    /// Parses a strtab from `bytes` at `offset` with `len` size as the backing string table, using `delim` as the delimiter
    pub fn parse(bytes: &'a [u8], offset: usize, len: usize, delim: u8) -> error::Result<Strtab<'a>> {
        if offset + len >= bytes.len () {
            return Err(error::Error::Malformed(format!("Strtable size ({}) + offset ({}) is out of bounds", len, offset)));
        }
        Ok(Strtab { bytes: &bytes[offset..offset+len], delim: ctx::StrCtx::Delimiter(delim) })
    }
    #[cfg(feature = "std")]
    /// Converts the string table to a vector, with the original `delim` used to separate the strings
    pub fn to_vec(self) -> error::Result<Vec<String>> {
        let len = self.bytes.len();<commit_msg>Check overflow in strtab (#34)<commit_after>//! A byte-offset based string table.
//! Commonly used in ELF binaries, Unix archives, and even PE binaries.

use core::ops::Index;
use core::slice;
use core::str;
use core::fmt;
use scroll::{self, ctx, Pread};
#[cfg(feature = "std")]
use error;

/// A common string table format which is indexed by byte offsets (and not
/// member index). Constructed using [`parse`](#method.parse)
/// with your choice of delimiter. Please be careful.
pub struct Strtab<'a> {
    bytes: &'a[u8],
    delim: ctx::StrCtx,
}

#[inline(always)]
fn get_str(offset: usize, bytes: &[u8], delim: ctx::StrCtx) -> scroll::Result<&str> {
    bytes.pread_with::<&str>(offset, delim)
}

impl<'a> Strtab<'a> {
    /// Construct a new strtab with `bytes` as the backing string table, using `delim` as the delimiter between entries
    pub fn new (bytes: &'a [u8], delim: u8) -> Self {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: bytes }
    }
    /// Construct a strtab from a `ptr`, and a `size`, using `delim` as the delimiter
    pub unsafe fn from_raw(ptr: *const u8, size: usize, delim: u8) -> Strtab<'a> {
        Strtab { delim: ctx::StrCtx::Delimiter(delim), bytes: slice::from_raw_parts(ptr, size) }
    }
    #[cfg(feature = "std")]
    /// Parses a strtab from `bytes` at `offset` with `len` size as the backing string table, using `delim` as the delimiter
    pub fn parse(bytes: &'a [u8], offset: usize, len: usize, delim: u8) -> error::Result<Strtab<'a>> {
        let (end, overflow) = offset.overflowing_add(len);
        if overflow || end >= bytes.len () {
            return Err(error::Error::Malformed(format!("Strtable size ({}) + offset ({}) is out of bounds", len, offset)));
        }
        Ok(Strtab { bytes: &bytes[offset..end], delim: ctx::StrCtx::Delimiter(delim) })
    }
    #[cfg(feature = "std")]
    /// Converts the string table to a vector, with the original `delim` used to separate the strings
    pub fn to_vec(self) -> error::Result<Vec<String>> {
        let len = self.bytes.len();
{'fraction_non_alphanumeric': 0.1629574678536103, 'fraction_numerical': 0.004451038575667656, 'mean_word_length': 3.5706214689265536, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7339853', 'n_tokens_mistral': 1332, 'n_tokens_neox': 1342, 'n_words': 447}