11use crate :: config:: ParseOptions ;
22use crate :: ebml:: element_reader:: { ElementChildIterator , ElementIdent , ElementReaderYield } ;
3- use crate :: ebml:: { EbmlTag , Language , SimpleTag , TagValue , TargetType } ;
3+ use crate :: ebml:: { EbmlTag , Language , SimpleTag , Tag , TagValue , Target , TargetType } ;
44use crate :: error:: Result ;
55
66use crate :: macros:: decode_err;
1717 while let Some ( child) = children_reader. next ( ) ? {
1818 match child {
1919 ElementReaderYield :: Master ( ( ElementIdent :: Tag , _size) ) => {
20- read_tag ( & mut children_reader. children ( ) , tag) ?
20+ let tag_element = read_tag ( & mut children_reader. children ( ) ) ?;
21+ tag. tags . push ( tag_element) ;
2122 } ,
2223 ElementReaderYield :: Eof => break ,
2324 _ => unimplemented ! ( "Unhandled child element in \\ Segment\\ Tags: {child:?}" ) ,
@@ -27,10 +28,13 @@ where
2728 Ok ( ( ) )
2829}
2930
30- fn read_tag < R > ( children_reader : & mut ElementChildIterator < ' _ , R > , _tag : & mut EbmlTag ) -> Result < ( ) >
31+ fn read_tag < R > ( children_reader : & mut ElementChildIterator < ' _ , R > ) -> Result < Tag >
3132where
3233 R : Read + Seek ,
3334{
35+ let mut target = None ;
36+ let mut simple_tags = Vec :: new ( ) ;
37+
3438 while let Some ( child) = children_reader. next ( ) ? {
3539 let ElementReaderYield :: Master ( ( master, _size) ) = child else {
3640 match child {
@@ -43,39 +47,39 @@ where
4347
4448 match master {
4549 ElementIdent :: Targets => {
46- let _ = read_targets ( & mut children_reader. children ( ) ) ?;
50+ if target. is_some ( ) {
51+ decode_err ! (
52+ @BAIL Ebml ,
53+ "Duplicate Targets element found in \\ Segment\\ Tags\\ Tag"
54+ ) ;
55+ }
56+
57+ target = Some ( read_targets ( & mut children_reader. children ( ) ) ?) ;
4758 } ,
4859 ElementIdent :: SimpleTag => {
49- let _ = read_simple_tag ( & mut children_reader. children ( ) ) ?;
60+ simple_tags . push ( read_simple_tag ( & mut children_reader. children ( ) ) ?) ;
5061 } ,
5162 _ => {
5263 unimplemented ! ( "Unhandled child element in \\ Segment\\ Tags\\ Tag: {master:?}" ) ;
5364 } ,
5465 }
5566 }
5667
57- Ok ( ( ) )
58- }
68+ let Some ( target) = target else {
69+ decode_err ! ( @BAIL Ebml , "\\ Segment\\ Tags\\ Tag is missing the required `Targets` element" ) ;
70+ } ;
5971
60- struct Target {
61- target_type_value : TargetType ,
62- target_type : Option < String > ,
63- track_uid : Vec < u64 > ,
64- edition_uid : Vec < u64 > ,
65- chapter_uid : Vec < u64 > ,
66- attachment_uid : Vec < u64 > ,
72+ Ok ( Tag {
73+ target,
74+ simple_tags,
75+ } )
6776}
6877
6978fn read_targets < R > ( children_reader : & mut ElementChildIterator < ' _ , R > ) -> Result < Target >
7079where
7180 R : Read + Seek ,
7281{
73- let mut target_type_value = None ;
74- let mut target_type = None ;
75- let mut track_uid = Vec :: new ( ) ;
76- let mut edition_uid = Vec :: new ( ) ;
77- let mut chapter_uid = Vec :: new ( ) ;
78- let mut attachment_uid = Vec :: new ( ) ;
82+ let mut target = Target :: default ( ) ;
7983
8084 while let Some ( child) = children_reader. next ( ) ? {
8185 let ElementReaderYield :: Child ( ( child, size) ) = child else {
@@ -89,46 +93,43 @@ where
8993
9094 match child. ident {
9195 ElementIdent :: TargetTypeValue => {
92- target_type_value = Some ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
96+ let value = children_reader. read_unsigned_int ( size. value ( ) ) ?;
97+
98+ // Casting the `u64` to `u8` is safe because the value is checked to be within
99+ // the range of `TargetType` anyway.
100+ let target_type = TargetType :: try_from ( value as u8 ) ?;
101+ target. target_type = target_type;
93102 } ,
94103 ElementIdent :: TargetType => {
95- target_type = Some ( children_reader. read_string ( size. value ( ) ) ?) ;
104+ target . name = Some ( children_reader. read_string ( size. value ( ) ) ?) ;
96105 } ,
97106 ElementIdent :: TagTrackUID => {
98- track_uid. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
107+ let mut track_uids = target. track_uids . unwrap_or_default ( ) ;
108+ track_uids. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
109+ target. track_uids = Some ( track_uids) ;
99110 } ,
100111 ElementIdent :: TagEditionUID => {
101- edition_uid. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
112+ let mut edition_uids = target. edition_uids . unwrap_or_default ( ) ;
113+ edition_uids. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
114+ target. edition_uids = Some ( edition_uids) ;
102115 } ,
103116 ElementIdent :: TagChapterUID => {
104- chapter_uid. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
117+ let mut chapter_uids = target. chapter_uids . unwrap_or_default ( ) ;
118+ chapter_uids. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
119+ target. chapter_uids = Some ( chapter_uids) ;
105120 } ,
106121 ElementIdent :: TagAttachmentUID => {
107- attachment_uid. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
122+ let mut attachment_uids = target. attachment_uids . unwrap_or_default ( ) ;
123+ attachment_uids. push ( children_reader. read_unsigned_int ( size. value ( ) ) ?) ;
124+ target. attachment_uids = Some ( attachment_uids) ;
108125 } ,
109126 _ => {
110127 unreachable ! ( "Unhandled child element in \\ Segment\\ Tags\\ Tag\\ Targets: {child:?}" )
111128 } ,
112129 }
113130 }
114131
115- let target_type_value = match target_type_value {
116- // Casting the `u64` to `u8` is safe because the value is checked to be within
117- // the range of `TargetType` anyway.
118- Some ( value) => TargetType :: try_from ( value as u8 ) ?,
119- // The spec defines TargetType 50 (Album) as the default value, as it is the most
120- // common grouping level.
121- None => TargetType :: Album ,
122- } ;
123-
124- Ok ( Target {
125- target_type_value,
126- target_type,
127- track_uid,
128- edition_uid,
129- chapter_uid,
130- attachment_uid,
131- } )
132+ Ok ( target)
132133}
133134
134135fn read_simple_tag < R > ( children_reader : & mut ElementChildIterator < ' _ , R > ) -> Result < SimpleTag >
0 commit comments