Class for representing and working with resource names.

A resource name is represented by a PathTemplate, an assignment of resource IDs to parameters in the template, and an optional service name. This class allows the service name and resource IDs to be modified, but only within the same template.

Beispiel #1
0
 /// <summary>
 /// Implementation of parsing, returning the error message for a FormatException if parsing fails.
 /// </summary>
 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!
 }
Beispiel #2
0
 /// <summary>
 /// Attempts to parse the given resource name against this template, returning <c>null</c> on failure.
 /// </summary>
 /// <remarks>
 /// Although this method returns <c>null</c> if a name is passed in which doesn't match the template,
 /// it still throws <see cref="ArgumentNullException"/> if <paramref name="name"/> is null, as this would
 /// usually indicate a programming error rather than a data error.
 /// </remarks>
 /// <param name="name">The resource name to parse against this template. Must not be null.</param>
 /// <param name="result">When this method returns, the parsed resource name or <c>null</c> if parsing fails.</param>
 /// <returns><c>true</c> if the name was parsed successfully; <c>false</c> otherwise.</returns>
 public bool TryParseName(string name, out ResourceName result)
 {
     return TryParseNameInternal(name, out result) == null;
 }