/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.IO;
namespace Avro.IO
{
///
/// Decoder for Avro binary format
///
public partial class BinaryDecoder : Decoder
{
private readonly Stream stream;
///
/// Initializes a new instance of the class.
///
/// Stream to decode.
public BinaryDecoder(Stream stream)
{
this.stream = stream;
}
///
/// null is written as zero bytes
///
public void ReadNull()
{
}
///
/// a boolean is written as a single byte
/// whose value is either 0 (false) or 1 (true).
///
///
public bool ReadBoolean()
{
byte b = read();
if (b == 0) return false;
if (b == 1) return true;
throw new AvroException("Not a boolean value in the stream: " + b);
}
///
/// int and long values are written using variable-length, zig-zag coding.
///
/// An integer value.
public int ReadInt()
{
return (int)ReadLong();
}
///
/// int and long values are written using variable-length, zig-zag coding.
///
/// A long value.
public long ReadLong()
{
byte b = read();
ulong n = b & 0x7FUL;
int shift = 7;
while ((b & 0x80) != 0)
{
b = read();
n |= (b & 0x7FUL) << shift;
shift += 7;
}
long value = (long)n;
return (-(value & 0x01L)) ^ ((value >> 1) & 0x7fffffffffffffffL);
}
///
/// Bytes are encoded as a long followed by that many bytes of data.
///
///
public byte[] ReadBytes()
{
return read(ReadLong());
}
///
/// Reads an enumeration.
///
/// Ordinal value of the enum.
public int ReadEnum()
{
return ReadInt();
}
///
/// Reads the size of the first block of an array.
///
/// Size of the first block of an array.
public long ReadArrayStart()
{
return doReadItemCount();
}
///
/// Processes the next block of an array and returns the number of items in the block and
/// let's the caller read those items.
///
/// Number of items in the next block of an array.
public long ReadArrayNext()
{
return doReadItemCount();
}
///
/// Reads the size of the next block of map-entries.
///
/// Size of the next block of map-entries.
public long ReadMapStart()
{
return doReadItemCount();
}
///
/// Processes the next block of map entries and returns the count of them.
///
/// Number of entires in the next block of a map.
public long ReadMapNext()
{
return doReadItemCount();
}
///
/// Reads the tag index of a union written by .
///
/// Tag index of a union.
public int ReadUnionIndex()
{
return ReadInt();
}
///
/// Reads fixed sized binary object.
///
/// Buffer to read the fixed value into.
public void ReadFixed(byte[] buffer)
{
ReadFixed(buffer, 0, buffer.Length);
}
///
/// Reads fixed sized binary object.
///
/// Buffer to read the fixed value into.
///
/// Position to start writing the fixed value to in the .
///
///
/// Number of bytes of the fixed to read.
///
public void ReadFixed(byte[] buffer, int start, int length)
{
Read(buffer, start, length);
}
///
/// Skips over a null value.
///
public void SkipNull()
{
ReadNull();
}
///
/// Skips over a boolean value.
///
public void SkipBoolean()
{
ReadBoolean();
}
///
/// Skips over an int value.
///
public void SkipInt()
{
ReadInt();
}
///
/// Skips over a long value.
///
public void SkipLong()
{
ReadLong();
}
///
/// Skips over a float value.
///
public void SkipFloat()
{
Skip(4);
}
///
/// Skips over a double value.
///
public void SkipDouble()
{
Skip(8);
}
///
/// Skips a byte-string written by .
///
public void SkipBytes()
{
Skip(ReadLong());
}
///
/// Skips a string written by .
///
public void SkipString()
{
SkipBytes();
}
///
/// Skips an enum value.
///
public void SkipEnum()
{
ReadLong();
}
///
/// Skips a union tag index.
///
public void SkipUnionIndex()
{
ReadLong();
}
///
/// Skips a fixed value of a specified length.
///
/// Length of the fixed to skip.
public void SkipFixed(int len)
{
Skip(len);
}
// Read p bytes into a new byte buffer
private byte[] read(long p)
{
byte[] buffer = new byte[p];
Read(buffer, 0, buffer.Length);
return buffer;
}
private byte read()
{
int n = stream.ReadByte();
if (n >= 0) return (byte)n;
throw new AvroException("End of stream reached");
}
private long doReadItemCount()
{
long result = ReadLong();
if (result < 0)
{
ReadLong(); // Consume byte-count if present
result = -result;
}
return result;
}
private void Skip(int p)
{
stream.Seek(p, SeekOrigin.Current);
}
private void Skip(long p)
{
stream.Seek(p, SeekOrigin.Current);
}
}
}