pub struct BlockList { /* private fields */ }Expand description
A collection of metadata blocks
This collection enforces the restriction that FLAC files must always contain a STREAMINFO metadata block and that block must always be first in the file.
Because it is required, that block may be retrieved unconditionally from this collection, while all others are optional and may appear in any order.
Implementations§
Source§impl BlockList
impl BlockList
Sourcepub fn new(streaminfo: Streaminfo) -> Self
pub fn new(streaminfo: Streaminfo) -> Self
Creates BlockList from initial STREAMINFO
Sourcepub fn read<R: Read>(r: R) -> Result<Self, Error>
pub fn read<R: Read>(r: R) -> Result<Self, Error>
Reads BlockList from the given reader
This assumes the reader is rewound to the beginning of the file.
Because this may perform many small reads, using a buffered reader is preferred when reading from a raw file.
§Errors
Returns any error reading or parsing metadata blocks
Sourcepub fn open<P: AsRef<Path>>(p: P) -> Result<Self, Error>
pub fn open<P: AsRef<Path>>(p: P) -> Result<Self, Error>
Reads BlockList from the given file path
§Errors
Returns any error reading or parsing metadata blocks
Sourcepub fn streaminfo(&self) -> &Streaminfo
pub fn streaminfo(&self) -> &Streaminfo
Returns reference to our STREAMINFO metadata block
Sourcepub fn streaminfo_mut(&mut self) -> &mut Streaminfo
pub fn streaminfo_mut(&mut self) -> &mut Streaminfo
Returns exclusive reference to our STREAMINFO metadata block
Care must be taken when modifying the STREAMINFO, or one’s file could be rendered unplayable.
Sourcepub fn blocks(&self) -> impl Iterator<Item = BlockRef<'_>>
pub fn blocks(&self) -> impl Iterator<Item = BlockRef<'_>>
Iterates over all the metadata blocks
Sourcepub fn insert<B: OptionalMetadataBlock>(&mut self, block: B) -> Option<B>
pub fn insert<B: OptionalMetadataBlock>(&mut self, block: B) -> Option<B>
Inserts new optional metadata block
If the block may only occur once in the stream (such as the SEEKTABLE), any existing block of the same type removed and extracted first.
Sourcepub fn get<B: OptionalMetadataBlock>(&self) -> Option<&B>
pub fn get<B: OptionalMetadataBlock>(&self) -> Option<&B>
Gets reference to metadata block, if present
If the block type occurs multiple times, this returns the first instance.
Sourcepub fn get_mut<B: OptionalMetadataBlock>(&mut self) -> Option<&mut B>
pub fn get_mut<B: OptionalMetadataBlock>(&mut self) -> Option<&mut B>
Gets mutable reference to metadata block, if present
If the block type occurs multiple times, this returns the first instance.
Sourcepub fn get_pair_mut<B, C>(&mut self) -> (Option<&mut B>, Option<&mut C>)where
B: OptionalMetadataBlock,
C: OptionalMetadataBlock,
pub fn get_pair_mut<B, C>(&mut self) -> (Option<&mut B>, Option<&mut C>)where
B: OptionalMetadataBlock,
C: OptionalMetadataBlock,
Gets mutable references to a pair of metadata blocks
If either block type occurs multiple times, this returns the first instance.
Sourcepub fn get_all<'b, B: OptionalMetadataBlock + 'b>(
&'b self,
) -> impl Iterator<Item = &'b B>
pub fn get_all<'b, B: OptionalMetadataBlock + 'b>( &'b self, ) -> impl Iterator<Item = &'b B>
Gets references to all metadata blocks of the given type
Sourcepub fn get_all_mut<'b, B: OptionalMetadataBlock + 'b>(
&'b mut self,
) -> impl Iterator<Item = &'b mut B>
pub fn get_all_mut<'b, B: OptionalMetadataBlock + 'b>( &'b mut self, ) -> impl Iterator<Item = &'b mut B>
Gets exclusive references to all metadata blocks of the given type
Sourcepub fn has<B: OptionalMetadataBlock>(&self) -> bool
pub fn has<B: OptionalMetadataBlock>(&self) -> bool
Returns true if block exists in list
Sourcepub fn remove<B: OptionalMetadataBlock>(&mut self)
pub fn remove<B: OptionalMetadataBlock>(&mut self)
Removes all instances of the given metadata block type
Sourcepub fn update<B>(&mut self, f: impl FnOnce(&mut B))where
B: OptionalMetadataBlock + Default,
pub fn update<B>(&mut self, f: impl FnOnce(&mut B))where
B: OptionalMetadataBlock + Default,
Updates first instance of the given block, creating it if necessary
§Example
use flac_codec::metadata::{BlockList, Streaminfo, VorbisComment};
use flac_codec::metadata::fields::ARTIST;
// build a BlockList with a dummy Streaminfo
let mut blocklist = BlockList::new(
Streaminfo {
minimum_block_size: 0,
maximum_block_size: 0,
minimum_frame_size: None,
maximum_frame_size: None,
sample_rate: 44100,
channels: 1u8.try_into().unwrap(),
bits_per_sample: 16u32.try_into().unwrap(),
total_samples: None,
md5: None,
},
);
// the block starts out with no comment
assert!(blocklist.get::<VorbisComment>().is_none());
// update Vorbis Comment with artist field,
// which adds a new block to the list
blocklist.update::<VorbisComment>(
|vc| vc.insert(ARTIST, "Artist 1")
);
assert!(blocklist.get::<VorbisComment>().is_some());
// updating Vorbis Comment again reuses that same block
blocklist.update::<VorbisComment>(
|vc| vc.insert(ARTIST, "Artist 2")
);
// the block now has two entries
assert_eq!(
blocklist.get::<VorbisComment>()
.unwrap()
.all(ARTIST).collect::<Vec<_>>(),
vec!["Artist 1", "Artist 2"],
);Sourcepub fn sort_by<O: Ord>(&mut self, f: impl Fn(OptionalBlockType) -> O)
pub fn sort_by<O: Ord>(&mut self, f: impl Fn(OptionalBlockType) -> O)
Sorts optional metadata blocks by block type
The function converts the type to some key which is used for ordering blocks from smallest to largest.
The order of blocks of the same type is preserved. This is an important consideration for APPLICATION metadata blocks, which may contain foreign metadata chunks that must be re-applied in the same order.
§Example
use flac_codec::metadata::{
BlockList, Streaminfo, Application, Padding, AsBlockRef,
OptionalBlockType,
};
// build a BlockList with a dummy Streaminfo
let streaminfo = Streaminfo {
minimum_block_size: 0,
maximum_block_size: 0,
minimum_frame_size: None,
maximum_frame_size: None,
sample_rate: 44100,
channels: 1u8.try_into().unwrap(),
bits_per_sample: 16u32.try_into().unwrap(),
total_samples: None,
md5: None,
};
let mut blocklist = BlockList::new(streaminfo.clone());
// add some blocks
let application_1 = Application {
id: 0x1234,
data: vec![0x01, 0x02, 0x03, 0x04],
};
blocklist.insert(application_1.clone());
let padding = Padding {
size: 10u32.try_into().unwrap(),
};
blocklist.insert(padding.clone());
let application_2 = Application {
id: 0x6789,
data: vec![0x06, 0x07, 0x08, 0x09],
};
blocklist.insert(application_2.clone());
// check their inital order
let mut iter = blocklist.blocks();
assert_eq!(iter.next(), Some(streaminfo.as_block_ref()));
assert_eq!(iter.next(), Some(application_1.as_block_ref()));
assert_eq!(iter.next(), Some(padding.as_block_ref()));
assert_eq!(iter.next(), Some(application_2.as_block_ref()));
assert_eq!(iter.next(), None);
drop(iter);
// sort the blocks to put padding last
blocklist.sort_by(|t| match t {
OptionalBlockType::Application => 0,
OptionalBlockType::SeekTable => 1,
OptionalBlockType::VorbisComment => 2,
OptionalBlockType::Cuesheet => 3,
OptionalBlockType::Picture => 4,
OptionalBlockType::Padding => 5,
});
// re-check their new order
let mut iter = blocklist.blocks();
assert_eq!(iter.next(), Some(streaminfo.as_block_ref()));
assert_eq!(iter.next(), Some(application_1.as_block_ref()));
assert_eq!(iter.next(), Some(application_2.as_block_ref()));
assert_eq!(iter.next(), Some(padding.as_block_ref()));
assert_eq!(iter.next(), None);