Replace Schema types with a FromEbml trait on the Element type

simplify lifetimes
This commit is contained in:
Tangent 128 2018-03-25 21:33:38 -04:00
parent 972a88c35b
commit cdcff869aa
7 changed files with 48 additions and 49 deletions

View File

@ -4,9 +4,7 @@ use std::env::args;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use lab_ebml::Schema;
use lab_ebml::webm::SimpleBlock;
use lab_ebml::webm::Webm;
use lab_ebml::webm::{ parse_webm, SimpleBlock };
use lab_ebml::webm::WebmElement::*;
pub fn main() {
@ -19,7 +17,7 @@ pub fn main() {
file.read_to_end(&mut buffer).expect("Reading file contents");
for element in Webm.parse(buffer.as_slice()) {
for element in parse_webm(buffer.as_slice()) {
match element {
// suppress printing byte arrays
Tracks(slice) => println!("Tracks[{}]", slice.len()),

View File

@ -5,7 +5,6 @@ extern crate lab_ebml;
use futures::future::FutureResult;
use futures::stream::{iter, Stream};
use lab_ebml::chunk::{Chunk, WebmStream, ChunkingError};
use lab_ebml::Schema;
use lab_ebml::timecode_fixer::ChunkStream;
use lab_ebml::webm::*;
use hyper::{Get, StatusCode};
@ -29,9 +28,9 @@ impl Service for WebmServer {
fn call(&self, req: Request) -> Self::Future {
let response = match (req.method(), req.path()) {
(&Get, "/loop") => {
let stream: BodyStream<Vec<u8>> = iter(Webm.parse(SRC_FILE).into_iter().map(|x| Ok(x)))
let stream: BodyStream<Vec<u8>> = iter(parse_webm(SRC_FILE).into_iter().map(|x| Ok(x)))
.chunk_webm()
.chain(iter(Webm.parse(SRC_FILE).into_iter().map(|x| Ok(x))).chunk_webm())
.chain(iter(parse_webm(SRC_FILE).into_iter().map(|x| Ok(x))).chunk_webm())
.fix_timecodes()
.map_err(|err| match err {
ChunkingError::IoError(io_err) => hyper::Error::Io(io_err),

View File

@ -1,7 +1,6 @@
extern crate lab_ebml;
use std::io::{Cursor, stdout, Write};
use lab_ebml::Schema;
use lab_ebml::webm::*;
use lab_ebml::webm::WebmElement::*;
use lab_ebml::timecode_fixer::TimecodeFixer;
@ -15,7 +14,7 @@ pub fn main() {
let mut reading_head = true;
for element in Webm.parse(SRC_FILE) {
for element in parse_webm(SRC_FILE) {
match element {
Cluster => reading_head = false,
// TODO: skip elements not required for streaming

View File

@ -2,6 +2,7 @@ use bytes::{BigEndian, ByteOrder, BufMut};
use std::error::Error as ErrorTrait;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::{Cursor, Error as IoError, ErrorKind, Result as IoResult, Write, Seek, SeekFrom};
use std::marker::PhantomData;
pub const EBML_HEAD_ID: u64 = 0x0A45DFA3;
pub const DOC_TYPE_ID: u64 = 0x0282;
@ -214,20 +215,21 @@ pub fn encode_integer<T: Write>(tag: u64, value: u64, output: &mut T) -> IoResul
}
#[derive(Debug, PartialEq)]
pub struct Ebml<S, T>(pub S, pub T);
pub struct Ebml<Source, Element> {
pub source: Source,
_marker: PhantomData<fn() -> Element>
}
pub trait Schema<'a> {
type Element: 'a;
pub trait FromEbml<'b>: Sized {
fn should_unwrap(element_id: u64) -> bool;
fn decode(element_id: u64, bytes: &'b[u8]) -> Result<Self, Error>;
fn should_unwrap(&self, element_id: u64) -> bool;
fn decode<'b: 'a>(&self, element_id: u64, bytes: &'b[u8]) -> Result<Self::Element, Error>;
fn decode_element<'b: 'a>(&self, bytes: &'b[u8]) -> Result<Option<(Self::Element, usize)>, Error> {
fn decode_element(bytes: &'b[u8]) -> Result<Option<(Self, usize)>, Error> {
match decode_tag(bytes) {
Ok(None) => Ok(None),
Err(err) => Err(err),
Ok(Some((element_id, payload_size_tag, tag_size))) => {
let should_unwrap = self.should_unwrap(element_id);
let should_unwrap = Self::should_unwrap(element_id);
let payload_size = match (should_unwrap, payload_size_tag) {
(true, _) => 0,
@ -241,7 +243,7 @@ pub trait Schema<'a> {
return Ok(None);
}
match self.decode(element_id, &bytes[tag_size..element_size]) {
match Self::decode(element_id, &bytes[tag_size..element_size]) {
Ok(element) => Ok(Some((element, element_size))),
Err(error) => Err(error)
}
@ -249,8 +251,11 @@ pub trait Schema<'a> {
}
}
fn parse<T>(self, source: T) -> Ebml<Self, T> where Self: Sized {
Ebml(self, source)
fn parse<T>(source: T) -> Ebml<T, Self> {
Ebml {
source: source,
_marker: PhantomData
}
}
}
@ -398,21 +403,17 @@ mod tests {
assert_eq!(decode_uint(&[0x80,0,0,0,0,0,0,1]), Ok(9223372036854775809));
}
struct Dummy;
#[derive(Debug, PartialEq)]
struct GenericElement(u64, usize);
impl<'a> Schema<'a> for Dummy {
type Element = GenericElement;
fn should_unwrap(&self, element_id: u64) -> bool {
impl<'a> FromEbml<'a> for GenericElement {
fn should_unwrap(element_id: u64) -> bool {
match element_id {
_ => false
}
}
fn decode<'b: 'a>(&self, element_id: u64, bytes: &'b[u8]) -> Result<GenericElement, Error> {
fn decode(element_id: u64, bytes: &'a[u8]) -> Result<GenericElement, Error> {
match element_id {
_ => Ok(GenericElement(element_id, bytes.len()))
}
@ -421,7 +422,7 @@ mod tests {
#[test]
fn decode_sanity_test() {
let decoded = Dummy.decode_element(TEST_FILE);
let decoded = GenericElement::decode_element(TEST_FILE);
assert_eq!(decoded, Ok(Some((GenericElement(0x0A45DFA3, 31), 43))));
}
}

View File

@ -1,30 +1,31 @@
use std::marker::PhantomData;
use ebml::*;
pub struct EbmlIterator<'b, T: Schema<'b>> {
schema: T,
pub struct EbmlIterator<'b, T: FromEbml<'b>> {
slice: &'b[u8],
position: usize,
_marker: PhantomData<fn() -> T>
}
impl<'b, S: Schema<'b>> IntoIterator for Ebml<S, &'b[u8]> {
type Item = S::Element;
type IntoIter = EbmlIterator<'b, S>;
impl<'b, E: FromEbml<'b>> IntoIterator for Ebml<&'b[u8], E> {
type Item = E;
type IntoIter = EbmlIterator<'b, E>;
fn into_iter(self) -> EbmlIterator<'b, S>
fn into_iter(self) -> EbmlIterator<'b, E>
{
EbmlIterator {
schema: self.0,
slice: self.1,
position: 0
slice: self.source,
position: 0,
_marker: PhantomData
}
}
}
impl<'b, T: Schema<'b>> Iterator for EbmlIterator<'b, T> {
type Item = T::Element;
impl<'b, T: FromEbml<'b>> Iterator for EbmlIterator<'b, T> {
type Item = T;
fn next(&mut self) -> Option<T::Element> {
match self.schema.decode_element(&self.slice[self.position..]) {
fn next(&mut self) -> Option<T> {
match Self::Item::decode_element(&self.slice[self.position..]) {
Err(_) => None,
Ok(None) => None,
Ok(Some((element, element_size))) => {

View File

@ -8,7 +8,7 @@ mod iterator;
pub mod timecode_fixer;
pub mod webm;
pub use ebml::{Error, Schema};
pub use ebml::{Error, FromEbml};
#[cfg(test)]
mod tests {

View File

@ -10,7 +10,10 @@ const TRACKS_ID: u64 = 0x0654AE6B;
const CLUSTER_ID: u64 = 0x0F43B675;
const TIMECODE_ID: u64 = 0x67;
const SIMPLE_BLOCK_ID: u64 = 0x23;
pub struct Webm;
pub fn parse_webm<'a, T: 'a>(source: T) -> Ebml<T, WebmElement<'a>> {
WebmElement::parse(source)
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct SimpleBlock<'b> {
@ -35,10 +38,8 @@ pub enum WebmElement<'b> {
Unknown(u64)
}
impl<'a> Schema<'a> for Webm {
type Element = WebmElement<'a>;
fn should_unwrap(&self, element_id: u64) -> bool {
impl<'b> FromEbml<'b> for WebmElement<'b> {
fn should_unwrap(element_id: u64) -> bool {
match element_id {
// Segment
SEGMENT_ID => true,
@ -47,7 +48,7 @@ impl<'a> Schema<'a> for Webm {
}
}
fn decode<'b: 'a>(&self, element_id: u64, bytes: &'b[u8]) -> Result<WebmElement<'b>, Error> {
fn decode(element_id: u64, bytes: &'b[u8]) -> Result<WebmElement<'b>, Error> {
match element_id {
EBML_HEAD_ID => Ok(WebmElement::EbmlHead),
VOID_ID => Ok(WebmElement::Void),
@ -131,7 +132,7 @@ mod tests {
#[test]
fn decode_webm_test1() {
let mut iter = Webm.parse(TEST_FILE).into_iter();
let mut iter = parse_webm(TEST_FILE).into_iter();
// test that we match the structure of the test file
assert_eq!(iter.next(), Some(WebmElement::EbmlHead));