tokensToFunction function
Implementation
PathFunction tokensToFunction(
List<Token> tokens, {
bool sensitive = false,
String Function(String)? encode,
bool validate = true,
}) {
final encoder = encode ?? _defaultEncode;
// Compile all the tokens into regexps.
final matches = tokens.map((token) {
if (token is RegExp) {
return RegExp('^(?:${token.pattern})\$', caseSensitive: false);
}
});
return (dynamic data) {
String path = '';
for (int i = 0; i < tokens.length; i++) {
final token = tokens[i];
if (token is String) {
path += token;
continue;
}
final value = data != null ? data[token.name] : null;
final optional = token.modifier == '?' || token.modifier == '*';
final repeat = token.modifier == '*' || token.modifier == '+';
if (value is List) {
if (!repeat) {
// 'Expected "${token.name}" to not repeat, but got an array'
throw TypeError();
}
if (value.isEmpty) {
if (optional) {
continue;
}
// 'Expected "${token.name}" to not be empty'
throw TypeError();
}
for (var j = 0; j < value.length; j++) {
final segment = encoder.call(value[j] as String);
if (validate && !(matches.elementAt(i) as RegExp).hasMatch(segment)) {
// 'Expected all "${token.name}" to match "${token.pattern}", but got "${segment}"'
throw TypeError();
}
path += '${token.prefix}$segment${token.suffix}';
}
continue;
}
if (value is String || value is num) {
final segment = encoder.call(value.toString());
if (validate && !(matches.elementAt(i) as RegExp).hasMatch(segment)) {
// 'Expected "${token.name}" to match "${token.pattern}", but got "${segment}"'
throw TypeError();
}
path += '${token.prefix}$segment${token.suffix}';
continue;
}
if (optional) {
continue;
}
// final typeOfMessage = repeat ? "an array" : "a string";
// 'Expected "${token.name}" to be ${typeOfMessage}'
throw TypeError();
}
return path;
};
}