/// <summary> /// Resets this frame to contain uncompressed data. /// </summary> /// <param name="data">Input buffer containing uncompressed data to be stored in this frame.</param> /// <param name="offset">Offset of uncompressed data in the input buffer.</param> /// <param name="count">Size of uncompressed data in the input buffer. Maximum data size is 64KB.</param> public void SetUncompressed(byte[] data, int offset, int count) { CheckRange(data, offset, count); CheckMaxFrameSize(count); EnsureBuffer(count); Array.Copy(data, offset, Buffer, 0, count); BufferUsage = count; DataLength = count; Checksum = ComputeMasked(data, offset, count); Type = SnappyFrameType.Uncompressed; }
/// <summary> /// Resets this frame to stream identifier frame. First frame in the stream must be identifier frame. /// </summary> public void SetStreamIdentifier() { BufferUsage = 0; Checksum = 0; DataLength = 6; Type = SnappyFrameType.StreamIdentifier; }
/// <summary> /// Resets this frame to contain compressed data. /// </summary> /// <param name="data">Input buffer containing uncompressed data that is compressed by this method before being stored in the frame.</param> /// <param name="offset">Offset of uncompressed data in the input buffer.</param> /// <param name="count">Size of uncompressed data in the input buffer. Maximum data size is 64KB.</param> public void SetCompressed(byte[] data, int offset, int count) { CheckRange(data, offset, count); CheckMaxFrameSize(count); EnsureBuffer(CompressTool.GetMaxCompressedLength(count)); BufferUsage = CompressTool.Compress(data, offset, count, Buffer, 0); DataLength = count; Checksum = ComputeMasked(data, offset, count); Type = SnappyFrameType.Compressed; }
/// <summary> /// Resets this frame to padding frame of specified size. /// </summary> /// <param name="size">Size of padding data excluding the 4 bytes of frame header. Maximum padding size is 16MB.</param> public void SetPadding(int size) { if (size < 0 || size >= (1 << 24)) throw new ArgumentOutOfRangeException(); BufferUsage = 0; Checksum = 0; DataLength = size; Type = SnappyFrameType.Padding; }
/// <summary> /// Retrieves Snappy frame from underlying stream. Retrieved frame data is stored in properties of this object. /// Return value indicates end of stream. Exceptions indicate data integrity errors and underlying stream errors. /// </summary> /// <param name="stream">Underlying stream that will be read by this method.</param> /// <returns> /// True if frame was successfully retrieved. False if there are no more frames in the stream, i.e. the end of stream has been reached. /// Note that reaching the end of stream in the middle of the frame is considered an error and causes exception instead. /// </returns> public bool Read(Stream stream) { try { var headerRead = stream.Read(WordBuffer, 0, 4); if (headerRead == 0) return false; EnsureRead(stream, WordBuffer, headerRead, 4 - headerRead); Type = (SnappyFrameType)WordBuffer[0]; int length = WordBuffer[1] + ((int)WordBuffer[2] << 8) + ((int)WordBuffer[3] << 16); if (Type == SnappyFrameType.Compressed || Type == SnappyFrameType.Uncompressed) { if (length < 4) throw new InvalidDataException(); EnsureRead(stream, WordBuffer, 0, 4); Checksum = (uint)WordBuffer[0] + ((uint)WordBuffer[1] << 8) + ((uint)WordBuffer[2] << 16) + ((uint)WordBuffer[3] << 24); BufferUsage = length - 4; if (BufferUsage > MaxBufferUsage) throw new InvalidDataException(); EnsureBuffer(BufferUsage); EnsureRead(stream, Buffer, 0, BufferUsage); DataLength = Type == SnappyFrameType.Uncompressed ? BufferUsage : CompressTool.GetUncompressedLength(Buffer, 0, BufferUsage); if (DataLength > MaxFrameSize) throw new InvalidDataException(); } else if (Type == SnappyFrameType.Padding || (byte)Type >= (byte)SnappyFrameType.SkippableFirst && (byte)Type <= (byte)SnappyFrameType.SkippableLast) { DataLength = length; BufferUsage = 0; Checksum = 0; SkipBytes(stream, length); } else if (Type == SnappyFrameType.StreamIdentifier) { if (length != 6) throw new InvalidOperationException(); DataLength = 6; BufferUsage = 0; Checksum = 0; EnsureBuffer(6); EnsureRead(stream, Buffer, 0, 6); if (!Utils.BuffersEqual(Buffer, StreamIdentifier, 6)) throw new InvalidDataException(); } else throw new InvalidDataException(); return true; } catch { SetPadding(0); throw; } }