lofty/config/write_options.rs
1/// Options to control how Lofty writes to a file
2///
3/// This acts as a dumping ground for all sorts of format-specific settings. As such, this is best
4/// used as an application global config that gets set once.
5#[derive(Copy, Clone, Debug, Eq, PartialEq)]
6#[non_exhaustive]
7pub struct WriteOptions {
8 pub(crate) preferred_padding: Option<u32>,
9 pub(crate) remove_others: bool,
10 pub(crate) respect_read_only: bool,
11 pub(crate) uppercase_id3v2_chunk: bool,
12 pub(crate) use_id3v23: bool,
13}
14
15impl WriteOptions {
16 /// Default preferred padding size in bytes
17 pub const DEFAULT_PREFERRED_PADDING: u32 = 1024;
18
19 /// Creates a new `WriteOptions`, alias for `Default` implementation
20 ///
21 /// See also: [`WriteOptions::default`]
22 ///
23 /// # Examples
24 ///
25 /// ```rust
26 /// use lofty::config::WriteOptions;
27 ///
28 /// let write_options = WriteOptions::new();
29 /// ```
30 pub const fn new() -> Self {
31 Self {
32 preferred_padding: Some(Self::DEFAULT_PREFERRED_PADDING),
33 remove_others: false,
34 respect_read_only: true,
35 uppercase_id3v2_chunk: true,
36 use_id3v23: false,
37 }
38 }
39
40 /// Set the preferred padding size in bytes
41 ///
42 /// If the tag format being written supports padding, this will be the size of the padding
43 /// in bytes.
44 ///
45 /// NOTES:
46 ///
47 /// * Not all tag formats support padding
48 /// * The actual padding size may be different from this value, depending on tag size limitations
49 ///
50 /// # Examples
51 ///
52 /// ```rust
53 /// use lofty::config::WriteOptions;
54 ///
55 /// // I really don't want my files rewritten, so I'll double the padding size!
56 /// let options = WriteOptions::new().preferred_padding(2048);
57 ///
58 /// // ...Or I don't want padding under any circumstances!
59 /// let options = WriteOptions::new().preferred_padding(0);
60 /// ```
61 pub fn preferred_padding(mut self, preferred_padding: u32) -> Self {
62 match preferred_padding {
63 0 => self.preferred_padding = None,
64 _ => self.preferred_padding = Some(preferred_padding),
65 }
66 self
67 }
68
69 /// Whether to remove all other tags when writing
70 ///
71 /// If set to `true`, only the tag being written will be kept in the file.
72 ///
73 /// # Examples
74 ///
75 /// ```rust,no_run
76 /// use lofty::config::WriteOptions;
77 /// use lofty::prelude::*;
78 /// use lofty::tag::{Tag, TagType};
79 ///
80 /// # fn main() -> lofty::error::Result<()> {
81 /// let mut id3v2_tag = Tag::new(TagType::Id3v2);
82 ///
83 /// // ...
84 ///
85 /// // I only want to keep the ID3v2 tag around!
86 /// let options = WriteOptions::new().remove_others(true);
87 /// id3v2_tag.save_to_path("test.mp3", options)?;
88 /// # Ok(()) }
89 /// ```
90 pub fn remove_others(mut self, remove_others: bool) -> Self {
91 self.remove_others = remove_others;
92 self
93 }
94
95 /// Whether to respect read-only tag items
96 ///
97 /// Some tag formats allow for items to be marked as read-only. If set to `true`, these items
98 /// will take priority over newly created tag items.
99 ///
100 /// NOTE: In the case of APE tags, one can mark the entire tag as read-only. This will append
101 /// the existing tag items to the new tag.
102 ///
103 /// # Examples
104 ///
105 /// ```rust,no_run
106 /// use lofty::config::WriteOptions;
107 /// use lofty::prelude::*;
108 /// use lofty::tag::{Tag, TagType};
109 ///
110 /// # fn main() -> lofty::error::Result<()> {
111 /// let mut id3v2_tag = Tag::new(TagType::Id3v2);
112 ///
113 /// // ...
114 ///
115 /// // I don't care about read-only items, I want to write my new items!
116 /// let options = WriteOptions::new().respect_read_only(false);
117 /// id3v2_tag.save_to_path("test.mp3", options)?;
118 /// # Ok(()) }
119 /// ```
120 pub fn respect_read_only(mut self, respect_read_only: bool) -> Self {
121 self.respect_read_only = respect_read_only;
122 self
123 }
124
125 /// Whether to uppercase the ID3v2 chunk name
126 ///
127 /// When dealing with RIFF/AIFF files, some software may expect the ID3v2 chunk name to be
128 /// lowercase.
129 ///
130 /// NOTE: The vast majority of software will be able to read both upper and lowercase
131 /// chunk names.
132 ///
133 /// # Examples
134 ///
135 /// ```rust,no_run
136 /// use lofty::config::WriteOptions;
137 /// use lofty::prelude::*;
138 /// use lofty::tag::{Tag, TagType};
139 ///
140 /// # fn main() -> lofty::error::Result<()> {
141 /// let mut id3v2_tag = Tag::new(TagType::Id3v2);
142 ///
143 /// // ...
144 ///
145 /// // I want to keep the ID3v2 chunk name lowercase
146 /// let options = WriteOptions::new().uppercase_id3v2_chunk(false);
147 /// id3v2_tag.save_to_path("test.mp3", options)?;
148 /// # Ok(()) }
149 pub fn uppercase_id3v2_chunk(mut self, uppercase_id3v2_chunk: bool) -> Self {
150 self.uppercase_id3v2_chunk = uppercase_id3v2_chunk;
151 self
152 }
153
154 /// Whether or not to use ID3v2.3 when saving [`TagType::Id3v2`](crate::tag::TagType::Id3v2)
155 /// or [`Id3v2Tag`](crate::id3::v2::Id3v2Tag)
156 ///
157 /// By default, Lofty will save ID3v2.4 tags. This option allows you to save ID3v2.3 tags instead.
158 ///
159 /// # Examples
160 ///
161 /// ```rust,no_run
162 /// use lofty::config::WriteOptions;
163 /// use lofty::prelude::*;
164 /// use lofty::tag::{Tag, TagType};
165 ///
166 /// # fn main() -> lofty::error::Result<()> {
167 /// let mut id3v2_tag = Tag::new(TagType::Id3v2);
168 ///
169 /// // ...
170 ///
171 /// // I need to save ID3v2.3 tags to support older software
172 /// let options = WriteOptions::new().use_id3v23(true);
173 /// id3v2_tag.save_to_path("test.mp3", options)?;
174 /// # Ok(()) }
175 /// ```
176 pub fn use_id3v23(&mut self, use_id3v23: bool) -> Self {
177 self.use_id3v23 = use_id3v23;
178 *self
179 }
180}
181
182impl Default for WriteOptions {
183 /// The default implementation for `WriteOptions`
184 ///
185 /// The defaults are as follows:
186 ///
187 /// ```rust,ignore
188 /// WriteOptions {
189 /// preferred_padding: 1024,
190 /// remove_others: false,
191 /// respect_read_only: true,
192 /// uppercase_id3v2_chunk: true,
193 /// use_id3v23: false,
194 /// }
195 /// ```
196 fn default() -> Self {
197 Self::new()
198 }
199}