1use alloc::borrow::Cow;
2
3use crate::AsmError;
4
5use super::buffer::{CodeBuffer, CodeBufferFinalized};
6use super::target::Environment;
7
8pub struct Section {
16 name: Cow<'static, str>,
17 align: u32,
18 buffer: CodeBuffer,
19}
20
21impl Section {
22 pub fn new(name: impl Into<Cow<'static, str>>, align: u32) -> Result<Self, AsmError> {
27 Self::with_env(name, align, Environment::host())
28 }
29
30 pub fn with_env(
32 name: impl Into<Cow<'static, str>>,
33 align: u32,
34 environment: Environment,
35 ) -> Result<Self, AsmError> {
36 if !align.is_power_of_two() {
37 return Err(AsmError::InvalidArgument);
38 }
39 Ok(Self {
40 name: name.into(),
41 align,
42 buffer: CodeBuffer::new(environment),
43 })
44 }
45
46 pub fn name(&self) -> &str {
47 &self.name
48 }
49
50 pub fn align(&self) -> u32 {
51 self.align
52 }
53
54 pub fn buffer(&self) -> &CodeBuffer {
55 &self.buffer
56 }
57
58 pub fn buffer_mut(&mut self) -> &mut CodeBuffer {
59 &mut self.buffer
60 }
61
62 pub fn finish(mut self) -> Result<FinalizedSection, AsmError> {
64 Ok(FinalizedSection {
65 name: self.name,
66 align: self.align,
67 code: self.buffer.finish()?,
68 })
69 }
70}
71
72pub struct FinalizedSection {
74 pub(crate) name: Cow<'static, str>,
75 pub(crate) align: u32,
76 pub(crate) code: CodeBufferFinalized,
77}
78
79impl FinalizedSection {
80 pub fn name(&self) -> &str {
81 &self.name
82 }
83
84 pub fn align(&self) -> u32 {
85 self.align
86 }
87
88 pub fn code(&self) -> &CodeBufferFinalized {
89 &self.code
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use crate::core::arch_traits::Arch;
97
98 #[test]
99 fn section_holds_named_buffer_with_alignment() {
100 let mut section = Section::new(".rodata", 16).unwrap();
101 assert_eq!(section.name(), ".rodata");
102 assert_eq!(section.align(), 16);
103
104 section.buffer_mut().write_u64(0x1122_3344_5566_7788);
105
106 let finalized = section.finish().unwrap();
107 assert_eq!(finalized.name(), ".rodata");
108 assert_eq!(finalized.align(), 16);
109 assert_eq!(
110 finalized.code().data(),
111 &0x1122_3344_5566_7788u64.to_ne_bytes()
112 );
113 }
114
115 #[test]
116 fn section_alignment_must_be_power_of_two() {
117 assert_eq!(
118 Section::new(".text", 3).err(),
119 Some(AsmError::InvalidArgument)
120 );
121 }
122
123 #[test]
124 fn section_preserves_explicit_target() {
125 let section = Section::with_env(".text", 4, Environment::new(Arch::AArch64)).unwrap();
126
127 assert_eq!(section.buffer().env().arch(), Arch::AArch64);
128 }
129}