@@ -4,6 +4,8 @@ mod simple_tag;
44mod tag;
55mod tag_name;
66mod target;
7+ #[ cfg( test) ]
8+ mod tests;
79mod write;
810
911pub use attached_file:: * ;
@@ -70,26 +72,12 @@ pub struct MatroskaTagKey<'a>(TargetType, Cow<'a, str>);
7072
7173impl MatroskaTag {
7274 fn get ( & self , key : MatroskaTagKey < ' _ > ) -> Option < & SimpleTag < ' _ > > {
73- fn tag_matches_target ( tag : & Tag < ' _ > , target_type : TargetType ) -> bool {
74- let Some ( target) = & tag. target else {
75- // An empty target is implicitly `Album`
76- return target_type == TargetType :: Album ;
77- } ;
78-
79- target. is_candidate_for_type ( target_type)
80- }
81-
8275 let MatroskaTagKey ( target, key) = key;
8376
84- let applicable_tags = self
85- . tags
86- . iter ( )
87- . filter ( |tag| tag_matches_target ( tag, target) ) ;
77+ let applicable_tags = self . tags . iter ( ) . filter ( |tag| tag. matches_target ( target) ) ;
8878 for applicable_tag in applicable_tags {
8979 for item in applicable_tag. simple_tags . iter ( ) {
90- if item. name == key
91- && ( item. language . is_none ( )
92- || matches ! ( & item. language, Some ( Language :: Iso639_2 ( l) ) if l == "und" ) )
80+ if item. name == key && matches ! ( & item. language, Language :: Iso639_2 ( l) if l == "und" )
9381 {
9482 return Some ( item) ;
9583 }
@@ -99,6 +87,33 @@ impl MatroskaTag {
9987 None
10088 }
10189
90+ fn get_or_insert_tag_for_type < ' a > (
91+ & ' a mut self ,
92+ target_type : TargetType ,
93+ ) -> & ' a mut Tag < ' static > {
94+ let mut pos = None ;
95+ if let Some ( applicable_tag_pos) = self
96+ . tags
97+ . iter ( )
98+ . position ( |tag| tag. matches_target ( target_type) )
99+ {
100+ pos = Some ( applicable_tag_pos) ;
101+ }
102+
103+ if pos. is_none ( ) {
104+ pos = Some ( self . tags . len ( ) ) ;
105+
106+ let mut new_tag = Tag :: default ( ) ;
107+ if target_type != TargetType :: Album {
108+ new_tag. target = Some ( Target :: from ( target_type) ) ;
109+ }
110+
111+ self . tags . push ( new_tag) ;
112+ }
113+
114+ self . tags . get_mut ( pos. unwrap ( ) ) . unwrap ( )
115+ }
116+
102117 fn get_str ( & self , key : MatroskaTagKey < ' _ > ) -> Option < Cow < ' _ , str > > {
103118 let simple_tag = self . get ( key) ?;
104119 simple_tag. get_str ( ) . map ( Cow :: from)
@@ -229,8 +244,12 @@ impl Accessor for MatroskaTag {
229244 ) ;
230245
231246 fn track ( & self ) -> Option < u32 > {
232- // `PART_NUMBER` at level Track
233- todo ! ( )
247+ self . get ( MatroskaTagKey (
248+ TargetType :: Track ,
249+ Cow :: Borrowed ( "PART_NUMBER" ) ,
250+ ) )
251+ . and_then ( SimpleTag :: get_str)
252+ . and_then ( |val| val. parse :: < u32 > ( ) . ok ( ) )
234253 }
235254
236255 fn set_track ( & mut self , _value : u32 ) {
@@ -242,8 +261,12 @@ impl Accessor for MatroskaTag {
242261 }
243262
244263 fn track_total ( & self ) -> Option < u32 > {
245- // `TOTAL_PARTS` at level album
246- todo ! ( )
264+ self . get ( MatroskaTagKey (
265+ TargetType :: Album ,
266+ Cow :: Borrowed ( "TOTAL_PARTS" ) ,
267+ ) )
268+ . and_then ( SimpleTag :: get_str)
269+ . and_then ( |val| val. parse :: < u32 > ( ) . ok ( ) )
247270 }
248271
249272 fn set_track_total ( & mut self , _value : u32 ) {
@@ -318,19 +341,6 @@ impl TagExt for MatroskaTag {
318341 todo ! ( )
319342 }
320343
321- fn remove_from_path < P : AsRef < Path > > ( & self , _path : P ) -> std:: result:: Result < ( ) , Self :: Err > {
322- todo ! ( )
323- }
324-
325- fn remove_from < F > ( & self , _file : & mut F ) -> std:: result:: Result < ( ) , Self :: Err >
326- where
327- F : FileLike ,
328- LoftyError : From < <F as Truncate >:: Error > ,
329- LoftyError : From < <F as Length >:: Error > ,
330- {
331- todo ! ( )
332- }
333-
334344 fn clear ( & mut self ) {
335345 self . tags . clear ( ) ;
336346 self . attached_files . clear ( ) ;
0 commit comments