Radarr/src/MonoTorrent/BEncoding/IBEncodedValue.cs

203 lines
7.0 KiB
C#

using System;
using System.IO;
namespace MonoTorrent.BEncoding
{
/// <summary>
/// Base interface for all BEncoded values.
/// </summary>
public abstract class BEncodedValue
{
internal abstract void DecodeInternal(RawReader reader);
/// <summary>
/// Encodes the BEncodedValue into a byte array
/// </summary>
/// <returns>Byte array containing the BEncoded Data</returns>
public byte[] Encode()
{
byte[] buffer = new byte[LengthInBytes()];
if (Encode(buffer, 0) != buffer.Length)
throw new BEncodingException("Error encoding the data");
return buffer;
}
/// <summary>
/// Encodes the BEncodedValue into the supplied buffer
/// </summary>
/// <param name="buffer">The buffer to encode the information to</param>
/// <param name="offset">The offset in the buffer to start writing the data</param>
/// <returns></returns>
public abstract int Encode(byte[] buffer, int offset);
public static T Clone<T>(T value)
where T : BEncodedValue
{
Check.Value(value);
return (T)BEncodedValue.Decode(value.Encode());
}
/// <summary>
/// Interface for all BEncoded values
/// </summary>
/// <param name="data">The byte array containing the BEncoded data</param>
/// <returns></returns>
public static BEncodedValue Decode(byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");
using (RawReader stream = new RawReader(new MemoryStream(data)))
return (Decode(stream));
}
internal static BEncodedValue Decode(byte[] buffer, bool strictDecoding)
{
return Decode(buffer, 0, buffer.Length, strictDecoding);
}
/// <summary>
/// Decode BEncoded data in the given byte array
/// </summary>
/// <param name="buffer">The byte array containing the BEncoded data</param>
/// <param name="offset">The offset at which the data starts at</param>
/// <param name="length">The number of bytes to be decoded</param>
/// <returns>BEncodedValue containing the data that was in the byte[]</returns>
public static BEncodedValue Decode(byte[] buffer, int offset, int length)
{
return Decode(buffer, offset, length, true);
}
public static BEncodedValue Decode(byte[] buffer, int offset, int length, bool strictDecoding)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
if (offset < 0 || length < 0)
throw new IndexOutOfRangeException("Neither offset or length can be less than zero");
if (offset > buffer.Length - length)
throw new ArgumentOutOfRangeException("length");
using (RawReader reader = new RawReader(new MemoryStream(buffer, offset, length), strictDecoding))
return (BEncodedValue.Decode(reader));
}
/// <summary>
/// Decode BEncoded data in the given stream
/// </summary>
/// <param name="stream">The stream containing the BEncoded data</param>
/// <returns>BEncodedValue containing the data that was in the stream</returns>
public static BEncodedValue Decode(Stream stream)
{
if (stream == null)
throw new ArgumentNullException("stream");
return Decode(new RawReader(stream, false));
}
/// <summary>
/// Decode BEncoded data in the given RawReader
/// </summary>
/// <param name="reader">The RawReader containing the BEncoded data</param>
/// <returns>BEncodedValue containing the data that was in the stream</returns>
public static BEncodedValue Decode(RawReader reader)
{
if (reader == null)
throw new ArgumentNullException("reader");
BEncodedValue data;
switch (reader.PeekByte())
{
case ('i'): // Integer
data = new BEncodedNumber();
break;
case ('d'): // Dictionary
data = new BEncodedDictionary();
break;
case ('l'): // List
data = new BEncodedList();
break;
case ('1'): // String
case ('2'):
case ('3'):
case ('4'):
case ('5'):
case ('6'):
case ('7'):
case ('8'):
case ('9'):
case ('0'):
data = new BEncodedString();
break;
default:
throw new BEncodingException("Could not find what value to decode");
}
data.DecodeInternal(reader);
return data;
}
/// <summary>
/// Interface for all BEncoded values
/// </summary>
/// <param name="data">The byte array containing the BEncoded data</param>
/// <returns></returns>
public static T Decode<T>(byte[] data) where T : BEncodedValue
{
return (T)BEncodedValue.Decode(data);
}
/// <summary>
/// Decode BEncoded data in the given byte array
/// </summary>
/// <param name="buffer">The byte array containing the BEncoded data</param>
/// <param name="offset">The offset at which the data starts at</param>
/// <param name="length">The number of bytes to be decoded</param>
/// <returns>BEncodedValue containing the data that was in the byte[]</returns>
public static T Decode<T>(byte[] buffer, int offset, int length) where T : BEncodedValue
{
return BEncodedValue.Decode<T>(buffer, offset, length, true);
}
public static T Decode<T>(byte[] buffer, int offset, int length, bool strictDecoding) where T : BEncodedValue
{
return (T)BEncodedValue.Decode(buffer, offset, length, strictDecoding);
}
/// <summary>
/// Decode BEncoded data in the given stream
/// </summary>
/// <param name="stream">The stream containing the BEncoded data</param>
/// <returns>BEncodedValue containing the data that was in the stream</returns>
public static T Decode<T>(Stream stream) where T : BEncodedValue
{
return (T)BEncodedValue.Decode(stream);
}
public static T Decode<T>(RawReader reader) where T : BEncodedValue
{
return (T)BEncodedValue.Decode(reader);
}
/// <summary>
/// Returns the size of the byte[] needed to encode this BEncodedValue
/// </summary>
/// <returns></returns>
public abstract int LengthInBytes();
}
}