elf/
string_table.rs
1use crate::parse::ParseError;
3use core::str::from_utf8;
4
5#[derive(Debug, Default, Clone, Copy)]
6pub struct StringTable<'data> {
7 data: &'data [u8],
8}
9
10impl<'data> StringTable<'data> {
11 pub fn new(data: &'data [u8]) -> Self {
12 StringTable { data }
13 }
14
15 pub fn get_raw(&self, offset: usize) -> Result<&'data [u8], ParseError> {
16 if self.data.is_empty() {
17 return Err(ParseError::BadOffset(offset as u64));
18 };
19
20 let start = self
21 .data
22 .get(offset..)
23 .ok_or(ParseError::BadOffset(offset as u64))?;
24 let end = start
25 .iter()
26 .position(|&b| b == 0u8)
27 .ok_or(ParseError::StringTableMissingNul(offset as u64))?;
28
29 Ok(start.split_at(end).0)
30 }
31
32 pub fn get(&self, offset: usize) -> Result<&'data str, ParseError> {
33 let raw_data = self.get_raw(offset)?;
34 Ok(from_utf8(raw_data)?)
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn test_empty_table_errors() {
44 let st = StringTable::default();
45 assert!(matches!(st.get(0), Err(ParseError::BadOffset(0))));
46 assert!(matches!(st.get(1), Err(ParseError::BadOffset(1))));
47 }
48
49 #[test]
53 fn test_get_index_0_gives_empty_string() {
54 let data = [0u8, 42u8, 0u8];
55 let st = StringTable::new(&data);
56 assert_eq!(st.get(0).unwrap(), "");
57 }
58
59 #[test]
60 fn test_get_raw_works() {
61 let data = [0u8, 0x45, 0x4C, 0x46, 0u8];
62 let st = StringTable::new(&data);
63 assert_eq!(st.get_raw(1).unwrap(), [0x45, 0x4c, 0x46]);
64 }
65
66 #[test]
67 fn test_get_string_works() {
68 let data = [0u8, 0x45, 0x4C, 0x46, 0u8];
69 let st = StringTable::new(&data);
70 assert_eq!(st.get(1).unwrap(), "ELF");
71 }
72
73 #[test]
74 fn test_get_raw_index_out_of_bounds_errors() {
75 let data = [0u8, 0x45, 0x4C, 0x46, 0u8];
76 let st = StringTable::new(&data);
77 let result = st.get_raw(7);
78 assert!(
79 matches!(result, Err(ParseError::BadOffset(7))),
80 "Unexpected Error type found: {result:?}"
81 );
82 }
83
84 #[test]
85 fn test_get_index_out_of_bounds_errors() {
86 let data = [0u8, 0x45, 0x4C, 0x46, 0u8];
87 let st = StringTable::new(&data);
88 let result = st.get(7);
89 assert!(
90 matches!(result, Err(ParseError::BadOffset(7))),
91 "Unexpected Error type found: {result:?}"
92 );
93 }
94
95 #[test]
96 fn test_get_raw_with_malformed_table_no_trailing_nul() {
97 let data = [0u8, 0x45, 0x4C, 0x46];
98 let st = StringTable::new(&data);
99 let result = st.get_raw(1);
100 assert!(
101 matches!(result, Err(ParseError::StringTableMissingNul(1))),
102 "Unexpected Error type found: {result:?}"
103 );
104 }
105
106 #[test]
107 fn test_get_with_malformed_table_no_trailing_nul() {
108 let data = [0u8, 0x45, 0x4C, 0x46];
109 let st = StringTable::new(&data);
110 let result = st.get(1);
111 assert!(
112 matches!(result, Err(ParseError::StringTableMissingNul(1))),
113 "Unexpected Error type found: {result:?}"
114 );
115 }
116}