mkv/elements/
midlevel.rs

1use std::io::Write;
2
3use super::parser::Event;
4use super::parser::SimpleContent;
5use super::database::Class;
6use super::database::id_to_class;
7use super::database::class_to_id;
8use super::generator::generate_ebml_number;
9use super::generator::EbmlNumberMode;
10use std::rc::Rc;
11use super::Element;
12use super::parser::EventsHandler;
13use super::builder::Builder;
14use super::generator::generate;
15use super::el_bin;
16
17#[derive(Debug)]
18pub enum MidlevelEvent<'a> {
19    EnterElement(Class),
20    LeaveElement(Class),
21    
22    Element(Rc<Element>), // After "Build" reply
23    Content(SimpleContent<'a>),
24    
25    Resync,
26}
27
28pub enum WhatToDo {
29    Build, // build DOM for this element
30    GoOn, // continue delivering events without starting builder
31}
32
33pub trait MidlevelEventHandler {
34    fn event(&mut self, e: MidlevelEvent) -> ();
35    fn how_to_handle(&mut self, c: Class) -> WhatToDo;
36}
37
38/// Mid-evel parser allows using Builder, but skipping headers of Segments or Clusters
39/// to avoid holding too much data in memory;
40pub struct MidlevelParser<H:MidlevelEventHandler> {
41    h:H,
42    b:Option<Builder>
43}
44
45impl<H:MidlevelEventHandler> MidlevelParser<H> {
46    pub fn new(h_:H) -> MidlevelParser<H> {
47        MidlevelParser { h:h_ , b:None}
48    }
49    
50    pub fn borrow_handler    (&self)     -> &H {        &self.h }
51    pub fn borrow_handler_mut(&mut self) -> &mut H {&mut self.h }
52    pub fn into_handler      (self)      -> H { self.h }
53}
54
55impl<H:MidlevelEventHandler> EventsHandler for MidlevelParser<H> {
56    fn event(&mut self, e : super::parser::Event) {
57        use super::parser::Event::*;
58
59        match e {
60            Begin(x)    => {
61                if let Some(ref mut b) = self.b {
62                    b.event(e);
63                } else {
64                    let klass = id_to_class(x.id);
65                    match self.h.how_to_handle(klass) {
66                        WhatToDo::GoOn => {
67                            self.h.event(MidlevelEvent::EnterElement(klass));
68                        }
69                        WhatToDo::Build => {
70                            let mut b = Builder::new();
71                            b.event(e);
72                            self.b = Some(b);
73                        }
74                    }
75                }
76            }
77            Data(_) if self.b.is_some() => {
78                if let Some(ref mut b) = self.b {
79                    b.event(e);
80                }
81            }
82            Data(x) => {
83                self.h.event(MidlevelEvent::Content(x));
84            }
85            End(x)      => {
86                if let Some(mut b) = self.b.take() {
87                    b.event(e);
88                    if ! b.captured_elements().is_empty() {
89                        let element = b.into_captured_elements().into_iter().next().unwrap();
90                        self.h.event(MidlevelEvent::Element(element));
91                    } else {
92                        self.b = Some(b);
93                    }
94                } else {
95                    self.h.event(MidlevelEvent::LeaveElement(id_to_class(x.id)));
96                }
97                
98            }
99            Resync      => {
100                self.b = None;
101                self.h.event(MidlevelEvent::Resync);
102            },
103        };
104    }
105}
106
107
108/// Serialize events back into mkv file.
109/// Segment size will be unfilled, Void will be auto-insterted.
110/// EBML head will be copied as is
111pub struct MidlevelEventsToFile<W:Write> {
112    w: W,
113}
114
115impl<W:Write> MidlevelEventsToFile<W> {
116    pub fn new(w_:W) -> Self {
117        MidlevelEventsToFile { w:w_ }
118    }
119    
120    pub fn borrow_file    (&self)     -> &W {        &self.w }
121    pub fn borrow_file_mut(&mut self) -> &mut W {&mut self.w }
122    pub fn into_file      (self)      -> W { self.w }
123}
124
125impl<W:Write> MidlevelEventHandler for MidlevelEventsToFile<W> {
126    fn how_to_handle(&mut self, klass: Class) -> WhatToDo {
127        if klass == Class::Segment {
128            WhatToDo::GoOn
129        } else {
130            WhatToDo::Build
131        }
132    }
133    fn event(&mut self, e: MidlevelEvent) -> () {
134        match e {
135            MidlevelEvent::EnterElement(klass) => {
136                if (klass == Class::Segment) {
137                    self.w.write(&generate_ebml_number(class_to_id(klass), EbmlNumberMode::Identifier)).unwrap();
138                    self.w.write(b"\xFF").unwrap(); // unknown length
139                    self.w.write(&generate(&el_bin(Class::Void, vec![0;32]))).unwrap();
140                } else {
141                    panic!("Should not happen")
142                }
143            }
144            MidlevelEvent::Element(x) => {
145                self.w.write(&generate(&x)).unwrap();
146            }
147            MidlevelEvent::LeaveElement(_) => { 
148            }
149            MidlevelEvent::Content(_) => {
150            }
151            MidlevelEvent::Resync => {
152                self.w.write(&generate(&el_bin(Class::Void, b"\nHere was resync\n".to_vec()))).unwrap();
153            }
154        }
155    }
156}