using System; using System.Buffers; using AyCode.Core.Serializers.Binaries; namespace AyCode.Services.SignalRs; /// /// Project-specific binary protocol with SignalParams-aware argument deserialization. /// Register this in PluginNopStartup.cs and AcSignalRClientBase instead of AcBinaryHubProtocol. /// public class AyCodeBinaryHubProtocol : AcBinaryHubProtocol { /// /// Parsed SignalParams from current message (arg[2]). /// Used by ReadSingleArgument (arg[3]) for type-aware deserialization. /// Thread-safe: SignalR processes messages sequentially per connection. /// private SignalParams? _currentSignalParams; public AyCodeBinaryHubProtocol() : this(AcBinarySerializerOptions.Default) { } public AyCodeBinaryHubProtocol(AcBinarySerializerOptions options, BinaryProtocolMode protocolMode = BinaryProtocolMode.Bytes) : base(options, protocolMode) { } protected override void OnArgumentRead(object? value, int index) { if (value is SignalParams sp) _currentSignalParams = sp; } protected override object? ReadSingleArgument(ref SequenceReader r, Type targetType) { r.TryReadLittleEndian(out int argLength); if (argLength == 0) return null; if (argLength == 1) { r.TryPeek(out byte marker); if (marker == 0) { r.Advance(1); return null; } } var argSlice = r.UnreadSequence.Slice(0, argLength); r.Advance(argLength); // byte[] fast-path: tag only, no VarUInt (argLength implies size) var argReader = new SequenceReader(argSlice); if (argReader.TryPeek(out byte tag) && tag == BinaryTypeCode.ByteArray) { return SequenceToByteArray(argSlice.Slice(1)); } // IsRawBytesData: return raw bytes, consumer deserializes if (_currentSignalParams is { IsRawBytesData: true }) return SequenceToByteArray(argSlice); // SignalDataType: resolve actual type for eager deserialization if (targetType == typeof(object) && _currentSignalParams?.SignalDataType != null) { var dataType = Type.GetType(_currentSignalParams.SignalDataType); if (dataType != null) targetType = dataType; } // Bytes mode: linearize to byte[] → ArrayBinaryInput (fastest deser, no segment overhead) if (_protocolMode == BinaryProtocolMode.Bytes) { var bytes = SequenceToByteArray(argSlice); return AcBinaryDeserializer.Deserialize(bytes, targetType, Options); } return DeserializeFromSequence(argSlice, targetType, Options); } }