using System; using MessagePack; namespace GameCult.Networking { /// /// Serializes and deserializes the explicit modern CultNet schema-v0 message family. /// public static class CultNetSchemaMessageSerialization { /// /// Gets the serializer options used for CultNet schema-v0 messages. /// public static readonly MessagePackSerializerOptions Options = MessagePackSerializerOptions.Standard.WithSecurity(MessagePackSecurity.UntrustedData); /// /// Serializes a typed CultNet schema message. /// public static byte[] Serialize(T message) where T : ICultNetSchemaMessage { if (message == null) throw new ArgumentNullException(nameof(message)); return MessagePackSerializer.Serialize(message, Options); } /// /// Deserializes a typed CultNet schema message. /// public static T Deserialize(byte[] payload) where T : ICultNetSchemaMessage { if (payload == null) throw new ArgumentNullException(nameof(payload)); return MessagePackSerializer.Deserialize(payload, Options); } /// /// Deserializes a CultNet schema message by inspecting its schema version. /// public static ICultNetSchemaMessage Deserialize(byte[] payload) { if (payload == null) throw new ArgumentNullException(nameof(payload)); var header = MessagePackSerializer.Deserialize(payload, Options); if (header == null || string.IsNullOrWhiteSpace(header.SchemaVersion)) { throw new MessagePackSerializationException("CultNet schema-v0 payload is missing schemaVersion."); } return header.SchemaVersion switch { CultNetSchemaVersions.Hello => Deserialize(payload), CultNetSchemaVersions.Login => Deserialize(payload), CultNetSchemaVersions.Register => Deserialize(payload), CultNetSchemaVersions.Verify => Deserialize(payload), CultNetSchemaVersions.LoginSuccess => Deserialize(payload), CultNetSchemaVersions.Error => Deserialize(payload), CultNetSchemaVersions.SampleChangeName => Deserialize(payload), CultNetSchemaVersions.SampleChat => Deserialize(payload), CultNetSchemaVersions.OperationRequest => Deserialize(payload), CultNetSchemaVersions.OperationResponse => Deserialize(payload), CultNetSchemaVersions.DocumentDelete => Deserialize(payload), CultNetSchemaVersions.DocumentPutRaw => Deserialize(payload), CultNetSchemaVersions.SnapshotRequest => Deserialize(payload), CultNetSchemaVersions.SnapshotResponseRaw => Deserialize(payload), CultNetSchemaVersions.DatabaseSubscribe => Deserialize(payload), CultNetSchemaVersions.DatabaseUnsubscribe => Deserialize(payload), CultNetSchemaVersions.DatabaseChangeRaw => Deserialize(payload), CultNetSchemaVersions.ShardCatalogRequest => Deserialize(payload), CultNetSchemaVersions.ShardCatalogResponse => Deserialize(payload), CultNetSchemaVersions.ShardLogRequest => Deserialize(payload), CultNetSchemaVersions.ShardLogResponse => Deserialize(payload), CultNetSchemaVersions.SimulationObservation => Deserialize(payload), CultNetSchemaVersions.SimulationConsensusCandidate => Deserialize(payload), CultNetSchemaVersions.VerseCatalogRequest => Deserialize(payload), CultNetSchemaVersions.VerseCatalogResponse => Deserialize(payload), CultNetSchemaVersions.PeerExchangeRequest => Deserialize(payload), CultNetSchemaVersions.PeerExchangeResponse => Deserialize(payload), CultNetSchemaVersions.SchemaCatalogRequest => Deserialize(payload), CultNetSchemaVersions.SchemaCatalogResponse => Deserialize(payload), _ => throw new MessagePackSerializationException( $"Unsupported CultNet schema-v0 message \"{header.SchemaVersion}\".") }; } [MessagePackObject(AllowPrivate = true)] internal sealed class CultNetSchemaHeader { [Key("schemaVersion")] public string SchemaVersion { get; set; } = string.Empty; } } }