PathTemplate.parse constructor
PathTemplate.parse(
- String source
Parses static segments, :name, and final **:name captures.
Implementation
factory PathTemplate.parse(String source) {
final normalized = source.trim();
if (normalized.isEmpty || normalized == '/') {
return PathTemplate._(source, const <_Part>[], const <String>{});
}
final text = normalized.startsWith('/')
? normalized.substring(1)
: normalized;
final path = text.endsWith('/') ? text.substring(0, text.length - 1) : text;
final segments = path.split('/');
final parts = <_Part>[];
final names = <String>{};
for (var index = 0; index < segments.length; index++) {
final segment = segments[index];
if (segment.isEmpty) {
throw PathSyntaxException('Path contains an empty segment.', source);
}
if (segment.startsWith('**:')) {
final name = segment.substring(3);
_validateName(name, source, names);
if (index != segments.length - 1) {
throw PathSyntaxException(
'A rest parameter must be the final segment.',
source,
);
}
parts.add(_RestPart(name));
continue;
}
if (segment.startsWith(':')) {
final name = segment.substring(1);
_validateName(name, source, names);
parts.add(_ParameterPart(name));
continue;
}
if (segment.contains(':') ||
segment.contains('*') ||
segment.contains('(') ||
segment.contains('{')) {
throw PathSyntaxException(
'Typed routes support only static, :name, and **:name segments.',
source,
);
}
parts.add(_StaticPart(segment));
}
return PathTemplate._(
source,
List<_Part>.of(parts, growable: false),
Set<String>.of(names),
);
}