mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-11-10 14:44:22 +00:00
ID3v2: Expose {synch_u32, unsynch_u32}
This commit is contained in:
parent
efedf0f443
commit
ec4fb07042
7 changed files with 72 additions and 57 deletions
|
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- **A proc macro for file creation**:
|
- **A proc macro for file creation**:
|
||||||
- With the new `lofty_attr` crate, file creation has been simplified significantly.
|
- With the new `lofty_attr` crate, file creation has been simplified significantly.
|
||||||
It is available for both internal and external usage.
|
It is available for both internal and external usage.
|
||||||
|
- **ID3v2**: Exposed internal functions `id3::v2::util::{synch_u32, unsynch_u32}`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- **TaggedFile**: `tag{_mut}` no longer takes a reference to `TagType`
|
- **TaggedFile**: `tag{_mut}` no longer takes a reference to `TagType`
|
||||||
|
|
|
@ -699,7 +699,7 @@ impl FileType {
|
||||||
|
|
||||||
// TODO: APE tags in the beginning of the file
|
// TODO: APE tags in the beginning of the file
|
||||||
pub(crate) fn from_buffer_inner(buf: &[u8]) -> (Option<Self>, Option<u32>) {
|
pub(crate) fn from_buffer_inner(buf: &[u8]) -> (Option<Self>, Option<u32>) {
|
||||||
use crate::id3::v2::unsynch_u32;
|
use crate::id3::v2::util::unsynch_u32;
|
||||||
|
|
||||||
// Start out with an empty return: (File type, id3 size)
|
// Start out with an empty return: (File type, id3 size)
|
||||||
// Only one can be set
|
// Only one can be set
|
||||||
|
|
|
@ -80,7 +80,7 @@ where
|
||||||
|
|
||||||
// unsynch the frame size if necessary
|
// unsynch the frame size if necessary
|
||||||
if synchsafe {
|
if synchsafe {
|
||||||
size = crate::id3::v2::unsynch_u32(size);
|
size = crate::id3::v2::util::unsynch_u32(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
let frame_id = FrameID::new(id_str)?;
|
let frame_id = FrameID::new(id_str)?;
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
//! * [Frame]
|
//! * [Frame]
|
||||||
|
|
||||||
mod flags;
|
mod flags;
|
||||||
pub(crate) mod util;
|
pub mod util;
|
||||||
|
|
||||||
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
||||||
use crate::macros::err;
|
use crate::macros::err;
|
||||||
|
use util::unsynch_u32;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
@ -66,24 +67,6 @@ pub enum ID3v2Version {
|
||||||
V4,
|
V4,
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/polyfloyd/rust-id3/blob/e142ec656bf70a8153f6e5b34a37f26df144c3c1/src/stream/unsynch.rs#L18-L20
|
|
||||||
pub(crate) fn unsynch_u32(n: u32) -> u32 {
|
|
||||||
n & 0xFF | (n & 0xFF00) >> 1 | (n & 0xFF_0000) >> 2 | (n & 0xFF00_0000) >> 3
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "id3v2")]
|
|
||||||
// https://github.com/polyfloyd/rust-id3/blob/e142ec656bf70a8153f6e5b34a37f26df144c3c1/src/stream/unsynch.rs#L9-L15
|
|
||||||
pub(crate) fn synch_u32(n: u32) -> Result<u32> {
|
|
||||||
if n > 0x1000_0000 {
|
|
||||||
err!(TooMuchData);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut x: u32 = n & 0x7F | (n & 0xFFFF_FF80) << 1;
|
|
||||||
x = x & 0x7FFF | (x & 0xFFFF_8000) << 1;
|
|
||||||
x = x & 0x7F_FFFF | (x & 0xFF80_0000) << 1;
|
|
||||||
Ok(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) struct ID3v2Header {
|
pub(crate) struct ID3v2Header {
|
||||||
#[cfg(feature = "id3v2")]
|
#[cfg(feature = "id3v2")]
|
||||||
|
|
|
@ -1,53 +1,84 @@
|
||||||
|
//! Utilities for working with ID3v2 tags
|
||||||
|
|
||||||
pub(crate) mod text_utils;
|
pub(crate) mod text_utils;
|
||||||
#[cfg(feature = "id3v2")]
|
|
||||||
pub(crate) mod upgrade;
|
|
||||||
|
|
||||||
#[cfg(feature = "id3v2")]
|
cfg_if::cfg_if! {
|
||||||
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
if #[cfg(feature = "id3v2")] {
|
||||||
|
pub(crate) mod upgrade;
|
||||||
|
|
||||||
#[cfg(feature = "id3v2")]
|
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
||||||
pub(in crate::id3::v2) fn unsynch_content(content: &[u8]) -> Result<Vec<u8>> {
|
|
||||||
let mut unsynch_content = Vec::new();
|
|
||||||
|
|
||||||
let mut discard = false;
|
pub(in crate::id3::v2) fn unsynch_content(content: &[u8]) -> Result<Vec<u8>> {
|
||||||
|
let mut unsynch_content = Vec::new();
|
||||||
|
|
||||||
let mut i = 0;
|
let mut discard = false;
|
||||||
let mut next = 0;
|
|
||||||
let content_len = content.len();
|
|
||||||
|
|
||||||
// Check for (0xFF, 0x00, 0x00), replace with (0xFF, 0x00)
|
let mut i = 0;
|
||||||
while i < content_len && next < content_len {
|
let mut next = 0;
|
||||||
// Verify the next byte is less than 0xE0 (0b111xxxxx)
|
let content_len = content.len();
|
||||||
// Then remove the next byte if it is a zero
|
|
||||||
if discard {
|
// Check for (0xFF, 0x00, 0x00), replace with (0xFF, 0x00)
|
||||||
if content[next] >= 0xE0 {
|
while i < content_len && next < content_len {
|
||||||
return Err(ID3v2Error::new(ID3v2ErrorKind::Other(
|
// Verify the next byte is less than 0xE0 (0b111xxxxx)
|
||||||
"Encountered an invalid unsynchronisation",
|
// Then remove the next byte if it is a zero
|
||||||
))
|
if discard {
|
||||||
.into());
|
if content[next] >= 0xE0 {
|
||||||
}
|
return Err(ID3v2Error::new(ID3v2ErrorKind::Other(
|
||||||
|
"Encountered an invalid unsynchronisation",
|
||||||
|
))
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if content[next] == 0 {
|
||||||
|
discard = false;
|
||||||
|
next += 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if content[next] == 0 {
|
|
||||||
discard = false;
|
discard = false;
|
||||||
|
|
||||||
|
unsynch_content.push(content[next]);
|
||||||
|
|
||||||
|
if content[next] == 0xFF {
|
||||||
|
discard = true
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
next += 1;
|
next += 1;
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(unsynch_content)
|
||||||
}
|
}
|
||||||
|
|
||||||
discard = false;
|
/// Create a synchsafe integer
|
||||||
|
///
|
||||||
|
/// See [`FrameFlags::unsynchronisation`](crate::id3::v2::FrameFlags::unsynchronisation) for an explanation.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// `n` doesn't fit in 28 bits
|
||||||
|
// https://github.com/polyfloyd/rust-id3/blob/e142ec656bf70a8153f6e5b34a37f26df144c3c1/src/stream/unsynch.rs#L9-L15
|
||||||
|
pub fn synch_u32(n: u32) -> Result<u32> {
|
||||||
|
if n > 0x1000_0000 {
|
||||||
|
crate::macros::err!(TooMuchData);
|
||||||
|
}
|
||||||
|
|
||||||
unsynch_content.push(content[next]);
|
let mut x: u32 = n & 0x7F | (n & 0xFFFF_FF80) << 1;
|
||||||
|
x = x & 0x7FFF | (x & 0xFFFF_8000) << 1;
|
||||||
if content[next] == 0xFF {
|
x = x & 0x7F_FFFF | (x & 0xFF80_0000) << 1;
|
||||||
discard = true
|
Ok(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1;
|
|
||||||
next += 1;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(unsynch_content)
|
/// Unsynchronise a synchsafe integer
|
||||||
|
///
|
||||||
|
/// See [`FrameFlags::unsynchronisation`](crate::id3::v2::FrameFlags::unsynchronisation) for an explanation.
|
||||||
|
// https://github.com/polyfloyd/rust-id3/blob/e142ec656bf70a8153f6e5b34a37f26df144c3c1/src/stream/unsynch.rs#L18-L20
|
||||||
|
pub fn unsynch_u32(n: u32) -> u32 {
|
||||||
|
n & 0xFF | (n & 0xFF00) >> 1 | (n & 0xFF_0000) >> 2 | (n & 0xFF00_0000) >> 3
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
use crate::error::{ID3v2Error, ID3v2ErrorKind, Result};
|
||||||
use crate::id3::v2::frame::{FrameFlags, FrameRef, FrameValue};
|
use crate::id3::v2::frame::{FrameFlags, FrameRef, FrameValue};
|
||||||
use crate::id3::v2::synch_u32;
|
use crate::id3::v2::util::synch_u32;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::file::FileType;
|
||||||
use crate::id3::find_id3v2;
|
use crate::id3::find_id3v2;
|
||||||
use crate::id3::v2::frame::FrameRef;
|
use crate::id3::v2::frame::FrameRef;
|
||||||
use crate::id3::v2::synch_u32;
|
|
||||||
use crate::id3::v2::tag::Id3v2TagRef;
|
use crate::id3::v2::tag::Id3v2TagRef;
|
||||||
|
use crate::id3::v2::util::synch_u32;
|
||||||
use crate::macros::err;
|
use crate::macros::err;
|
||||||
use crate::probe::Probe;
|
use crate::probe::Probe;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue