private string TryParseNameInternal(string name, out ResourceName result)
{
GaxPreconditions.CheckNotNull(name, nameof(name));
string serviceName = null;
if (name.StartsWith("//"))
{
int nameEnd = name.IndexOf('/', 2);
// Can't call ValidateServiceName as we don't want to throw...
if (nameEnd == 2)
{
result = null;
return "Service name cannot be empty";
}
// It's *just about* plausible to have a template of ** and a value of "//service".
if (nameEnd == -1)
{
serviceName = name.Substring(2);
name = "";
}
else
{
serviceName = name.Substring(2, nameEnd - 2);
name = name.Substring(nameEnd + 1);
}
}
string[] nameSegments = name == "" ? new string[0] : name.Split(s_slashSplit);
if (_hasPathWildcard)
{
// The path wildcard can be empty...
if (nameSegments.Length < _segments.Count - 1)
{
result = null;
return "Name does not match template: too few segments";
}
}
else if (nameSegments.Length != _segments.Count)
{
result = null;
return "Name does not match template: incorrect number of segments";
}
string[] resourceIds = new string[ParameterCount];
int resourceIdIndex = 0;
int nameSegmentIndex = 0;
foreach (var segment in _segments)
{
switch (segment.Kind)
{
case SegmentKind.Literal:
var nameSegment = nameSegments[nameSegmentIndex++];
if (nameSegment != segment.Value)
{
result = null;
return $"Name does not match template in literal segment: '{nameSegment}' != '{segment.Value}'";
}
break;
case SegmentKind.Wildcard:
// Could use segment.ValidateWildcard, but the exception wouldn't be as clean.
var value = nameSegments[nameSegmentIndex++];
if (value == "")
{
result = null;
return "Name does not match template: wildcard segment is empty";
}
resourceIds[resourceIdIndex++] = value;
break;
case SegmentKind.PathWildcard:
// Work out how many segments to consume based on the number of segments in the template and the
// actual number of segments in the specified name
int count = nameSegments.Length - _segments.Count + 1;
// Make the common case more efficient
if (count == 1)
{
resourceIds[resourceIdIndex++] = nameSegments[nameSegmentIndex++];
}
else
{
resourceIds[resourceIdIndex++] = string.Join("/", nameSegments.Skip(nameSegmentIndex).Take(count));
nameSegmentIndex += count;
}
break;
}
}
result = ResourceName.CreateWithShallowCopy(this, serviceName, resourceIds);
return null; // Success!
}