Innovenergy_trunk/csharp/Lib/Protocols/DBus/WireFormat/DBusReader.cs

284 lines
7.6 KiB
C#

using System.Text;
using InnovEnergy.Lib.Protocols.DBus.Protocol.DataTypes;
using InnovEnergy.Lib.Protocols.DBus.Protocol.DataTypes.Signatures;
namespace InnovEnergy.Lib.Protocols.DBus.WireFormat;
internal abstract class DBusReader
{
public Boolean SwapEndian { get; }
public abstract Int32 BytesRead { get; }
public abstract Byte ReadByte();
public abstract ArraySegment<Byte> ReadSegment(Int32 size); // TODO
protected DBusReader(Boolean swapEndian) => SwapEndian = swapEndian;
public Int16 ReadInt16()
{
var span = ReadAlignedSpan(sizeof(Int16));
return BitConverter.ToInt16(span);
}
public UInt16 ReadUInt16()
{
var span = ReadAlignedSpan(sizeof(UInt16));
return BitConverter.ToUInt16(span);
}
public Int32 ReadInt32()
{
var span = ReadAlignedSpan(sizeof(Int32));
return BitConverter.ToInt32(span);
}
public UInt32 ReadUInt32()
{
var span = ReadAlignedSpan(sizeof(UInt32));
return BitConverter.ToUInt32(span);
}
public Int64 ReadInt64()
{
var span = ReadAlignedSpan(sizeof(Int64));
return BitConverter.ToInt64(span);
}
public UInt64 ReadUInt64()
{
var span = ReadAlignedSpan(sizeof(UInt64));
return BitConverter.ToUInt64(span);
}
public Boolean ReadBoolean()
{
var uInt32 = ReadUInt32();
return uInt32 switch
{
0 => false,
1 => true,
_ => throw new Exception($"Read value {uInt32} at position " +
$"{BytesRead - sizeof(UInt32)} " +
"while expecting boolean (0/1)")
};
}
public Double ReadDouble()
{
var span = ReadAlignedSpan(sizeof(Double));
return BitConverter.ToDouble(span);
}
public String ReadString()
{
var strLen = ReadInt32();
var span = ReadSegment(strLen);
var str = Encoding.UTF8.GetString(span);
SkipNull();
return str;
}
public ObjectPath ReadObjectPath() => ReadString();
public Signature ReadSignature()
{
var sigLen = ReadByte();
var span = ReadSegment(sigLen);
var sig = Encoding.ASCII.GetString(span); // only ascii chars allowed in sig
SkipNull();
return Signature.FromString(sig);
}
public Variant ReadVariant()
{
var signature = ReadSignature();
var value = signature.Read(this);
return new Variant(value, signature);
}
public void AlignForComposite() => Align(8); // structs/arrays/dict elements are always 8-aligned
private ReadOnlySpan<Byte> ReadAlignedSpan(Int32 size)
{
Align(size);
var start = BytesRead;
var span = ReadSegment(size);
if (SwapEndian)
Array.Reverse(span.Array!, span.Offset + start, size);
return span;
}
private void SkipNull()
{
if (ReadByte() != 0)
throw new Exception("Read a non-zero byte while expecting a null byte");
}
private void Align(Int32 alignment)
{
while (BytesRead % alignment != 0)
SkipNull();
}
public override String ToString() => $"@{BytesRead}";
}
// internal abstract class DBusReader
// {
// public static Boolean Debug { get; set; }
// public Boolean SwapEndian { get; }
//
// public abstract Int32 BytesRead { get; }
// public abstract Byte ReadByte();
// public abstract ArraySegment<Byte> ReadSegment(Int32 size); // TODO
//
// protected DBusReader(Boolean swapEndian) => SwapEndian = swapEndian;
//
// public Int16 ReadInt16()
// {
// var span = ReadAlignedSpan(sizeof(Int16));
// var r = BitConverter.ToInt16(span);
//
// if (Debug) Console.WriteLine("ReadInt16 " + r);
//
// return r;
// }
//
// public UInt16 ReadUInt16()
// {
// var span = ReadAlignedSpan(sizeof(UInt16));
// var r = BitConverter.ToUInt16(span);
// if (Debug) Console.WriteLine("ReadUInt16 " + r);
// return r;
// }
//
// public Int32 ReadInt32()
// {
// var span = ReadAlignedSpan(sizeof(Int32));
// var r = BitConverter.ToInt32(span);
// if (Debug) Console.WriteLine("ReadInt32 " + r);
// return r;
// }
//
// public UInt32 ReadUInt32()
// {
// var span = ReadAlignedSpan(sizeof(UInt32));
// var r = BitConverter.ToUInt32(span);
// if (Debug) Console.WriteLine("ReadUInt32 " + r);
// return r;
// }
//
// public Int64 ReadInt64()
// {
// var span = ReadAlignedSpan(sizeof(Int64));
// var r = BitConverter.ToInt64(span);
// if (Debug) Console.WriteLine("ReadInt64 " + r);
// return r;
// }
//
// public UInt64 ReadUInt64()
// {
// var span = ReadAlignedSpan(sizeof(UInt64));
// var r = BitConverter.ToUInt64(span);
// if (Debug) Console.WriteLine("ReadUInt64 " + r);
// return r;
// }
//
// public Boolean ReadBoolean()
// {
// var uInt32 = ReadUInt32();
//
// var r = uInt32 switch
// {
// 0 => false,
// 1 => true,
// _ => throw new ProtocolException($"Read value {uInt32} at position " +
// $"{BytesRead - sizeof(UInt32)} " +
// "while expecting boolean (0/1)")
// };
//
// if (Debug) Console.WriteLine("ReadBoolean " + r);
// return r;
// }
//
// public Double ReadDouble()
// {
// var span = ReadAlignedSpan(sizeof(Double));
// var r = BitConverter.ToDouble(span);
// if (Debug) Console.WriteLine("ReadDouble " + r);
// return r;
// }
//
// public String ReadString()
// {
// var strLen = ReadInt32();
// var span = ReadSegment(strLen);
// var str = Encoding.UTF8.GetString(span);
// if (Debug) Console.WriteLine("ReadString " + str);
// SkipNull();
// return str;
// }
//
// public ObjectPath ReadObjectPath()
// {
// if (Debug) Console.WriteLine("ReadObjectPath:");
// return ReadString();
// }
//
// public Signature ReadSignature()
// {
// if (Debug) Console.WriteLine("ReadSignature:");
// var sigLen = ReadByte();
// var span = ReadSegment(sigLen);
// var sig = Encoding.ASCII.GetString(span); // only ascii chars allowed in sig
// SkipNull();
// return Signature.FromString(sig);
// }
//
// public Variant ReadVariant()
// {
// if (Debug) Console.WriteLine("ReadVariant:");
// var signature = ReadSignature();
// var value = signature.Read(this);
//
// return new Variant(value, signature);
// }
//
// public void AlignForComposite() => Align(8); // structs/arrays/dict elements are always 8-aligned
//
// private ReadOnlySpan<Byte> ReadAlignedSpan(Int32 size)
// {
// Align(size);
//
// var start = BytesRead;
// var span = ReadSegment(size);
//
// if (SwapEndian)
// Array.Reverse(span.Array!, span.Offset + start, size);
//
// return span;
// }
//
// private void SkipNull()
// {
// if (ReadByte() != 0)
// throw new ProtocolException("Read a non-zero byte while expecting a null byte");
// }
//
// private void Align(Int32 alignment)
// {
// while (BytesRead % alignment != 0)
// SkipNull();
// }
//
// public override String ToString() => $"@{BytesRead}";
// }