mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-13 14:12:31 +00:00
OggTag cleanup
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
parent
09c248c6c9
commit
f46cd1b301
1 changed files with 76 additions and 110 deletions
|
@ -39,31 +39,6 @@ impl Default for OggInnerTag {
|
|||
}
|
||||
|
||||
impl OggInnerTag {
|
||||
fn get_value(&self, key: &str) -> Option<&str> {
|
||||
self.comments.get_key_value(key).and_then(|pair| {
|
||||
if pair.1.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(pair.1.as_str())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn set_value<V>(&mut self, key: &str, val: V)
|
||||
where
|
||||
V: Into<String>,
|
||||
{
|
||||
let mut comments = self.comments.clone();
|
||||
let _ = comments.insert(key.to_string(), val.into());
|
||||
self.comments = comments;
|
||||
}
|
||||
|
||||
fn remove_key(&mut self, key: &str) {
|
||||
let mut comments = self.comments.clone();
|
||||
comments.retain(|k, _| k != key);
|
||||
self.comments = comments;
|
||||
}
|
||||
|
||||
fn read_from<R>(reader: &mut R, format: &OggFormat) -> Result<Self>
|
||||
where
|
||||
R: Read + Seek,
|
||||
|
@ -97,6 +72,21 @@ impl OggInnerTag {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn get_value(&self, key: &str) -> Option<&str> {
|
||||
self.comments.get_key_value(key).map(|(_, v)| v.as_str())
|
||||
}
|
||||
|
||||
fn set_value<V>(&mut self, key: &str, val: V)
|
||||
where
|
||||
V: Into<String>,
|
||||
{
|
||||
self.comments.insert(key.to_string(), val.into());
|
||||
}
|
||||
|
||||
fn remove_key(&mut self, key: &str) {
|
||||
self.comments.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
|
@ -119,17 +109,14 @@ impl TryFrom<OGGTags> for OggTag {
|
|||
fn try_from(inp: OGGTags) -> Result<Self> {
|
||||
let mut tag = Self::default();
|
||||
|
||||
let vendor = inp.0;
|
||||
let pictures = inp.1;
|
||||
let comments = inp.2;
|
||||
|
||||
tag.inner = OggInnerTag {
|
||||
vendor: inp.0,
|
||||
comments: comments.into_iter().collect(),
|
||||
pictures: if pictures.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Cow::from(pictures))
|
||||
},
|
||||
vendor,
|
||||
comments,
|
||||
pictures: (!pictures.is_empty()).then(|| Cow::from(pictures)),
|
||||
};
|
||||
|
||||
Ok(tag)
|
||||
|
@ -144,32 +131,28 @@ impl TryFrom<metaflac::Tag> for OggTag {
|
|||
let mut tag = Self::default();
|
||||
|
||||
if let Some(comments) = inp.vorbis_comments() {
|
||||
let comments = comments.clone();
|
||||
let mut user_comments = comments.comments;
|
||||
let mut user_comments = comments.comments.clone();
|
||||
|
||||
let mut pictures = Vec::new();
|
||||
|
||||
if let Some(data) = user_comments.remove("METADATA_BLOCK_PICTURE") {
|
||||
for item in data {
|
||||
if let Ok(pic) = Picture::from_apic_bytes(&item.as_bytes()) {
|
||||
if let Some(pics) = user_comments.remove("METADATA_BLOCK_PICTURE") {
|
||||
pics.iter().for_each(|item| {
|
||||
if let Ok(pic) = Picture::from_apic_bytes(item.as_bytes()) {
|
||||
pictures.push(pic)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let mut comment_collection = Vec::new();
|
||||
let mut comment_collection: HashMap<String, String> = HashMap::new();
|
||||
|
||||
for (k, v) in user_comments.clone() {
|
||||
for e in v {
|
||||
comment_collection.push((k.clone(), e.clone()))
|
||||
comment_collection.insert(k.clone(), e.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let comment_collection: HashMap<String, String> =
|
||||
comment_collection.into_iter().collect();
|
||||
|
||||
tag.inner = OggInnerTag {
|
||||
vendor: comments.vendor_string,
|
||||
vendor: comments.vendor_string.clone(),
|
||||
comments: comment_collection,
|
||||
pictures: Some(Cow::from(pictures)),
|
||||
};
|
||||
|
@ -234,25 +217,23 @@ impl AudioTagEdit for OggTag {
|
|||
}
|
||||
|
||||
fn year(&self) -> Option<i32> {
|
||||
if let Some(Ok(y)) = self
|
||||
if let Some(Ok(y)) = self.inner.get_value("YEAR").map(str::parse::<i32>) {
|
||||
return Some(y);
|
||||
} else if let Some(Ok(y)) = self
|
||||
.inner
|
||||
.get_value("DATE")
|
||||
.map(|s| s.chars().take(4).collect::<String>().parse::<i32>())
|
||||
.map(|d| (&d[..4]).parse::<i32>())
|
||||
{
|
||||
Some(y)
|
||||
} else if let Some(Ok(y)) = self.inner.get_value("YEAR").map(str::parse::<i32>) {
|
||||
Some(y)
|
||||
} else {
|
||||
None
|
||||
return Some(y);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
fn set_year(&mut self, year: i32) {
|
||||
self.inner.set_value("DATE", &year.to_string());
|
||||
self.inner.set_value("YEAR", &year.to_string());
|
||||
}
|
||||
fn remove_year(&mut self) {
|
||||
self.inner.remove_key("YEAR");
|
||||
self.inner.remove_key("DATE");
|
||||
}
|
||||
|
||||
fn album_title(&self) -> Option<&str> {
|
||||
|
@ -278,40 +259,66 @@ impl AudioTagEdit for OggTag {
|
|||
}
|
||||
|
||||
fn front_cover(&self) -> Option<Picture> {
|
||||
get_cover(PictureType::CoverFront, &self.inner.pictures)
|
||||
if let Some(p) = &self.inner.pictures {
|
||||
return p
|
||||
.iter()
|
||||
.find(|c| c.pic_type == PictureType::CoverFront)
|
||||
.cloned();
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(clippy::collapsible_if)]
|
||||
fn set_front_cover(&mut self, cover: Picture) {
|
||||
if let Some(pic) = create_cover(&cover) {
|
||||
self.remove_front_cover();
|
||||
self.inner.pictures = Some(replace_pic(pic, &self.inner.pictures))
|
||||
if PictureType::CoverFront == cover.pic_type {
|
||||
if let Ok(pic) = Picture::from_apic_bytes(&cover.as_apic_bytes()) {
|
||||
self.remove_back_cover();
|
||||
|
||||
if let Some(p) = self.inner.pictures.as_mut().map(std::borrow::Cow::to_mut) {
|
||||
p.push(pic)
|
||||
} else {
|
||||
self.inner.pictures = Some(Cow::from(vec![pic]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_front_cover(&mut self) {
|
||||
if let Some(p) = self.inner.pictures.clone() {
|
||||
let mut p = p.to_vec();
|
||||
p.retain(|pic| Some(pic) != self.front_cover().as_ref());
|
||||
self.inner.pictures = Some(Cow::from(p));
|
||||
if let Some(p) = self.inner.pictures.as_mut().map(std::borrow::Cow::to_mut) {
|
||||
p.retain(|pic| pic.pic_type != PictureType::CoverFront)
|
||||
}
|
||||
}
|
||||
|
||||
fn back_cover(&self) -> Option<Picture> {
|
||||
get_cover(PictureType::CoverBack, &self.inner.pictures)
|
||||
if let Some(p) = &self.inner.pictures {
|
||||
return p
|
||||
.iter()
|
||||
.find(|c| c.pic_type == PictureType::CoverBack)
|
||||
.cloned();
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(clippy::collapsible_if)]
|
||||
fn set_back_cover(&mut self, cover: Picture) {
|
||||
if let Some(pic) = create_cover(&cover) {
|
||||
self.remove_back_cover();
|
||||
self.inner.pictures = Some(replace_pic(pic, &self.inner.pictures))
|
||||
if PictureType::CoverBack == cover.pic_type {
|
||||
if let Ok(pic) = Picture::from_apic_bytes(&cover.as_apic_bytes()) {
|
||||
self.remove_back_cover();
|
||||
|
||||
if let Some(p) = self.inner.pictures.as_mut().map(std::borrow::Cow::to_mut) {
|
||||
p.push(pic)
|
||||
} else {
|
||||
self.inner.pictures = Some(Cow::from(vec![pic]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_back_cover(&mut self) {
|
||||
if let Some(p) = self.inner.pictures.clone() {
|
||||
let mut p = p.to_vec();
|
||||
p.retain(|pic| Some(pic) != self.back_cover().as_ref());
|
||||
self.inner.pictures = Some(Cow::from(p));
|
||||
if let Some(p) = self.inner.pictures.as_mut().map(std::borrow::Cow::to_mut) {
|
||||
p.retain(|pic| pic.pic_type != PictureType::CoverBack)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,47 +385,6 @@ impl AudioTagEdit for OggTag {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_cover(p_type: PictureType, pictures: &Option<Cow<'static, [Picture]>>) -> Option<Picture> {
|
||||
match pictures {
|
||||
None => None,
|
||||
Some(pictures) => {
|
||||
for pic in pictures.iter() {
|
||||
if pic.pic_type == p_type {
|
||||
return Some(pic.clone());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn create_cover(cover: &Picture) -> Option<Picture> {
|
||||
if cover.pic_type == PictureType::CoverFront || cover.pic_type == PictureType::CoverBack {
|
||||
if let Ok(pic) = Picture::from_apic_bytes(&cover.as_apic_bytes()) {
|
||||
return Some(pic);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn replace_pic(
|
||||
pic: Picture,
|
||||
pictures: &Option<Cow<'static, [Picture]>>,
|
||||
) -> Cow<'static, [Picture]> {
|
||||
if let Some(pictures) = pictures {
|
||||
let mut pictures = pictures.to_vec();
|
||||
pictures.retain(|p| p.pic_type != pic.pic_type);
|
||||
|
||||
pictures.push(pic);
|
||||
|
||||
Cow::from(pictures)
|
||||
} else {
|
||||
Cow::from(vec![pic])
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioTagWrite for OggTag {
|
||||
fn write_to(&self, file: &mut File) -> Result<()> {
|
||||
let mut sig = [0; 4];
|
||||
|
|
Loading…
Reference in a new issue