// Copyright © WireMock.Net #if PROTOBUF using System; using System.Threading; using System.Threading.Tasks; using ProtoBufJsonConverter; using ProtoBufJsonConverter.Models; using Stef.Validation; using WireMock.Models; using WireMock.Util; namespace WireMock.Matchers; /// /// Grpc ProtoBuf Matcher /// /// public class ProtoBufMatcher : IProtoBufMatcher { /// public string Name => nameof(ProtoBufMatcher); /// public MatchBehaviour MatchBehaviour { get; } /// /// The Func to define The proto definition as text. /// public Func ProtoDefinition { get; } /// /// The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}". /// public string MessageType { get; } /// /// The Matcher to use (optional). /// public IObjectMatcher? Matcher { get; } private static readonly Converter ProtoBufToJsonConverter = SingletonFactory.GetInstance(); /// /// Initializes a new instance of the class. /// /// The proto definition. /// The full type of the protobuf (request/response) message object. Format is "{package-name}.{type-name}". /// The match behaviour. (default = "AcceptOnMatch") /// The optional jsonMatcher to use to match the ProtoBuf as (json) object. public ProtoBufMatcher( Func protoDefinition, string messageType, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, IObjectMatcher? matcher = null ) { ProtoDefinition = Guard.NotNull(protoDefinition); MessageType = Guard.NotNullOrWhiteSpace(messageType); Matcher = matcher; MatchBehaviour = matchBehaviour; } /// public async Task IsMatchAsync(byte[]? input, CancellationToken cancellationToken = default) { var result = new MatchResult(); if (input != null) { try { var instance = await DecodeAsync(input, true, cancellationToken).ConfigureAwait(false); result = Matcher?.IsMatch(instance) ?? new MatchResult(MatchScores.Perfect); } catch (Exception e) { result = new MatchResult(MatchScores.Mismatch, e); } } return MatchBehaviourHelper.Convert(MatchBehaviour, result); } /// public Task DecodeAsync(byte[]? input, CancellationToken cancellationToken = default) { return DecodeAsync(input, false, cancellationToken); } /// public string GetCSharpCodeArguments() { return "NotImplemented"; } private async Task DecodeAsync(byte[]? input, bool throwException, CancellationToken cancellationToken) { if (input == null) { return null; } var request = new ConvertToObjectRequest(ProtoDefinition().Text, MessageType, input); try { return await ProtoBufToJsonConverter.ConvertAsync(request, cancellationToken).ConfigureAwait(false); } catch { if (throwException) { throw; } return null; } } } #endif