From 17a9261449f32eeadaf9cacad0dffa904a8a253b Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Wed, 3 Apr 2024 12:06:09 -0400 Subject: [PATCH] APE: Leave retaining read-only items for the future --- src/ape/tag/mod.rs | 4 +-- src/ape/tag/write.rs | 59 ++++++++++++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/ape/tag/mod.rs b/src/ape/tag/mod.rs index da17038a7..ec2d76f24 100644 --- a/src/ape/tag/mod.rs +++ b/src/ape/tag/mod.rs @@ -498,9 +498,9 @@ where pub(crate) fn dump_to( &mut self, writer: &mut W, - _write_options: WriteOptions, + write_options: WriteOptions, ) -> Result<()> { - let temp = write::create_ape_tag(self)?; + let temp = write::create_ape_tag(self, std::iter::empty(), write_options)?; writer.write_all(&temp)?; Ok(()) diff --git a/src/ape/tag/write.rs b/src/ape/tag/write.rs index 7b25c7b21..ecbb474a8 100644 --- a/src/ape/tag/write.rs +++ b/src/ape/tag/write.rs @@ -17,8 +17,8 @@ use byteorder::{LittleEndian, WriteBytesExt}; #[allow(clippy::shadow_unrelated)] pub(crate) fn write_to<'a, I>( data: &mut File, - tag: &mut ApeTagRef<'a, I>, - _write_options: WriteOptions, + tag_ref: &mut ApeTagRef<'a, I>, + write_options: WriteOptions, ) -> Result<()> where I: Iterator>, @@ -45,15 +45,16 @@ where // If one is found, it'll be removed and rewritten at the bottom, where it should be let mut header_ape_tag = (false, (0, 0)); - // TODO: Respect read only let start = data.stream_position()?; match read::read_ape_tag(data, false)? { Some((mut existing_tag, header)) => { - // Only keep metadata around that's marked read only - existing_tag.items.retain(|i| i.read_only); + if write_options.respect_read_only { + // Only keep metadata around that's marked read only + existing_tag.items.retain(|i| i.read_only); - if !existing_tag.items.is_empty() { - read_only = Some(existing_tag) + if !existing_tag.items.is_empty() { + read_only = Some(existing_tag) + } } header_ape_tag = (true, (start, start + u64::from(header.size))) @@ -78,15 +79,22 @@ where // Also check this tag for any read only items let start = data.stream_position()? as usize + 32; if let Some((mut existing_tag, header)) = read::read_ape_tag(data, true)? { - let size = header.size; - - existing_tag.items.retain(|i| i.read_only); + if write_options.respect_read_only { + existing_tag.items.retain(|i| i.read_only); - if !existing_tag.items.is_empty() { - read_only = Some(existing_tag) + if !existing_tag.items.is_empty() { + read_only = match read_only { + Some(mut read_only) => { + read_only.items.extend(existing_tag.items); + Some(read_only) + }, + None => Some(existing_tag), + } + } } // Since the "start" was really at the end of the tag, this sanity check seems necessary + let size = header.size; if let Some(start) = start.checked_sub(size as usize) { ape_tag_location = Some(start..start + size as usize); } else { @@ -95,13 +103,15 @@ where } // Preserve any metadata marked as read only - let tag = if let Some(read_only) = read_only { - create_ape_tag(&mut ApeTagRef { - read_only: read_only.read_only, - items: read_only.items.iter().map(Into::into), - })? + let tag; + if let Some(read_only) = read_only { + tag = create_ape_tag( + tag_ref, + read_only.items.iter().map(Into::into), + write_options, + )?; } else { - create_ape_tag(tag)? + tag = create_ape_tag(tag_ref, std::iter::empty(), write_options)?; }; data.rewind()?; @@ -128,9 +138,14 @@ where Ok(()) } -pub(super) fn create_ape_tag<'a, I>(tag: &mut ApeTagRef<'a, I>) -> Result> +pub(super) fn create_ape_tag<'a, 'b, I, R>( + tag: &mut ApeTagRef<'a, I>, + mut read_only: R, + write_options: WriteOptions, +) -> Result> where I: Iterator>, + R: Iterator>, { let items = &mut tag.items; let mut peek = items.peekable(); @@ -140,6 +155,12 @@ where return Ok(Vec::::new()); } + if read_only.next().is_some() && write_options.respect_read_only { + // TODO: Implement retaining read only items + log::warn!("Retaining read only items is not supported yet"); + drop(read_only); + } + let mut tag_write = Cursor::new(Vec::::new()); let mut item_count = 0_u32;