File: Parsers\IPAddressListParser.cs
Web Access
Project: src\src\Libraries\Microsoft.AspNetCore.HeaderParsing\Microsoft.AspNetCore.HeaderParsing.csproj (Microsoft.AspNetCore.HeaderParsing)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using Microsoft.Extensions.Primitives;
 
namespace Microsoft.AspNetCore.HeaderParsing.Parsers;
 
internal sealed class IPAddressListParser : HeaderParser<IReadOnlyList<IPAddress>>
{
    public static IPAddressListParser Instance { get; } = new();
 
    public override bool TryParse(StringValues values, [NotNullWhen(true)] out IReadOnlyList<IPAddress>? result, [NotNullWhen(false)] out string? error)
    {
        var list = new List<IPAddress>();
 
        foreach (var value in values)
        {
            var startIndex = 0;
            int nextSeparatorIndex;
 
            do
            {
                nextSeparatorIndex = value!.IndexOf(',', startIndex);
                var length = (nextSeparatorIndex >= 0 ? nextSeparatorIndex : value.Length) - startIndex;
 
                if (length == 0)
                {
                    error = "IP address cannot be empty.";
                    result = null;
                    return false;
                }
 
#if NETCOREAPP3_1_OR_GREATER
                var addressToParse = value.AsSpan(startIndex, length).Trim();
#else
                var addressToParse = value.AsSpan(startIndex, length).Trim().ToString();
#endif
 
                if (IPAddress.TryParse(addressToParse, out var address))
                {
                    list.Add(address);
                }
                else
                {
                    error = "Unable to parse IP address.";
                    result = null;
                    return false;
                }
 
                startIndex = nextSeparatorIndex + 1;
            }
            while (nextSeparatorIndex >= 0);
        }
 
        result = list;
        error = null;
        return true;
    }
}