private DecoderMetadataBuilder ReadDecoder() { var decoder = new DecoderMetadataBuilder(); var mainByte = ReadByte(); if ((mainByte & 0x80) != 0) { throw new NotImplementedException(); } var idLen = (mainByte & 0x0F); if (idLen > 4) { throw new InvalidDataException(); // all known decoders use 4 bytes or less } int id = 0; for (int i = idLen - 1; i >= 0; i--) { id |= ReadByte() << (i * 8); } decoder.Method = CompressionMethod.TryDecode(id); if (decoder.Method.IsUndefined) { throw new InvalidDataException(); // unknown decoder } if ((mainByte & 0x10) != 0) { decoder.InputCount = ReadNumberAsInt32(); decoder.OutputCount = ReadNumberAsInt32(); } else { decoder.InputCount = 1; decoder.OutputCount = 1; } decoder.Method.CheckInputOutputCount(decoder.InputCount, decoder.OutputCount); decoder.InputInfo = ImmutableArray.CreateBuilder <DecoderInputMetadata>(decoder.InputCount); // We need to fill the array because it is not guaranteed that inputs will be connected in order. // No valid decoder can have Int32.MaxValue inputs so we can use this as a placeholder value to detect bugs. var placeholder = new DecoderInputMetadata(Int32.MaxValue, Int32.MaxValue); for (int i = 0; i < decoder.InputCount; i++) { decoder.InputInfo.Add(placeholder); } if ((mainByte & 0x20) != 0) { var settingsLength = ReadNumberAsInt32(); var settingsBuilder = ImmutableArray.CreateBuilder <byte>(settingsLength); for (int i = 0; i < settingsLength; i++) { settingsBuilder.Add(ReadByte()); } decoder.Settings = settingsBuilder.MoveToImmutable(); } else { decoder.Settings = ImmutableArray <byte> .Empty; } return(decoder); }