public static StorageFrameDecoded ReadFrame(Stream source)
        {
            using (var binary = new BitReader(source))
            {
                var version = binary.ReadInt64();
                var name = binary.ReadString();
                var len = binary.Read7BitInt();
                var bytes = binary.ReadBytes(len);
                var sha1Expected = binary.ReadBytes(20);

                var decoded = new StorageFrameDecoded(bytes, name, version);
                if (decoded.IsEmpty && sha1Expected.All(b => b == 0))
                {
                    // this looks like end of the stream.
                    return decoded;
                }

                //SHA1. TODO: compute hash nicely
                var sha1Actual = EncodeFrame(name, bytes, version).Hash;
                if (!sha1Expected.SequenceEqual(sha1Actual))
                    throw new StorageFrameException("SHA mismatch in data frame");

                return decoded;
            }
        }
 public object ReadMessage(Stream stream)
 {
     using (var bin = new BitReader(stream))
     {
         var contract = bin.ReadString();
         Formatter formatter;
         if (!_formattersByContract.TryGetValue(contract, out formatter))
             throw new InvalidOperationException(string.Format("Couldn't find contract type for name '{0}'", contract));
         var length = bin.Read7BitInt();
         var data = bin.ReadBytes(length);
         using (var inner = new MemoryStream(data, 0,length))
         {
             return formatter.DeserializerDelegate(inner);
         }
     }
 }
        public IEnumerable<DataRecord> ReadAll(long startOffset, int maxRecordCount)
        {
            if (startOffset < 0)
                throw new ArgumentOutOfRangeException("startOffset");

            if (maxRecordCount < 0)
                throw new ArgumentOutOfRangeException("maxRecordCount");

            var endOffset = GetEndOffset();

            if (startOffset >= endOffset)
                yield break;

            if (!File.Exists(Path.Combine(_path, "stream.dat")))
                throw new InvalidOperationException("File stream.chk found but stream.dat file does not exist");

            using (_dataStream = new FileStream(Path.Combine(_path, "stream.dat"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                using (_dataBits = new BitReader(_dataStream))
                {
                    _dataStream.Seek(startOffset, SeekOrigin.Begin);

                    int count = 0;
                    while (_dataStream.Position < endOffset && count <= maxRecordCount)
                    {
                        var key = _dataBits.ReadString();
                        var length = _dataBits.Reader7BitInt();

                        if (_dataStream.Position + length > _dataStream.Length)
                            throw new InvalidOperationException("Data length is out of range.");

                        var data = _dataBits.ReadBytes(length);
                        yield return new DataRecord(key, data, _dataStream.Position);

                        if (count == maxRecordCount)
                            break;

                        count++;
                    }
                }
            }
        }
 protected static void DeserializeId(BitReader br, UniqueId uid)
 {
     if (uid.Type == UniqueIdType.Steam)
     {
         uid.Id = br.ReadBytes(8);
     }
     else if (uid.Type == UniqueIdType.PS4)
     {
         uid.Id = br.ReadBytes(32);
     }
     else if (uid.Type == UniqueIdType.Unknown)
     {
         uid.Id = br.ReadBytes(3); // Will be 0
         if (uid.Id.Sum(x => x) != 0)
         {
             throw new Exception("Unknown id isn't 0, might be lost");
         }
     }
     else if (uid.Type == UniqueIdType.Xbox)
     {
         uid.Id = br.ReadBytes(8);
     }
     else
     {
         throw new ArgumentException(string.Format("Invalid type: {0}. Next bits are {1}", ((int)uid.Type).ToString(), br.GetBits(br.Position, Math.Min(4096, br.Length - br.Position)).ToBinaryString()));
     }
     uid.PlayerNumber = br.ReadByte();
 }