using System.Net; using System.Reflection; namespace SimpleHttpServer.Types; internal record EndpointInvocationInfo { //internal record struct QueryParameterInfo(string Name, Type Type, bool isPathParam, bool Path_isCatchAll, bool Query_IsOptional) { // public static QueryParameterInfo CreatePathParam(string name, Type type) => new(name, type, false, name == "$*", false); // public static QueryParameterInfo CreateQueryParam(string name, Type type, bool isOptional) => new(name, type, false, false, isOptional); //} internal record struct PathParameterInfo(string Name, Type Type, int ArgPos, int SegmentStartPos, bool IsCatchAll) { public PathParameterInfo(string name, Type type, int argPos) : this(name, type, argPos, -1, name == "$*") { } } internal record struct QueryParameterInfo(string Name, Type Type, int ArgPos, bool IsOptional); internal readonly MethodInfo methodInfo; internal readonly List queryParameters; internal readonly List pathParameters; internal readonly InternalEndpointCheckAttribute[] requiredChecks; /// /// a reference to the object in which this method is defined (or null if the class is static) /// internal readonly object? typeInstanceReference; public EndpointInvocationInfo(MethodInfo methodInfo, List pathParameters, List queryParameters, InternalEndpointCheckAttribute[] requiredChecks, object? typeInstanceReference) { this.methodInfo = methodInfo ?? throw new ArgumentNullException(nameof(methodInfo)); this.queryParameters = queryParameters ?? throw new ArgumentNullException(nameof(queryParameters)); this.pathParameters = pathParameters ?? throw new ArgumentNullException(nameof(pathParameters)); this.requiredChecks = requiredChecks; this.typeInstanceReference = typeInstanceReference; if (pathParameters.Any()) { Assert(pathParameters.Count(x => x.IsCatchAll) <= 1); // at most one catchall parameter var argPoses = pathParameters.Select(x => x.ArgPos).Concat(queryParameters.Select(x => x.ArgPos)).ToArray(); var argCnt = pathParameters.Count + queryParameters.Count; Assert(argPoses.Distinct().Count() == argCnt); // ArgPoses must be unique Assert(argPoses.Min() == HttpServer.expectedEndpointParameterPrefixCount); // ArgPoses must start from just after the prefix Assert(argPoses.Max() == HttpServer.expectedEndpointParameterPrefixCount + argCnt - 1); // ArgPoses must be contiguous Assert(pathParameters.All(x => x.SegmentStartPos != -1)); } } public bool CheckAll(HttpListenerRequest req) => requiredChecks.All(x => x.Check(req)); }