1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
require 'mustermann/pattern'
require 'mustermann/ast/node'
module Mustermann
# Matches strings that are identical to the pattern.
#
# @example
# Mustermann.new('/:foo', type: :identity) === '/bar' # => false
#
# @see Mustermann::Pattern
# @see file:README.md#identity Syntax description in the README
class Identity < Pattern
register :identity
# @param (see Mustermann::Pattern#===)
# @return (see Mustermann::Pattern#===)
# @see (see Mustermann::Pattern#===)
def ===(string)
unescape(string) == @string
end
# @param (see Mustermann::Pattern#peek_size)
# @return (see Mustermann::Pattern#peek_size)
# @see (see Mustermann::Pattern#peek_size)
def peek_size(string)
return unless unescape(string).start_with? @string
return @string.size if string.start_with? @string # optimization
@string.each_char.with_index.inject(0) do |count, (char, index)|
char_size = 1
escaped = @@uri.escape(char, /./)
char_size = escaped.size if string[index, escaped.size].downcase == escaped.downcase
count + char_size
end
end
# URI templates support generating templates (the logic is quite complex, though).
#
# @example (see Mustermann::Pattern#to_templates)
# @param (see Mustermann::Pattern#to_templates)
# @return (see Mustermann::Pattern#to_templates)
# @see Mustermann::Pattern#to_templates
def to_templates
[@@uri.escape(to_s)]
end
# Generates an AST so it's compatible with {Mustermann::AST::Pattern}.
# Not used internally by {Mustermann::Identity}.
# @!visibility private
def to_ast
payload = @string.each_char.with_index.map { |c, i| AST::Node[c == ?/ ? :separator : :char].new(c, start: i, stop: i+1) }
AST::Node[:root].new(payload, pattern: @string, start: 0, stop: @string.length)
end
# Identity patterns support expanding.
#
# This implementation does not use {Mustermann::Expander} internally to save memory and
# compilation time.
#
# @example (see Mustermann::Pattern#expand)
# @param (see Mustermann::Pattern#expand)
# @return (see Mustermann::Pattern#expand)
# @raise (see Mustermann::Pattern#expand)
# @see Mustermann::Pattern#expand
# @see Mustermann::Expander
def expand(behavior = nil, values = {})
values, behavior = behavior, nil if behavior.kind_of?(Hash)
return to_s if values.empty? or behavior == :ignore
raise ExpandError, "cannot expand with keys %p" % values.keys.sort if behavior == :raise
raise ArgumentError, "unknown behavior %p" % behavior if behavior != :append
params = values.map { |key, value| @@uri.escape(key.to_s) + "=" + @@uri.escape(value.to_s, /[^\w]/) }
separator = @string.include?(??) ? ?& : ??
@string + separator + params.join(?&)
end
end
end
|