Files
MeWeb/src/MeWeb.Core/Knowledge/NetworkTable.cs
T

63 lines
2.3 KiB
C#
Raw Normal View History

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;
}
}
}