예제 #1
0
        public void should_be_able_to_take_a_buffer_from_the_current_position()
        {
            BufferStream sut = new BufferStream();
            List<ArraySegment<byte>> segments = new List<ArraySegment<byte>>();
            for (int i = 0; i < 10; i++)
            {
                segments.Add(GetSegment(new byte[16], 512, 1024));
            }
            sut.Initialize(segments);

            // pre-condition
            Assert.AreEqual(0, sut.Position);

            sut.Position += 24;

            // act
            var actual = sut.Take(36);

            var totalLength = actual.Sum(segment => segment.Count);

            // assert
            Assert.IsNotNull(actual);
            Assert.AreEqual(36, totalLength);
            // TODO: check if the data is correct
        }
예제 #2
0
        public BufferStream_tests()
        {
            outputStream = new MemoryStream();
            context = new Mock<HttpContextBase>();
            pageHelper = new Mock<IPageHelper>();

            pageHelper.Setup(h => h.ReplacePlaceholders(It.IsAny<string>()))
                      .Returns<string>(s => s);

            context.SetupGet(c => c.Response.ContentType).Returns("text/html");
            context.SetupGet(c => c.Response.Output.Encoding).Returns(Encoding.ASCII);

            buffer = new BufferStream(outputStream, context.Object, pageHelper.Object);
        }
예제 #3
0
        public void should_be_able_to_read_a_byte_and_the_position_should_be_advanced_by_one()
        {
            BufferStream sut = new BufferStream();
            sut.Initialize(new[] { GetSegment(new byte[] { 0x01, 0x02 }, 512, 1024) });

            // pre-condition
            Assert.AreEqual(2, sut.Length);
            Assert.AreEqual(0, sut.Position);

            // act
            var first = sut.ReadByte();

            // assert
            Assert.AreEqual(1, first);
            Assert.AreEqual(1, sut.Position);
        }
예제 #4
0
        public void should_be_able_to_read_a_single_byte()
        {
            byte expected = 0x01;

            BufferStream sut = new BufferStream();
            sut.Initialize(new[] { GetSegment(new byte[] { expected }, 123, 1024) });

            // pre-condition
            Assert.AreEqual(1, sut.Length);
            Assert.AreEqual(0, sut.Position);
            
            // act
            var actual = sut.ReadByte();

            // assert
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(1, sut.Position);
        }
예제 #5
0
        public void should_be_able_to_get_correct_position()
        {
            var data = Encoding.UTF8.GetBytes("SuperSocket rocks!");
            var segments = new List<ArraySegment<byte>>();
            segments.Add(new ArraySegment<byte>(data));

            using (var BufferStream = new BufferStream())
            {
                BufferStream.Initialize(segments);

                Assert.AreEqual(data.Length, BufferStream.Length);
                Assert.AreEqual(0, BufferStream.Position);

                BufferStream.Seek(1, SeekOrigin.Begin);
                Assert.AreEqual(1, BufferStream.Position);

                BufferStream.Seek(1, SeekOrigin.Current);
                Assert.AreEqual(2, BufferStream.Position);

                BufferStream.Seek(data.Length - 1, SeekOrigin.Begin);
                Assert.AreEqual(data.Length - 1, BufferStream.Position);
            }

        }
예제 #6
0
        public void should_be_able_to_read_a_string_from_one_segment()
        {
            string expected = "The quick brown fox jumps over the lazy dog";
            var encoding = Encoding.ASCII;

            var bytes = encoding.GetBytes(expected);

            ArraySegment<byte> segment = new ArraySegment<byte>(bytes);

            BufferStream sut = new BufferStream();
            sut.Initialize(new[] { segment });

            // act
            var actual = sut.ReadString(expected.Length, encoding);

            // assert
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, sut.Position);
        }
예제 #7
0
        public void should_be_able_to_read_a_string_from_segments()
        {
            string expected = "The quick brown fox jumps over the lazy dog";

            BufferStream sut = new BufferStream();
            sut.Initialize(GetSegments(expected, Encoding.ASCII, 2));

            // pre-condition
            Assert.AreEqual(expected.Length, sut.Length);

            var actual = sut.ReadString(expected.Length, Encoding.ASCII);

            // assert
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, sut.Position);
        }
 protected virtual void SendInternal(BufferStream Buffer)
 {
     AddSendCommand(new SendCommand(Buffer, Timestamp));
 }
예제 #9
0
        public static OJN Decode(string filename)
        {
            if (!File.Exists(filename))
            {
                throw new FileNotFoundException("OJN File not found", filename);
            }

            if (!Check(filename))
            {
                throw new FormatException("Invalid O2Jam Chart.");
            }

            var ojn = DecodeHeader(filename);

            using (var stream = new BufferStream(filename))
            {
                ojn.Events = new Dictionary <OJN.Difficulty, Event[]>();
                foreach (var difficulty in Enum.GetValues(typeof(OJN.Difficulty)) as OJN.Difficulty[])
                {
                    if (difficulty == OJN.Difficulty.MX)
                    {
                        continue;
                    }

                    var events = new List <Event>();
                    int offset = ojn.BlockOffset[difficulty];
                    int count  = ojn.BlockCount[difficulty];

                    stream.Seek(offset, SeekOrigin.Begin);
                    for (int block = 0; block < count; block++)
                    {
                        var ev = new Event
                        {
                            Measure   = stream.ReadInt32(),
                            LaneIndex = stream.ReadInt16(),
                            Tempo     = stream.ReadInt16()
                        };

                        // We don't convert the lane index directly to channel, we keep them both
                        // This allow the Event class to be usable for various number of channels (e.g: 3key / 5key / 10key)
                        // The decoder is responsible to convert this index into correct channel enum
                        // Lane Index then still preserved, this might needed in certain cases such as encoding the chart back to the file or identify the lane index of BGM.
                        // While channel may make judgement and rendering process easier by distinguish event types between playable and background events
                        ev.Channel = ev.LaneIndex > (int)Event.ChannelType.Note7 ? Event.ChannelType.BGM : (Event.ChannelType)ev.LaneIndex;

                        for (int i = 0; i < ev.Tempo; i++)
                        {
                            ev.Beat = (int)(i * (192f / ev.Tempo));
                            ev.Cell = i;

                            if (ev.Channel == Event.ChannelType.BPM ||
                                ev.Channel == Event.ChannelType.Measurement)
                            {
                                var time = new Event.Time(ev)
                                {
                                    Value = stream.ReadSingle()
                                };

                                if (time.Value != 0)
                                {
                                    events.Add(time);
                                }
                            }
                            else
                            {
                                int refId = stream.ReadInt16();
                                if ((int)ev.Channel < 0 || refId <= 0)
                                {
                                    stream.Seek(2, SeekOrigin.Current);
                                    continue;
                                }

                                int audio = stream.ReadByte();
                                int flag  = stream.ReadByte();
                                var type  = (Event.SignatureType)flag;

                                float volume = ((audio >> 4) & 0x0F);
                                volume = volume == 0 ? 100 : ((volume / 16f) * 100f);

                                float pan = (audio & 0x0F);
                                if (pan == 0)
                                {
                                    pan = 8;
                                }
                                pan = ((pan - 8) / 8f) * 100;

                                int id     = (refId - 1) + (flag % 8 > 3 ? 1000 : 0);
                                var sample = new Event.Sound(ev)
                                {
                                    Id        = id,
                                    Signature = type,
                                    Pan       = pan,
                                    Volume    = volume
                                };


                                events.Add(sample);
                            }
                        }
                    }

                    // Long Note Pairing
                    foreach (var ev in events.FindAll((e) => e is Event.Sound && e.Signature == Event.SignatureType.Hold))
                    {
                        var sln = ev as Event.Sound;
                        var eln = events.Find((e) =>
                        {
                            var se = e as Event.Sound;
                            return(se != null &&
                                   se.Pair == null &&
                                   se.Signature == Event.SignatureType.Release &&
                                   se.Channel == sln.Channel);
                        }) as Event.Sound;

                        if (eln != null)
                        {
                            sln.Pair = eln;
                            eln.Pair = sln;
                        }
                    }

                    // Clean up
                    events.RemoveAll((e) => {
                        var se = e as Event.Sound;
                        return(se != null && ((se.Signature == Event.SignatureType.Hold && se.Pair == null) /*|| se.Signature == Event.SignatureType.Release*/));
                    });

                    // Sort event based on offset
                    events.Sort((a, b) => a.Offset.CompareTo(b.Offset));

                    // Calculate Timestamp
                    var timeEvents = events.FindAll((e) => e.Channel == Event.ChannelType.BPM);
                    for (int i = 0; i < events.Count; i++)
                    {
                        var ev = events[i] as Event.Sound;
                        if (ev == null)
                        {
                            continue;
                        }

                        double bpm         = ojn.BPM;
                        double timeOffset  = 0;
                        double bpmPosition = 0;
                        foreach (var time in timeEvents)
                        {
                            if (time.Offset < ev.Offset)
                            {
                                timeOffset += ((time.Offset - bpmPosition) / (192f / 4f)) * (60f / bpm);

                                bpm         = ((Event.Time)time).Value;
                                bpmPosition = time.Offset;
                            }
                            else if (time.Offset > ev.Offset)
                            {
                                break;
                            }
                        }

                        var timestamp = TimeSpan.FromSeconds(timeOffset + (((ev.Offset - bpmPosition) / (192f / 4f)) * (60f / bpm)));;
                        events[i] = new Event.Sound(ev, timestamp);
                    }

                    ojn.Events[difficulty] = events.ToArray();
                }

                return(ojn);
            }
        }
예제 #10
0
        public void should_be_able_to_read_an_integer(bool littleEndian, byte[] bytes, long expected)
        {
            List<ArraySegment<byte>> segments = new List<ArraySegment<byte>>();
            segments.Add(new ArraySegment<byte>(bytes));
            BufferStream sut = new BufferStream();
            sut.Initialize(segments);

            // act
            var actual = sut.ReadInt32(littleEndian);

            // assert
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(4, sut.Position);
        }
예제 #11
0
        public void should_be_able_to_read_an_unsigned_long_integer(bool littleEndian, byte[] bytes, ulong expected)
        {
            List<ArraySegment<byte>> segments = new List<ArraySegment<byte>>();
            segments.Add(new ArraySegment<byte>(bytes));
            BufferStream sut = new BufferStream();
            sut.Initialize(segments);

            // act
            ulong actual = sut.ReadUInt64(littleEndian);

            // assert
            Assert.AreEqual(8, bytes.Length);
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(8, sut.Position);
        }
예제 #12
0
        private static T FromStream <T>(Stream stream)
            where T : ItemBase <T>
        {
            try
            {
                using (var targetStream = new RangeStream(stream, true))
                {
                    using (Stream verifyStream = new RangeStream(targetStream, 0, targetStream.Length - 4, true))
                    {
                        byte[] verifyCrc  = Crc32_Castagnoli.ComputeHash(verifyStream);
                        byte[] orignalCrc = new byte[4];

                        using (RangeStream crcStream = new RangeStream(targetStream, targetStream.Length - 4, 4, true))
                        {
                            crcStream.Read(orignalCrc, 0, orignalCrc.Length);
                        }

                        if (!Unsafe.Equals(verifyCrc, orignalCrc))
                        {
                            throw new ArgumentException("Crc Error");
                        }
                    }

                    targetStream.Seek(0, SeekOrigin.Begin);
                    byte type = (byte)targetStream.ReadByte();

                    using (Stream dataStream = new RangeStream(targetStream, targetStream.Position, targetStream.Length - targetStream.Position - 4, true))
                    {
                        if (type == (byte)ConvertCompressionAlgorithm.None)
                        {
                            return(ItemBase <T> .Import(dataStream, _bufferManager));
                        }
                        else if (type == (byte)ConvertCompressionAlgorithm.Deflate)
                        {
                            using (BufferStream deflateBufferStream = new BufferStream(_bufferManager))
                            {
                                byte[] decompressBuffer = null;

                                try
                                {
                                    decompressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                    using (DeflateStream deflateStream = new DeflateStream(dataStream, CompressionMode.Decompress, true))
                                    {
                                        int i = -1;

                                        while ((i = deflateStream.Read(decompressBuffer, 0, decompressBuffer.Length)) > 0)
                                        {
                                            deflateBufferStream.Write(decompressBuffer, 0, i);
                                        }
                                    }
                                }
                                finally
                                {
                                    if (decompressBuffer != null)
                                    {
                                        _bufferManager.ReturnBuffer(decompressBuffer);
                                    }
                                }

#if DEBUG
                                Debug.WriteLine("OutoposConverter FromStream : {0}→{1} {2}",
                                                NetworkConverter.ToSizeString(dataStream.Length),
                                                NetworkConverter.ToSizeString(deflateBufferStream.Length),
                                                NetworkConverter.ToSizeString(dataStream.Length - deflateBufferStream.Length));
#endif

                                deflateBufferStream.Seek(0, SeekOrigin.Begin);

                                return(ItemBase <T> .Import(deflateBufferStream, _bufferManager));
                            }
                        }
                        else
                        {
                            throw new ArgumentException("ArgumentException");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
예제 #13
0
 public void should_not_be_able_to_skip_backwards()
 {
     BufferStream sut = new BufferStream();
     sut.Initialize(new[] { GetSegment(new byte[] { 0x01, 0x02, 0x03, 0x04 }, 123, 1024) });
     sut.Position = 1;
     sut.Skip(-1);
 }
예제 #14
0
        private static Stream Decrypt(Stream stream, IExchangeDecrypt privateKey)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (privateKey == null)
            {
                throw new ArgumentNullException("privateKey");
            }

            try
            {
                byte type = (byte)stream.ReadByte();

                if (type == (byte)ConvertCryptoAlgorithm.Aes256)
                {
                    byte[] cryptoKey;

                    {
                        byte[] lengthBuffer = new byte[4];
                        if (stream.Read(lengthBuffer, 0, lengthBuffer.Length) != lengthBuffer.Length)
                        {
                            throw new ArgumentException();
                        }
                        int length = NetworkConverter.ToInt32(lengthBuffer);

                        byte[] encryptedBuffer = new byte[length];
                        if (stream.Read(encryptedBuffer, 0, encryptedBuffer.Length) != encryptedBuffer.Length)
                        {
                            throw new ArgumentException();
                        }

                        cryptoKey = Exchange.Decrypt(privateKey, encryptedBuffer);
                    }

                    BufferStream outStream = null;

                    try
                    {
                        outStream = new BufferStream(_bufferManager);

                        using (Stream dataStream = new WrapperStream(stream, true))
                        {
                            var iv = new byte[32];
                            dataStream.Read(iv, 0, iv.Length);

                            using (var rijndael = new RijndaelManaged()
                            {
                                KeySize = 256, BlockSize = 256, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7
                            })
                                using (var inStream = new RangeStream(dataStream, dataStream.Position, dataStream.Length - dataStream.Position))
                                    using (CryptoStream cs = new CryptoStream(inStream, rijndael.CreateDecryptor(cryptoKey, iv), CryptoStreamMode.Read))
                                    {
                                        byte[] buffer = null;

                                        try
                                        {
                                            buffer = _bufferManager.TakeBuffer(1024 * 4);

                                            int i = -1;

                                            while ((i = cs.Read(buffer, 0, buffer.Length)) > 0)
                                            {
                                                outStream.Write(buffer, 0, i);
                                            }
                                        }
                                        finally
                                        {
                                            _bufferManager.ReturnBuffer(buffer);
                                        }
                                    }
                        }

                        outStream.Seek(0, SeekOrigin.Begin);
                    }
                    catch (Exception)
                    {
                        if (outStream != null)
                        {
                            outStream.Dispose();
                        }

                        throw;
                    }

                    return(outStream);
                }

                throw new NotSupportedException();
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
예제 #15
0
        private static Stream Compress(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            var targetStream = new RangeStream(stream, true);

            List <KeyValuePair <byte, Stream> > list = new List <KeyValuePair <byte, Stream> >();

            try
            {
                targetStream.Seek(0, SeekOrigin.Begin);

                BufferStream deflateBufferStream = null;

                try
                {
                    deflateBufferStream = new BufferStream(_bufferManager);

                    using (DeflateStream deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                    {
                        byte[] compressBuffer = null;

                        try
                        {
                            compressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                            int i = -1;

                            while ((i = targetStream.Read(compressBuffer, 0, compressBuffer.Length)) > 0)
                            {
                                deflateStream.Write(compressBuffer, 0, i);
                            }
                        }
                        finally
                        {
                            if (compressBuffer != null)
                            {
                                _bufferManager.ReturnBuffer(compressBuffer);
                            }
                        }
                    }

                    deflateBufferStream.Seek(0, SeekOrigin.Begin);

                    list.Add(new KeyValuePair <byte, Stream>((byte)ConvertCompressionAlgorithm.Deflate, deflateBufferStream));
                }
                catch (Exception)
                {
                    if (deflateBufferStream != null)
                    {
                        deflateBufferStream.Dispose();
                    }
                }
            }
            catch (Exception)
            {
            }

            list.Add(new KeyValuePair <byte, Stream>((byte)ConvertCompressionAlgorithm.None, targetStream));

            list.Sort((x, y) =>
            {
                int c = x.Value.Length.CompareTo(y.Value.Length);
                if (c != 0)
                {
                    return(c);
                }

                return(x.Key.CompareTo(y.Key));
            });

#if DEBUG
            if (list[0].Value.Length != targetStream.Length)
            {
                Debug.WriteLine("ContentConverter Compress {3} : {0}→{1} {2}",
                                NetworkConverter.ToSizeString(targetStream.Length),
                                NetworkConverter.ToSizeString(list[0].Value.Length),
                                NetworkConverter.ToSizeString(list[0].Value.Length - targetStream.Length),
                                (ConvertCompressionAlgorithm)list[0].Key);
            }
#endif

            for (int i = 1; i < list.Count; i++)
            {
                list[i].Value.Dispose();
            }

            BufferStream metadataStream = new BufferStream(_bufferManager);
            metadataStream.WriteByte((byte)list[0].Key);

            return(new UniteStream(metadataStream, list[0].Value));
        }
예제 #16
0
        private static Stream Encrypt(Stream stream, IExchangeEncrypt publicKey)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (publicKey == null)
            {
                throw new ArgumentNullException("publicKey");
            }

            try
            {
                BufferStream outStream = null;

                try
                {
                    outStream = new BufferStream(_bufferManager);
                    outStream.WriteByte((byte)ConvertCryptoAlgorithm.Aes256);

                    byte[] cryptoKey = new byte[32];
                    _random.GetBytes(cryptoKey);

                    {
                        var encryptedBuffer = Exchange.Encrypt(publicKey, cryptoKey);
                        outStream.Write(NetworkConverter.GetBytes((int)encryptedBuffer.Length), 0, 4);
                        outStream.Write(encryptedBuffer, 0, encryptedBuffer.Length);
                    }

                    byte[] iv = new byte[32];
                    _random.GetBytes(iv);
                    outStream.Write(iv, 0, iv.Length);

                    using (Stream inStream = new WrapperStream(stream, true))
                    {
                        using (var rijndael = new RijndaelManaged()
                        {
                            KeySize = 256, BlockSize = 256, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7
                        })
                            using (CryptoStream cs = new CryptoStream(inStream, rijndael.CreateEncryptor(cryptoKey, iv), CryptoStreamMode.Read))
                            {
                                byte[] buffer = null;

                                try
                                {
                                    buffer = _bufferManager.TakeBuffer(1024 * 4);

                                    int i = -1;

                                    while ((i = cs.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        outStream.Write(buffer, 0, i);
                                    }
                                }
                                finally
                                {
                                    if (buffer != null)
                                    {
                                        _bufferManager.ReturnBuffer(buffer);
                                    }
                                }
                            }
                    }

                    outStream.Seek(0, SeekOrigin.Begin);
                }
                catch (Exception)
                {
                    if (outStream != null)
                    {
                        outStream.Dispose();
                    }

                    throw;
                }

                return(outStream);
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
예제 #17
0
        private static Stream Decompress(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            try
            {
                var targetStream = new RangeStream(stream, true);

                byte type = (byte)targetStream.ReadByte();

                if (type == (byte)ConvertCompressionAlgorithm.None)
                {
                    return(new RangeStream(targetStream));
                }
                else if (type == (byte)ConvertCompressionAlgorithm.Deflate)
                {
                    using (Stream dataStream = new WrapperStream(targetStream, true))
                    {
                        BufferStream deflateBufferStream = null;

                        try
                        {
                            deflateBufferStream = new BufferStream(_bufferManager);

                            using (DeflateStream deflateStream = new DeflateStream(dataStream, CompressionMode.Decompress, true))
                            {
                                byte[] decompressBuffer = null;

                                try
                                {
                                    decompressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                    int i = -1;

                                    while ((i = deflateStream.Read(decompressBuffer, 0, decompressBuffer.Length)) > 0)
                                    {
                                        deflateBufferStream.Write(decompressBuffer, 0, i);
                                    }
                                }
                                finally
                                {
                                    if (decompressBuffer != null)
                                    {
                                        _bufferManager.ReturnBuffer(decompressBuffer);
                                    }
                                }
                            }

                            deflateBufferStream.Seek(0, SeekOrigin.Begin);

#if DEBUG
                            Debug.WriteLine("ContentConverter Decompress {3} : {0}→{1} {2}",
                                            NetworkConverter.ToSizeString(dataStream.Length),
                                            NetworkConverter.ToSizeString(deflateBufferStream.Length),
                                            NetworkConverter.ToSizeString(dataStream.Length - deflateBufferStream.Length),
                                            ConvertCompressionAlgorithm.Deflate);
#endif

                            return(deflateBufferStream);
                        }
                        catch (Exception)
                        {
                            if (deflateBufferStream != null)
                            {
                                deflateBufferStream.Dispose();
                            }
                        }
                    }
                }

                throw new ArgumentException("ArgumentException");
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
예제 #18
0
 public GameModel(BufferStream stream)
 {
     FromStream(stream);
 }
예제 #19
0
        public void should_be_able_to_read_a_string_from_multiple_segments()
        {
            string expected = "The quick brown fox jumps over the lazy dog";
            Encoding encoding = Encoding.ASCII;

            // create n-segments of each word and space
            Random random = new Random(0);

            List<ArraySegment<byte>> segments = new List<ArraySegment<byte>>();
            var words = expected.Split(' ');

            for (int i = 0; i < words.Length; i++)
            {
                if (i != 0)
                {
                    segments.Add(GetSegment(encoding.GetBytes(" "), random.Next(0,256), random.Next(1, 4) * 1024));
                }

                segments.Add(GetSegment(encoding.GetBytes(words[i]), random.Next(0, 256), random.Next(1, 4) * 1024));
            }

            BufferStream sut = new BufferStream();
            sut.Initialize(segments);

            // pre-condition
            Assert.AreEqual(expected.Length, sut.Length);

            string actual = sut.ReadString(expected.Length, encoding);

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, sut.Position);
        }
예제 #20
0
 public void TestStream()
 {          
     var buffer = this.GetBuffer(0);
     var stream = new BufferStream(buffer);
     var bytes = new byte[1024];
     //1048576
     for (var i = 0; i < 1024; i++)
     {
         stream.Write(bytes, 0, bytes.Length);
     }          
     Assert.AreEqual(1048576, stream.Length);
     var readableBytes = 0;
     var count = 0;
     while ((count = stream.Read(bytes, 0, bytes.Length)) > 0)
     {
         readableBytes += count;
     }
     Assert.AreEqual(1048576, readableBytes);
     Assert.AreEqual(buffer.ReaderIndex, buffer.WriterIndex);
 }
예제 #21
0
        public void should_be_able_to_call_skip_to_advance_the_position()
        {
            BufferStream sut = new BufferStream();
            sut.Initialize(new[] { GetSegment(new byte[] { 0x01 }, 123, 1024) });

            // pre-condition
            Assert.AreEqual(1, sut.Length);

            // act
            var actual = sut.Skip(1);
            
            // assert
            Assert.NotNull(actual);
            Assert.AreEqual(1, sut.Position);
        }
예제 #22
0
        public static byte[] Encode(OJM.OMC omc)
        {
            using (var stream = new BufferStream())
            {
                stream.Write("OMC\0");
                stream.Write(omc.WaveCount);
                stream.Write(omc.OggCount);
                stream.Write(omc.WaveOffset);
                stream.Write(omc.OggOffset);
                stream.Write(omc.FileSize);

                stream.Seek(omc.WaveOffset, SeekOrigin.Begin);
                for (short i = 0; i < omc.WaveSamples.Max((sample) => sample.Value.Id); i++)
                {
                    OJM.OMC.WaveSample sample = null;
                    string             name   = string.Empty.PadNull(32);
                    short audioFormat         = 0;
                    short channelCount        = 0;
                    int   sampleRate          = 0;
                    int   bitrate             = 0;
                    short blockAlign          = 0;
                    short bitsPerSample       = 0;
                    int   unkData             = 0;
                    int   size = 0;

                    if (omc.WaveSamples.ContainsKey(i))
                    {
                        sample        = omc.WaveSamples[i];
                        name          = sample.Name.PadNull(32);
                        audioFormat   = sample.AudioFormat;
                        channelCount  = sample.ChannelCount;
                        sampleRate    = sample.SampleRate;
                        bitrate       = sample.Bitrate;
                        blockAlign    = sample.BlockAlign;
                        bitsPerSample = sample.BitsPerSample;
                        unkData       = sample.UnkData;
                        size          = sample.Size;
                    }

                    stream.Write(name);
                    stream.Write(audioFormat);
                    stream.Write(channelCount);
                    stream.Write(sampleRate);
                    stream.Write(bitrate);
                    stream.Write(blockAlign);
                    stream.Write(bitsPerSample);
                    stream.Write(unkData);
                    stream.Write(size);

                    if (sample != null && size > 0)
                    {
                        byte[] payload = sample.Payload;
                        var    info    = EncodeTo <WavEncoder>(payload);

                        sample.Payload = payload;
                        using (var waveStream = new BufferStream(payload))
                        {
                            waveStream.Seek(44, SeekOrigin.Begin);
                            stream.Write(EncodeWave(waveStream.ReadRemaining()));
                        }
                    }
                }

                stream.Seek(omc.OggOffset, SeekOrigin.Begin);
                for (short i = 1000; i < omc.OggSamples.Max((sample) => sample.Value.Id); i++)
                {
                    var sample = omc.OggSamples.ContainsKey(i) ? omc.OggSamples[i] : null;
                    if (sample == null)
                    {
                        continue;
                    }

                    stream.Write(sample.Name.PadNull(32));


                    if (sample.Size > 0)
                    {
                        byte[] payload = sample.Payload;
                        EncodeTo <OggEncoder>(payload);
                        sample.Payload = payload;


                        stream.Write(sample.Size);
                        stream.Write(payload);
                    }
                }

                return(stream.ToArray());
            }
        }
예제 #23
0
        public void should_be_able_to_skip_to_the_end_of_all_the_buffers()
        {
            int segmentSize = 16;
            BufferStream sut = new BufferStream();
            List<ArraySegment<byte>> segments = new List<ArraySegment<byte>>();
            segments.Add(GetSegment(new byte[segmentSize], 512, 1024));
            segments.Add(GetSegment(new byte[segmentSize], 512, 1024));
            sut.Initialize(segments);

            sut.Skip(segmentSize * 2);
        }
        protected override int ProcessIncoming(NetContext context, Connection connection, Stream incoming)
        {
            if (incoming.Length < 2) return 0; // can't read that; frame takes at minimum two bytes

            

            byte[] buffer = null;
            try
            {
                buffer = context.GetBuffer();
                int read;
                // read as much as possible up to 14 bytes; that gives us space for 2 bytes frame header, 8 bytes length, and 4 bytes mask
                read = NetContext.TryFill(incoming, buffer, 14);

                int headerLength;
                var frame = WebSocketsFrame.TryParseFrameHeader(buffer, read, out headerLength);

                if (frame == null) return 0;
                int payloadLen = frame.PayloadLength;

#if VERBOSE
                Debug.WriteLine("Parsed header from: " + BitConverter.ToString(buffer, 0, headerLength));
#endif

                if (incoming.Length < headerLength + payloadLen) return 0; // not enough data to read the payload

                if (payloadLen != 0)
                {
                    Stream payload = null;
                    try
                    {
                        payload = new BufferStream(context, context.Handler.MaxIncomingQuota);
                        if (read != headerLength) incoming.Position -= (read - headerLength); // we got it wrong...

                        Copy(incoming, payload, buffer, frame.Mask, payloadLen);

                        if (payloadLen != payload.Length)
                        {
                            throw new InvalidOperationException("I munged the data");
                        }
                        frame.Payload = payload;
                        payload = null;
                    }
                    finally
                    {
                        if (payload != null) payload.Dispose();
                    }
                }
                foreach (var final in ApplyExtensions(context, connection, frame, true))
                {
                    ProcessFrame(context, connection, final);
                }
                return headerLength + payloadLen;
            }
            finally
            {
                context.Recycle(buffer);
            }
        }
예제 #25
0
        protected override Stream Export(BufferManager bufferManager, int count)
        {
            lock (this.ThisLock)
            {
                BufferStream bufferStream = new BufferStream(bufferManager);

                // Name
                if (this.Name != null)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.Name, this.Name);
                }
                // Length
                if (this.Length != 0)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.Length, this.Length);
                }
                // CreationTime
                if (this.CreationTime != DateTime.MinValue)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.CreationTime, this.CreationTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", System.Globalization.DateTimeFormatInfo.InvariantInfo));
                }
                // Comment
                if (this.Comment != null)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.Comment, this.Comment);
                }
                // Rank
                if (this.Rank != 0)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.Rank, this.Rank);
                }
                // Key
                if (this.Key != null)
                {
                    using (var stream = this.Key.Export(bufferManager))
                    {
                        ItemUtilities.Write(bufferStream, (byte)SerializeId.Key, stream);
                    }
                }

                // Keywords
                foreach (var value in this.Keywords)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.Keyword, value);
                }

                // CompressionAlgorithm
                if (this.CompressionAlgorithm != 0)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.CompressionAlgorithm, this.CompressionAlgorithm.ToString());
                }

                // CryptoAlgorithm
                if (this.CryptoAlgorithm != 0)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.CryptoAlgorithm, this.CryptoAlgorithm.ToString());
                }
                // CryptoKey
                if (this.CryptoKey != null)
                {
                    ItemUtilities.Write(bufferStream, (byte)SerializeId.CryptoKey, this.CryptoKey);
                }

                // Certificate
                if (this.Certificate != null)
                {
                    using (var stream = this.Certificate.Export(bufferManager))
                    {
                        ItemUtilities.Write(bufferStream, (byte)SerializeId.Certificate, stream);
                    }
                }

                bufferStream.Seek(0, SeekOrigin.Begin);
                return(bufferStream);
            }
        }
예제 #26
0
            IEnumerable<WebSocketsFrame> IExtension.ApplyOutgoing(NetContext context, WebSocketConnection connection, WebSocketsFrame frame)
            {
                if (!frame.IsControlFrame && frame.PayloadLength > parent.compressMessagesLargerThanBytes)
                {
                    if (frame.Reserved1)
                    {
                        throw new InvalidOperationException("Reserved1 flag is already set; extension conflict?");
                    }

                    int headerBytes = 0;
                    if (outbound == null)
                    {
                        outbound = new ZStream();
                        const int BITS = 12; // 4096 byte outbound buffer (instead of full 32k=15)
                        outbound.deflateInit(zlibConst.Z_BEST_COMPRESSION, BITS);
                        headerBytes = 2;
                    }
                    BufferStream tmp = null;
                    var payload = frame.Payload;
                    payload.Position = 0;
                    byte[] inBuffer = null, outBuffer = null;
                    try
                    {
                        inBuffer = context.GetBuffer();
                        outBuffer = context.GetBuffer();
                        tmp = new BufferStream(context, 0);

                        outbound.next_out = outBuffer;
                        outbound.next_in = inBuffer;

                        int remaining = frame.PayloadLength;
                        while (remaining > 0)
                        {
                            int readCount = payload.Read(inBuffer, 0, inBuffer.Length);
                            if (readCount <= 0) break;
                            remaining -= readCount;

                            outbound.next_in_index = 0;
                            outbound.avail_in = readCount;

                            do
                            {
                                outbound.next_out_index = 0;
                                outbound.avail_out = outBuffer.Length;
                                long priorOut = outbound.total_out;
                                int err = outbound.deflate(remaining == 0 ? zlibConst.Z_SYNC_FLUSH : zlibConst.Z_NO_FLUSH);
                                if (err != zlibConst.Z_OK && err != zlibConst.Z_STREAM_END)
                                    throw new ZStreamException("deflating: " + outbound.msg);

                                int outCount = (int)(outbound.total_out - priorOut);
                                if (outCount > 0)
                                {
                                    if (headerBytes == 0)
                                    {
                                        tmp.Write(outBuffer, 0, outCount);
                                    }
                                    else
                                    {
                                        if (outCount < headerBytes)
                                        {
                                            throw new InvalidOperationException("Failed to write entire header");
                                        }
                                        // check the generated header meets our expectations
                                        // CMF is very specific - CM must be 8, and CINFO must be <=7 (for 32k window)
                                        if ((outBuffer[0] & 15) != 8)
                                        {
                                            throw new InvalidOperationException("Zlib CM header was incorrect");
                                        }
                                        if ((outBuffer[0] & 128) != 0) // if msb set, is > 7 - invalid
                                        {
                                            throw new InvalidOperationException("Zlib CINFO header was incorrect");
                                        }

                                        // FLG is less important; FCHECK is irrelevent, FLEVEL doesn't matter; but
                                        // FDICT must be zero, to ensure that we aren't expecting a an initialization dictionary
                                        if ((outBuffer[1] & 32) != 0)
                                        {
                                            throw new InvalidOperationException("Zlib FLG.FDICT header was set (must not be)");
                                        }

                                        // skip the header, and write anything else
                                        outCount -= headerBytes;
                                        if (outCount > 0)
                                        {
                                            tmp.Write(outBuffer, headerBytes, outCount);
                                        }
                                        headerBytes = 0; // all written now
                                    }
                                }
                            } while (outbound.avail_in > 0 || outbound.avail_out == 0);
                        }
                        if (remaining != 0) throw new EndOfStreamException();
                        if (headerBytes != 0) throw new InvalidOperationException("Zlib header was not written");

                        // verify the last 4 bytes, then drop them
                        tmp.Position = tmp.Length - 4;
                        NetContext.Fill(tmp, outBuffer, 4);
                        if (!(outBuffer[0] == 0x00 && outBuffer[1] == 0x00 && outBuffer[2] == 0xFF && outBuffer[3] == 0xFF))
                        {
                            throw new InvalidOperationException("expectation failed: 0000FFFF in the tail");
                        }

                        if (parent.disableContextTakeover && tmp.Length >= frame.PayloadLength)
                        { // compressing it didn't do anything useful; since we're going to discard
                          // the compression context, we might as well stick with the original data
                            payload.Position = 0;
                            payload = null; // so that it doesn't get disposed
                        }
                        else
                        {
                            // set our final output
                            tmp.Position = 0;
                            tmp.SetLength(tmp.Length - 4);
                            long bytesSaved = frame.PayloadLength - tmp.Length;
                            frame.Payload = tmp;
                            frame.PayloadLength = (int)tmp.Length;
                            frame.Reserved1 = true;
                            tmp = payload as BufferStream;
                            parent.RegisterOutboundBytesSaved(bytesSaved);
                        }
                    }
#if DEBUG
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex);
                        throw;
                    }
#endif
                    finally
                    {
                        if (outbound != null)
                        {
                            outbound.next_out = null;
                            outbound.next_in = null;
                        }
                        if (tmp != null) tmp.Dispose();
                        if (inBuffer != null) context.Recycle(inBuffer);
                        if (outBuffer != null) context.Recycle(outBuffer);
                        if (parent.disableContextTakeover) ClearContext(false, true);
                    }
                }
                yield return frame;
            }
예제 #27
0
        public void should_be_able_to_advance_the_position_within_current_segment()
        {
            int segmentLength = 16;
            int expectedPosition = segmentLength/2;

            BufferStream sut = new BufferStream();
            sut.Initialize(new[] { GetSegment(new byte[segmentLength], 512, 1024) });

            Assert.AreEqual(0, sut.Position);

            sut.Position += expectedPosition;

            Assert.AreEqual(expectedPosition, sut.Position);
        }
예제 #28
0
        public void Connect()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

            using (DeadlockMonitor.Lock(this.ThisLock))
            {
                try
                {
                    TimeSpan timeout = new TimeSpan(0, 30, 0);

                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();

                    using (BufferStream stream = new BufferStream(_bufferManager))
                        using (XmlTextWriter writer = new XmlTextWriter(stream, new UTF8Encoding(false)))
                        {
                            writer.WriteStartDocument();

                            writer.WriteStartElement("Configuration");

                            if (_myProtocolVersion == ProtocolVersion.Version1)
                            {
                                writer.WriteStartElement("Protocol");
                                writer.WriteAttributeString("Version", "1");

                                writer.WriteEndElement(); //Protocol
                            }

                            writer.WriteEndElement(); //Configuration

                            writer.WriteEndDocument();
                            writer.Flush();
                            stream.Flush();

                            stream.Seek(0, SeekOrigin.Begin);
                            _connection.Send(stream, timeout - stopwatch.Elapsed);
                        }

                    using (Stream stream = _connection.Receive(timeout - stopwatch.Elapsed))
                        using (XmlTextReader reader = new XmlTextReader(stream))
                        {
                            while (reader.Read())
                            {
                                if (reader.NodeType == XmlNodeType.Element)
                                {
                                    if (reader.LocalName == "Protocol")
                                    {
                                        var version = reader.GetAttribute("Version");

                                        if (version == "1")
                                        {
                                            _otherProtocolVersion |= ProtocolVersion.Version1;
                                        }
                                    }
                                }
                            }
                        }

                    _protocolVersion = _myProtocolVersion & _otherProtocolVersion;

                    if (_protocolVersion == ProtocolVersion.Version1)
                    {
                        _lastSendTime = DateTime.UtcNow;

                        ThreadPool.QueueUserWorkItem(new WaitCallback(this.Pull));
                    }
                    else
                    {
                        throw new ConnectionManagerException();
                    }
                }
                catch (Exception ex)
                {
                    throw new ConnectionManagerException(ex.Message, ex);
                }
            }
        }
예제 #29
0
        public override SparseStream OpenContent(SparseStream parentStream, Ownership ownsStream)
        {
            if (parentStream != null && ownsStream == Ownership.Dispose)
            {
                parentStream.Dispose();
            }

            if (_buffer != null)
            {
                SparseStream rawStream = new BufferStream(_buffer, FileAccess.Read);
                return new BlockCacheStream(rawStream, Ownership.Dispose);
            }
            else
            {
                return SparseStream.FromStream(_stream, Ownership.None);
            }
        }
예제 #30
0
        public void should_be_able_to_advance_the_position_into_the_next_segment()
        {
            BufferStream sut = new BufferStream();
            List<ArraySegment<byte>> segments = new List<ArraySegment<byte>>();
            segments.Add(GetSegment(new byte[16], 512, 1024));
            segments.Add(GetSegment(new byte[16], 512, 1024));
            sut.Initialize(segments);

            Assert.AreEqual(0, sut.Position);

            sut.Position += 24;

            Assert.AreEqual(24, sut.Position);
        }
예제 #31
0
            private int Inflate(BufferStream tmp, byte[] outBuffer, int count)
            {
                inbound.next_in_index = 0;
                inbound.avail_in = count;
                inbound.next_out = outBuffer;
                int totalBytes = 0;
                do
                {
                    inbound.next_out_index = 0;
                    
                    inbound.avail_out = outBuffer.Length;

                    long priorOut = inbound.total_out;
                    var err = inbound.inflate(zlibConst.Z_SYNC_FLUSH);

                    if (err != zlibConst.Z_OK && err != zlibConst.Z_STREAM_END)
                        throw new ZStreamException("inflating: " + inbound.msg);

                    int outCount = (int)(inbound.total_out - priorOut);
                    if (outCount > 0)
                    {
                        tmp.Write(outBuffer, 0, outCount);
                        totalBytes += outCount;
                    }
                } while (inbound.avail_in > 0);
                return totalBytes;
            }
예제 #32
0
        public void should_be_able_to_rewind_the_position_into_the_previous_segment()
        {
            int segmentLength = 16;
            int expectedPosition = segmentLength * 3 / 2;

            BufferStream sut = new BufferStream();
            List<ArraySegment<byte>> segments = new List<ArraySegment<byte>>();
            segments.Add(GetSegment(new byte[segmentLength], 512, 1024));
            segments.Add(GetSegment(new byte[segmentLength], 512, 1024));
            sut.Initialize(segments);

            Assert.AreEqual(0, sut.Position);

            sut.Position += expectedPosition;

            Assert.AreEqual(expectedPosition, sut.Position);

            sut.Position -= segmentLength;
            Assert.AreEqual(segmentLength/2, sut.Position);
        }
예제 #33
0
            IEnumerable<WebSocketsFrame> IExtension.ApplyIncoming(NetContext context, WebSocketConnection connection, WebSocketsFrame frame)
            {
                if (frame.Reserved1 && !frame.IsControlFrame)
                {
                    BufferStream tmp = null;
                    var payload = frame.Payload;
                    payload.Position = 0;
                    byte[] inBuffer = null, outBuffer = null;

                    try
                    {
                        outBuffer = context.GetBuffer();
                        inBuffer = context.GetBuffer();
                        tmp = new BufferStream(context, 0);

                        if (inbound == null)
                        {
                            inbound = new ZStream();
                            inbound.inflateInit();

                            // fake a zlib header with:
                            // CMF:
                            //   CM = 8 (deflate)
                            //   CINFO = 7 (32k window)
                            // FLG:
                            //   FCHECK: 26 (checksum of other bits)
                            //   FDICT: 0 (no dictionary)
                            //   FLEVEL: 3 (maximum)
                            inBuffer[0] = 120;
                            inBuffer[1] = 218;
                            inbound.next_in = inBuffer;
                            int chk = Inflate(tmp, outBuffer, 2);
                            if (chk != 0) throw new InvalidOperationException("Spoofed zlib header suggested data");
                        }   
                        
                        inbound.next_in = inBuffer;
                        int remaining = frame.PayloadLength;
                        //bool first = true;
                        while (remaining > 0)
                        {
                            int readCount = payload.Read(inBuffer, 0, inBuffer.Length);
                            if (readCount <= 0) break;
                            remaining -= readCount;

                            //if (first)
                            //{   // kill the BFINAL flag from the first block, if set; we don't want zlib
                            //    // trying to verify the ADLER checksum; unfortunately, a frame can contain
                            //    // multiple blocks, and a *later* block could have BFINAL set. That sucks.
                            //    inBuffer[0] &= 254;
                            //    first = false;
                            //}
                            Inflate(tmp, outBuffer, readCount);                          
                        }
                        if (remaining != 0) throw new EndOfStreamException();

                        // spoof the missing 4 bytes from the tail
                        inBuffer[0] = inBuffer[1] = 0x00;
                        inBuffer[2] = inBuffer[3] = 0xFF;
                        Inflate(tmp, outBuffer, 4);

                        // set our final output
                        tmp.Position = 0;
                        frame.Payload = tmp;
                        long bytesSaved = tmp.Length - frame.PayloadLength;
                        frame.PayloadLength = (int)tmp.Length;
                        frame.Reserved1 = false;
                        tmp = payload as BufferStream;
                        parent.RegisterInboundBytesSaved(bytesSaved);
                    }
#if DEBUG
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex);
                        throw;
                    }
#endif
                    finally
                    {
                        if (inbound != null)
                        {
                            inbound.next_out = null;
                            inbound.next_in = null;
                        }
                        if (tmp != null) tmp.Dispose();
                        if (inBuffer != null) context.Recycle(inBuffer);
                        if (outBuffer != null) context.Recycle(outBuffer);
                        if (parent.disableContextTakeover) ClearContext(true, false);
                    }

                }
                yield return frame;
            }
예제 #34
0
        public static OJN DecodeHeader(string filename)
        {
            var ojn = new OJN();

            using (var stream = new BufferStream(filename))
            {
                stream.Seek(0, SeekOrigin.Begin);
                ojn.Id              = stream.ReadInt32();
                ojn.Sign            = stream.ReadString(4);
                ojn.EncodingVersion = stream.ReadSingle();
                ojn.Genre           = (OJN.Genres)stream.ReadInt32();
                ojn.BPM             = stream.ReadSingle();

                ojn.Level = new Dictionary <OJN.Difficulty, short>
                {
                    [OJN.Difficulty.EX] = stream.ReadInt16(),
                    [OJN.Difficulty.NX] = stream.ReadInt16(),
                    [OJN.Difficulty.HX] = stream.ReadInt16(),
                    [OJN.Difficulty.MX] = stream.ReadInt16()
                };

                ojn.EventCount = new Dictionary <OJN.Difficulty, int>
                {
                    [OJN.Difficulty.EX] = stream.ReadInt32(),
                    [OJN.Difficulty.NX] = stream.ReadInt32(),
                    [OJN.Difficulty.HX] = stream.ReadInt32()
                };

                ojn.NoteCount = new Dictionary <OJN.Difficulty, int>
                {
                    [OJN.Difficulty.EX] = stream.ReadInt32(),
                    [OJN.Difficulty.NX] = stream.ReadInt32(),
                    [OJN.Difficulty.HX] = stream.ReadInt32()
                };

                ojn.MeasureCount = new Dictionary <OJN.Difficulty, int>
                {
                    [OJN.Difficulty.EX] = stream.ReadInt32(),
                    [OJN.Difficulty.NX] = stream.ReadInt32(),
                    [OJN.Difficulty.HX] = stream.ReadInt32()
                };

                ojn.BlockCount = new Dictionary <OJN.Difficulty, int>
                {
                    [OJN.Difficulty.EX] = stream.ReadInt32(),
                    [OJN.Difficulty.NX] = stream.ReadInt32(),
                    [OJN.Difficulty.HX] = stream.ReadInt32()
                };

                ojn.OldEncodingVersion = stream.ReadInt16();
                ojn.OldId    = stream.ReadInt16();
                ojn.OldGenre = stream.ReadString(20);

                int thumbnailSize = stream.ReadInt32();
                ojn.Version = stream.ReadInt32();

                ojn.Title       = stream.ReadString(64);
                ojn.Artist      = stream.ReadString(32);
                ojn.Pattern     = stream.ReadString(32);
                ojn.OJMFileName = stream.ReadString(32);

                int coverArtSize = stream.ReadInt32();

                ojn.Duration = new Dictionary <OJN.Difficulty, int>
                {
                    [OJN.Difficulty.EX] = stream.ReadInt32(),
                    [OJN.Difficulty.NX] = stream.ReadInt32(),
                    [OJN.Difficulty.HX] = stream.ReadInt32()
                };

                ojn.BlockOffset = new Dictionary <OJN.Difficulty, int>
                {
                    [OJN.Difficulty.EX] = stream.ReadInt32(),
                    [OJN.Difficulty.NX] = stream.ReadInt32(),
                    [OJN.Difficulty.HX] = stream.ReadInt32()
                };

                ojn.CoverArtOffset = stream.ReadInt32();

                stream.Seek(ojn.CoverArtOffset, SeekOrigin.Begin);
                ojn.CoverArt  = stream.ReadBytes(coverArtSize);
                ojn.Thumbnail = stream.ReadBytes(thumbnailSize);

                return(ojn);
            }
        }