Skip to content

Commit 6a24aea

Browse files
committed
cow for code segment data
1 parent 5949315 commit 6a24aea

File tree

2 files changed

+46
-26
lines changed

2 files changed

+46
-26
lines changed

espflash/src/chip/esp8266.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ fn encode_flash_size(size: FlashSize) -> Result<u8, FlashDetectError> {
111111
}
112112

113113
fn merge_rom_segments<'a>(
114-
mut segments: impl Iterator<Item = CodeSegment>,
114+
mut segments: impl Iterator<Item = CodeSegment<'a>>,
115115
) -> Option<RomSegment<'a>> {
116116
let first = segments.next()?;
117117
if let Some(second) = segments.next() {

espflash/src/elf.rs

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::cmp::Ordering;
44
use crate::chip::Chip;
55
use crate::flasher::FlashSize;
66
use std::fmt::{Debug, Formatter};
7+
use std::mem::take;
78
use xmas_elf::sections::{SectionData, ShType};
89
use xmas_elf::ElfFile;
910

@@ -55,7 +56,7 @@ impl<'a> FirmwareImage<'a> {
5556
self.elf.header.pt2.entry_point() as u32
5657
}
5758

58-
pub fn segments(&'a self) -> impl Iterator<Item = CodeSegment> + 'a {
59+
pub fn segments(&'a self) -> impl Iterator<Item = CodeSegment<'a>> + 'a {
5960
self.elf
6061
.section_iter()
6162
.filter(|header| {
@@ -74,56 +75,75 @@ impl<'a> FirmwareImage<'a> {
7475
})
7576
}
7677

77-
pub fn rom_segments(&'a self, chip: Chip) -> impl Iterator<Item = CodeSegment> + 'a {
78+
pub fn rom_segments(&'a self, chip: Chip) -> impl Iterator<Item = CodeSegment<'a>> + 'a {
7879
self.segments()
7980
.filter(move |segment| chip.addr_is_flash(segment.addr))
8081
}
8182

82-
pub fn ram_segments(&'a self, chip: Chip) -> impl Iterator<Item = CodeSegment> + 'a {
83+
pub fn ram_segments(&'a self, chip: Chip) -> impl Iterator<Item = CodeSegment<'a>> + 'a {
8384
self.segments()
8485
.filter(move |segment| !chip.addr_is_flash(segment.addr))
8586
}
8687
}
8788

8889
#[derive(Eq, Clone)]
8990
/// A segment of code from the source elf
90-
pub struct CodeSegment {
91+
pub struct CodeSegment<'a> {
9192
pub addr: u32,
92-
data: Vec<u8>,
93+
data: Cow<'a, [u8]>,
9394
}
9495

95-
impl CodeSegment {
96-
pub fn new(addr: u32, data: &[u8]) -> Self {
97-
let mut data = data.to_vec();
98-
96+
impl<'a> CodeSegment<'a> {
97+
pub fn new(addr: u32, data: &'a [u8]) -> Self {
9998
// pad to 4 byte
10099
let padding = (4 - data.len() % 4) % 4;
101-
data.extend_from_slice(&[0; 4][0..padding]);
102-
103-
CodeSegment { addr, data }
100+
if padding == 0 {
101+
CodeSegment {
102+
addr,
103+
data: Cow::Borrowed(data),
104+
}
105+
} else {
106+
let mut data = data.to_vec();
107+
data.extend_from_slice(&[0; 4][0..padding]);
108+
CodeSegment {
109+
addr,
110+
data: Cow::Owned(data),
111+
}
112+
}
104113
}
105114

106115
/// Split of the first `count` bytes into a new segment, adjusting the remaining segment as needed
107116
pub fn split_off(&mut self, count: usize) -> Self {
108117
if count < self.data.len() {
109-
let rest = self.data.split_off(count);
118+
let (head, tail) = match take(&mut self.data) {
119+
Cow::Borrowed(data) => {
120+
let (head, tail) = data.split_at(count);
121+
(Cow::Borrowed(head), Cow::Borrowed(tail))
122+
}
123+
Cow::Owned(mut data) => {
124+
let tail = data.split_off(count);
125+
(Cow::Owned(data), Cow::Owned(tail))
126+
}
127+
};
110128
let new = CodeSegment {
111129
addr: self.addr,
112-
data: self.data.split_off(0),
130+
data: head,
113131
};
114132
self.addr += count as u32;
115-
self.data = rest;
133+
self.data = tail;
116134
new
117135
} else {
118136
let new = self.clone();
119137
self.addr += self.size();
120-
self.data = Vec::new();
138+
self.data = Cow::Borrowed(&[]);
121139
new
122140
}
123141
}
124142

125-
pub fn add(&mut self, data: &[u8]) {
126-
self.data.extend_from_slice(data);
143+
pub fn add(&mut self, extend: &[u8]) {
144+
let mut data = take(&mut self.data).into_owned();
145+
data.extend_from_slice(extend);
146+
self.data = Cow::Owned(data);
127147
}
128148

129149
pub fn size(&self) -> u32 {
@@ -135,7 +155,7 @@ impl CodeSegment {
135155
}
136156
}
137157

138-
impl Debug for CodeSegment {
158+
impl Debug for CodeSegment<'_> {
139159
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
140160
f.debug_struct("CodeSegment")
141161
.field("addr", &self.addr)
@@ -144,19 +164,19 @@ impl Debug for CodeSegment {
144164
}
145165
}
146166

147-
impl PartialEq for CodeSegment {
167+
impl PartialEq for CodeSegment<'_> {
148168
fn eq(&self, other: &Self) -> bool {
149169
self.addr.eq(&other.addr)
150170
}
151171
}
152172

153-
impl PartialOrd for CodeSegment {
173+
impl PartialOrd for CodeSegment<'_> {
154174
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
155175
self.addr.partial_cmp(&other.addr)
156176
}
157177
}
158178

159-
impl Ord for CodeSegment {
179+
impl Ord for CodeSegment<'_> {
160180
fn cmp(&self, other: &Self) -> Ordering {
161181
self.addr.cmp(&other.addr)
162182
}
@@ -168,11 +188,11 @@ pub struct RomSegment<'a> {
168188
pub data: Cow<'a, [u8]>,
169189
}
170190

171-
impl From<CodeSegment> for RomSegment<'static> {
172-
fn from(segment: CodeSegment) -> Self {
191+
impl<'a> From<CodeSegment<'a>> for RomSegment<'a> {
192+
fn from(segment: CodeSegment<'a>) -> Self {
173193
RomSegment {
174194
addr: segment.addr,
175-
data: Cow::Owned(segment.data),
195+
data: segment.data,
176196
}
177197
}
178198
}

0 commit comments

Comments
 (0)