1#[cfg(feature = "read")]
2use alloc::borrow::Cow;
3use core::fmt;
4
5use crate::common::Format;
6use crate::read::{Reader, ReaderOffset, ReaderOffsetId, Result};
7
8pub trait Relocate<T: ReaderOffset = usize> {
10 fn relocate_address(&self, offset: T, value: u64) -> Result<u64>;
12
13 fn relocate_offset(&self, offset: T, value: T) -> Result<T>;
15}
16
17#[derive(Clone)]
23pub struct RelocateReader<R: Reader, T: Relocate<R::Offset>> {
24 section: R,
25 reader: R,
26 relocate: T,
27}
28
29impl<R, T> RelocateReader<R, T>
30where
31 R: Reader,
32 T: Relocate<R::Offset>,
33{
34 pub fn new(section: R, relocate: T) -> Self {
36 let reader = section.clone();
37 Self {
38 section,
39 reader,
40 relocate,
41 }
42 }
43
44 pub fn inner(&self) -> &R {
46 &self.reader
47 }
48}
49
50impl<R, T> fmt::Debug for RelocateReader<R, T>
51where
52 R: Reader,
53 T: Relocate<R::Offset>,
54{
55 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
56 fmt.debug_tuple("RelocationReader")
57 .field(&self.reader)
58 .finish()
59 }
60}
61
62impl<R, T> Reader for RelocateReader<R, T>
63where
64 R: Reader,
65 T: Relocate<R::Offset> + fmt::Debug + Clone,
66{
67 type Endian = R::Endian;
68 type Offset = R::Offset;
69
70 fn read_address(&mut self, address_size: u8) -> Result<u64> {
71 let offset = self.reader.offset_from(&self.section);
72 let value = self.reader.read_address(address_size)?;
73 self.relocate.relocate_address(offset, value)
74 }
75
76 fn read_offset(&mut self, format: Format) -> Result<R::Offset> {
77 let offset = self.reader.offset_from(&self.section);
78 let value = self.reader.read_offset(format)?;
79 self.relocate.relocate_offset(offset, value)
80 }
81
82 fn read_sized_offset(&mut self, size: u8) -> Result<R::Offset> {
83 let offset = self.reader.offset_from(&self.section);
84 let value = self.reader.read_sized_offset(size)?;
85 self.relocate.relocate_offset(offset, value)
86 }
87
88 #[inline]
89 fn split(&mut self, len: Self::Offset) -> Result<Self> {
90 let mut other = self.clone();
91 other.reader.truncate(len)?;
92 self.reader.skip(len)?;
93 Ok(other)
94 }
95
96 #[inline]
99 fn endian(&self) -> Self::Endian {
100 self.reader.endian()
101 }
102
103 #[inline]
104 fn len(&self) -> Self::Offset {
105 self.reader.len()
106 }
107
108 #[inline]
109 fn empty(&mut self) {
110 self.reader.empty()
111 }
112
113 #[inline]
114 fn truncate(&mut self, len: Self::Offset) -> Result<()> {
115 self.reader.truncate(len)
116 }
117
118 #[inline]
119 fn offset_from(&self, base: &Self) -> Self::Offset {
120 self.reader.offset_from(&base.reader)
121 }
122
123 #[inline]
124 fn offset_id(&self) -> ReaderOffsetId {
125 self.reader.offset_id()
126 }
127
128 #[inline]
129 fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
130 self.reader.lookup_offset_id(id)
131 }
132
133 #[inline]
134 fn find(&self, byte: u8) -> Result<Self::Offset> {
135 self.reader.find(byte)
136 }
137
138 #[inline]
139 fn skip(&mut self, len: Self::Offset) -> Result<()> {
140 self.reader.skip(len)
141 }
142
143 #[cfg(not(feature = "read"))]
144 fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed {
145 super::reader::seal_if_no_alloc::Sealed
146 }
147
148 #[cfg(feature = "read")]
149 #[inline]
150 fn to_slice(&self) -> Result<Cow<'_, [u8]>> {
151 self.reader.to_slice()
152 }
153
154 #[cfg(feature = "read")]
155 #[inline]
156 fn to_string(&self) -> Result<Cow<'_, str>> {
157 self.reader.to_string()
158 }
159
160 #[cfg(feature = "read")]
161 #[inline]
162 fn to_string_lossy(&self) -> Result<Cow<'_, str>> {
163 self.reader.to_string_lossy()
164 }
165
166 #[inline]
167 fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
168 self.reader.read_slice(buf)
169 }
170}