1use nom::number::complete::{le_u32, le_u64};
2
3use crate::{helpers::string_upto_null_terminator, macho::MachOResult};
4
5use super::{pad_to_size, LCLoadCommand, LoadCommandBase, LoadCommandParser};
6
7#[derive(Debug, PartialEq, Eq)]
8pub struct NoteCommand {
9 pub cmd: LCLoadCommand,
10 pub cmdsize: u32,
11 pub data_owner: String,
12 pub offset: u64,
13 pub size: u64,
14}
15
16impl LoadCommandParser for NoteCommand {
17 fn parse(ldcmd: &[u8]) -> MachOResult<Self> {
18 let (cursor, base) = LoadCommandBase::parse(ldcmd)?;
19 let (cursor, data_owner_offset) = le_u32(cursor)?;
20 let (cursor, offset) = le_u64(cursor)?;
21 let (_, size) = le_u64(cursor)?;
22
23 let (_, data_owner) =
24 string_upto_null_terminator(&ldcmd[data_owner_offset as usize..])?;
25
26 Ok(
27 NoteCommand {
28 cmd: base.cmd,
29 cmdsize: base.cmdsize,
30 data_owner,
31 offset,
32 size,
33 },
34 )
35 }
36
37 fn serialize(&self) -> Vec<u8> {
38 let mut buf = Vec::new();
39 buf.extend(self.cmd.serialize());
40 buf.extend(self.cmdsize.to_le_bytes());
41 buf.extend((0x1C as u32).to_le_bytes()); buf.extend(self.offset.to_le_bytes());
43 buf.extend(self.size.to_le_bytes());
44 buf.extend(self.data_owner.as_bytes());
45 buf.push(0);
46 pad_to_size(&mut buf, self.cmdsize as usize);
47 buf
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use crate::command::LCLoadCommand;
55
56 #[test]
57 fn test_note_serialise() {
58 let cmd = NoteCommand {
59 cmd: LCLoadCommand::LcNote,
60 cmdsize: 47,
61 data_owner: "com.apple.dt.Xcode".to_string(),
62 offset: 0,
63 size: 0,
64 };
65
66 let serialized = cmd.serialize();
67 let deserialized = NoteCommand::parse(&serialized).unwrap();
68 assert_eq!(cmd, deserialized);
69 }
70}