Matroska-Solution / MediaContainers.Matroska / EBML / EBMLDocumentReader.cs
Code · 60 lines · 1998 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Xtremegaida.DataStructures;

namespace MediaContainers;

public sealed class EBMLDocumentReader : IDisposable
{
	private readonly EBMLReader reader;

	public EBMLHeader Header { get; private set; }
	public EBMLMasterElement Body { get; private set; }
	public EBMLReader Reader => reader;

	private EBMLDocumentReader(EBMLReader reader, EBMLHeader header, EBMLMasterElement body)
	{
		this.reader = reader;
		Header = header;
		Body = body;
	}

	public bool CanBeReadBy(EBMLDocType type)
	{
		return type.CanReadDocument(Header);
	}

	private static async ValueTask<EBMLDocumentReader> Read(EBMLHeader header, EBMLReader reader, CancellationToken cancellationToken = default)
	{
		if (!EBMLDocTypeLookup.HandleEBMLDocType(header, reader))
		{
			throw new Exception("Unrecognised EBML doctype: " + header.DocType + " version " + header.DocTypeVersion);
		}
		var body = await reader.ReadNextElement(true, cancellationToken) as EBMLMasterElement;
		if (body == null) { throw new Exception("Expected a master element as document body"); }
		return new EBMLDocumentReader(reader, header, body);
	}

	public static async ValueTask<EBMLDocumentReader> Read(IDataQueueReader reader, bool keepReaderOpen = false,
	   DataBufferCache cache = null, CancellationToken cancellationToken = default)
	{
		var header = await EBMLHeader.Read(reader, cache, cancellationToken);
		var ebml = new EBMLReader(reader, keepReaderOpen, cache);
		return await Read(header, ebml, cancellationToken);
	}

	public static async ValueTask<EBMLDocumentReader> Read(Stream stream, bool keepStreamOpen = false,
	   DataBufferCache cache = null, CancellationToken cancellationToken = default)
	{
		var header = await EBMLHeader.Read(stream, cache, cancellationToken);
		var ebml = new EBMLReader(stream, keepStreamOpen, cache);
		return await Read(header, ebml, cancellationToken);
	}

	public void Dispose()
	{
		reader.Dispose();
	}
}