63 lines
2.3 KiB
C#
63 lines
2.3 KiB
C#
using System.IO.Compression;
|
|||
|
|
using System.Text;
|
||
|
|
|
||
|
|
namespace MeWeb.Core.Knowledge;
|
||
|
|
|
||
|
|
public class NetworkInfo
|
||
|
|
{
|
||
|
|
public uint Number { get; set; }
|
||
|
|
public string Organisation { get; set; }
|
||
|
|
public List<uint> Upstreams { get; set; } = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
public sealed class NetworkTable
|
||
|
|
{
|
||
|
|
const uint Magic = 0x324B574D;
|
||
|
|
|
||
|
|
readonly Dictionary<uint, NetworkInfo> networks = [];
|
||
|
|
|
||
|
|
public DateTimeOffset BuiltAt { get; private set; }
|
||
|
|
|
||
|
|
public int Count => networks.Count;
|
||
|
|
|
||
|
|
public NetworkInfo Find(uint number) => networks.GetValueOrDefault(number);
|
||
|
|
|
||
|
|
public static NetworkTable Read(Stream compressed)
|
||
|
|
{
|
||
|
|
using var brotli = new BrotliStream(compressed, CompressionMode.Decompress);
|
||
|
|
using var reader = new BinaryReader(brotli, Encoding.UTF8);
|
||
|
|
if (reader.ReadUInt32() != Magic) throw new InvalidDataException("not a me-web? network table");
|
||
|
|
var table = new NetworkTable { BuiltAt = DateTimeOffset.FromUnixTimeSeconds(reader.ReadInt64()) };
|
||
|
|
var count = reader.Read7BitEncodedInt();
|
||
|
|
var previous = 0u;
|
||
|
|
for (var i = 0; i < count; i++)
|
||
|
|
{
|
||
|
|
previous += (uint)reader.Read7BitEncodedInt64();
|
||
|
|
var info = new NetworkInfo { Number = previous, Organisation = reader.ReadString() };
|
||
|
|
var upstreams = reader.Read7BitEncodedInt();
|
||
|
|
for (var u = 0; u < upstreams; u++) info.Upstreams.Add((uint)reader.Read7BitEncodedInt64());
|
||
|
|
if (info.Organisation.Length == 0) info.Organisation = null;
|
||
|
|
table.networks[info.Number] = info;
|
||
|
|
}
|
||
|
|
return table;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void Write(Stream output, DateTimeOffset builtAt, IEnumerable<NetworkInfo> networks)
|
||
|
|
{
|
||
|
|
var list = networks.Where(n => n.Number != 0).OrderBy(n => n.Number).ToList();
|
||
|
|
using var brotli = new BrotliStream(output, CompressionLevel.SmallestSize, leaveOpen: true);
|
||
|
|
using var writer = new BinaryWriter(brotli, Encoding.UTF8);
|
||
|
|
writer.Write(Magic);
|
||
|
|
writer.Write(builtAt.ToUnixTimeSeconds());
|
||
|
|
writer.Write7BitEncodedInt(list.Count);
|
||
|
|
var previous = 0u;
|
||
|
|
foreach (var info in list)
|
||
|
|
{
|
||
|
|
writer.Write7BitEncodedInt64(info.Number - previous);
|
||
|
|
writer.Write(info.Organisation ?? "");
|
||
|
|
writer.Write7BitEncodedInt(info.Upstreams.Count);
|
||
|
|
foreach (var upstream in info.Upstreams) writer.Write7BitEncodedInt64(upstream);
|
||
|
|
previous = info.Number;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|