@@ -125,6 +125,10 @@ impl Ilst {
125
125
126
126
/// Inserts an [`Atom`]
127
127
///
128
+ /// NOTE: Do not use this to replace atoms. This will take the value from the provided atom and
129
+ /// merge it into an atom of the same type, keeping any existing value(s). To ensure an atom
130
+ /// is replaced, use [`Ilst::replace_atom`].
131
+ ///
128
132
/// # Examples
129
133
///
130
134
/// ```rust
@@ -142,7 +146,8 @@ impl Ilst {
142
146
/// let title = ilst.get(&TITLE_IDENTIFIER);
143
147
/// assert!(title.is_some());
144
148
/// ```
145
- pub fn insert ( & mut self , atom : Atom < ' _ > ) {
149
+ #[ allow( clippy:: missing_panics_doc) ] // Unwrap on an infallible
150
+ pub fn insert ( & mut self , atom : Atom < ' static > ) {
146
151
if atom. ident == COVR && atom. data . is_pictures ( ) {
147
152
for data in atom. data {
148
153
match data {
@@ -153,7 +158,14 @@ impl Ilst {
153
158
return ;
154
159
}
155
160
156
- self . atoms . push ( atom. into_owned ( ) ) ;
161
+ if let Some ( existing) = self . get_mut ( atom. ident ( ) ) {
162
+ existing. merge ( atom) . expect (
163
+ "Somehow the atom merge condition failed, despite the validation beforehand." ,
164
+ ) ;
165
+ return ;
166
+ }
167
+
168
+ self . atoms . push ( atom) ;
157
169
}
158
170
159
171
/// Inserts an [`Atom`], replacing any atom with the same [`AtomIdent`]
@@ -752,6 +764,7 @@ impl From<Tag> for Ilst {
752
764
#[ cfg( test) ]
753
765
mod tests {
754
766
use crate :: mp4:: ilst:: atom:: AtomDataStorage ;
767
+ use crate :: mp4:: ilst:: TITLE ;
755
768
use crate :: mp4:: read:: AtomReader ;
756
769
use crate :: mp4:: { AdvisoryRating , Atom , AtomData , AtomIdent , Ilst , Mp4File } ;
757
770
use crate :: tag:: utils:: test_utils;
@@ -1156,4 +1169,20 @@ mod tests {
1156
1169
1157
1170
assert_eq ! ( file. ilst( ) , Some ( & Ilst :: default ( ) ) ) ;
1158
1171
}
1172
+
1173
+ #[ test]
1174
+ fn merge_insert ( ) {
1175
+ let mut ilst = Ilst :: new ( ) ;
1176
+
1177
+ // Insert two titles
1178
+ ilst. set_title ( String :: from ( "Foo" ) ) ;
1179
+ ilst. insert ( Atom :: new ( TITLE , AtomData :: UTF8 ( String :: from ( "Bar" ) ) ) ) ;
1180
+
1181
+ // Title should still be the first value, but there should be two total values
1182
+ assert_eq ! ( ilst. title( ) . as_deref( ) , Some ( "Foo" ) ) ;
1183
+ assert_eq ! ( ilst. get( & TITLE ) . unwrap( ) . data( ) . count( ) , 2 ) ;
1184
+
1185
+ // Meaning we only have 1 atom
1186
+ assert_eq ! ( ilst. len( ) , 1 ) ;
1187
+ }
1159
1188
}
0 commit comments