284 lines
7.6 KiB
C#
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}";
|
|
// } |