mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2025-03-04 23:07:20 +00:00
Reimplement read only for APEv2
This commit is contained in:
parent
fcc63ce0b4
commit
0bd0929716
2 changed files with 36 additions and 31 deletions
|
@ -1,5 +1,5 @@
|
|||
use super::constants::INVALID_KEYS;
|
||||
use crate::{ItemKey, ItemValue, LoftyError, Result, Tag, TagItem, TagType};
|
||||
use crate::{ItemKey, ItemValue, LoftyError, Result, Tag, TagItem, TagType, TagItemFlags};
|
||||
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::ops::Neg;
|
||||
|
@ -62,8 +62,11 @@ where
|
|||
return Err(LoftyError::Ape("Tag item contains a non ASCII key"));
|
||||
}
|
||||
|
||||
// TODO: reimplement read only
|
||||
// let read_only = (flags & 1) == 1;
|
||||
let item_flags = TagItemFlags {
|
||||
read_only: (flags & 1) == 1,
|
||||
.. TagItemFlags::default()
|
||||
};
|
||||
|
||||
let item_type = (flags & 6) >> 1;
|
||||
|
||||
let mut value = vec![0; value_size as usize];
|
||||
|
@ -80,11 +83,12 @@ where
|
|||
_ => return Err(LoftyError::Ape("Tag item contains an invalid item type")),
|
||||
};
|
||||
|
||||
let item = TagItem::new(
|
||||
let mut item = TagItem::new(
|
||||
ItemKey::from_key(&TagType::Ape, &*key).unwrap(),
|
||||
parsed_value,
|
||||
);
|
||||
|
||||
item.set_flags(item_flags);
|
||||
tag.insert_item(item);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,11 +28,14 @@ pub(crate) fn write_to(data: &mut File, tag: &Tag) -> Result<()> {
|
|||
let start = data.seek(SeekFrom::Current(-8))?;
|
||||
|
||||
data.seek(SeekFrom::Current(8))?;
|
||||
let (mut tag, size) = read_ape_tag(data, false)?;
|
||||
let (mut existing, size) = read_ape_tag(data, false)?;
|
||||
|
||||
// Only keep metadata around that's marked read only
|
||||
// TODO
|
||||
read_only = retain_read_only(&mut tag);
|
||||
existing.retain(|i| i.flags().read_only);
|
||||
|
||||
if existing.item_count() > 0 {
|
||||
read_only = Some(existing)
|
||||
}
|
||||
|
||||
header_ape_tag = (true, (start, start + u64::from(size)))
|
||||
} else {
|
||||
|
@ -57,9 +60,13 @@ pub(crate) fn write_to(data: &mut File, tag: &Tag) -> Result<()> {
|
|||
if &ape_preamble == APE_PREAMBLE {
|
||||
let start = data.seek(SeekFrom::Current(0))? as usize + 24;
|
||||
|
||||
let (mut tag, size) = read_ape_tag(data, true)?;
|
||||
let (mut existing, size) = read_ape_tag(data, true)?;
|
||||
|
||||
read_only = retain_read_only(&mut tag);
|
||||
existing.retain(|i| i.flags().read_only);
|
||||
|
||||
if existing.item_count() > 0 {
|
||||
read_only = Some(existing)
|
||||
}
|
||||
|
||||
// Since the "start" was really at the end of the tag, this sanity check seems necessary
|
||||
if let Some(start) = start.checked_sub(size as usize) {
|
||||
|
@ -69,19 +76,18 @@ pub(crate) fn write_to(data: &mut File, tag: &Tag) -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// Preserve any metadata marked as read only
|
||||
// If there is any read only metadata, we will have to clone the HashMap
|
||||
// If there is any read only metadata, we will have to clone the Tag
|
||||
let tag = if let Some(read_only) = read_only {
|
||||
create_ape_tag(tag)?
|
||||
} else {
|
||||
let mut metadata = tag.clone();
|
||||
|
||||
for (k, v) in read_only {
|
||||
metadata.insert(k, v);
|
||||
for i in read_only.items().to_vec() {
|
||||
metadata.insert_item(i);
|
||||
}
|
||||
|
||||
create_ape_tag(&metadata)?
|
||||
} else {
|
||||
create_ape_tag(tag)?
|
||||
};
|
||||
|
||||
data.seek(SeekFrom::Start(0))?;
|
||||
|
@ -117,15 +123,14 @@ fn create_ape_tag(metadata: &Tag) -> Result<Vec<u8>> {
|
|||
|
||||
let item_count = metadata.item_count() as u32;
|
||||
|
||||
for item in metadata.iter() {
|
||||
for item in metadata.items() {
|
||||
let (size, flags, value) = match item.value() {
|
||||
ItemValue::Binary(value) => {
|
||||
let mut flags = 1_u32 << 1;
|
||||
|
||||
// TODO
|
||||
// if *ro {
|
||||
// flags |= 1_u32
|
||||
// }
|
||||
if item.flags().read_only {
|
||||
flags |= 1_u32
|
||||
}
|
||||
|
||||
(value.len() as u32, flags, value.as_slice())
|
||||
},
|
||||
|
@ -134,21 +139,22 @@ fn create_ape_tag(metadata: &Tag) -> Result<Vec<u8>> {
|
|||
|
||||
let mut flags = 0_u32;
|
||||
|
||||
// if *ro {
|
||||
// flags |= 1_u32
|
||||
// }
|
||||
if item.flags().read_only {
|
||||
flags |= 1_u32
|
||||
}
|
||||
|
||||
(value.len() as u32, flags, value)
|
||||
},
|
||||
ItemValue::Locator(value) => {
|
||||
let mut flags = 2_u32 << 1;
|
||||
|
||||
// if *ro {
|
||||
// flags |= 1_u32
|
||||
// }
|
||||
if item.flags().read_only {
|
||||
flags |= 1_u32
|
||||
}
|
||||
|
||||
(value.len() as u32, flags, value.as_bytes())
|
||||
},
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
tag.write_u32::<LittleEndian>(size)?;
|
||||
|
@ -200,8 +206,3 @@ fn create_ape_tag(metadata: &Tag) -> Result<Vec<u8>> {
|
|||
Ok(tag)
|
||||
}
|
||||
}
|
||||
|
||||
fn retain_read_only(tag: &mut Tag) {
|
||||
// TODO
|
||||
if tag.item_count() != 0 {}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue