mustermann 3.0.4 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/mustermann/ast/expander.rb +4 -5
- data/lib/mustermann/ast/parser.rb +2 -3
- data/lib/mustermann/ast/translator.rb +4 -5
- data/lib/mustermann/expander.rb +1 -1
- data/lib/mustermann/rails.rb +47 -0
- data/lib/mustermann/version.rb +1 -1
- data/lib/mustermann/versions.rb +47 -0
- metadata +6 -38
- data/bench/capturing.rb +0 -57
- data/bench/regexp.rb +0 -21
- data/bench/simple_vs_sinatra.rb +0 -23
- data/bench/template_vs_addressable.rb +0 -26
- data/bench/uri_parser_object.rb +0 -16
- data/mustermann.gemspec +0 -18
- data/spec/ast_spec.rb +0 -15
- data/spec/composite_spec.rb +0 -163
- data/spec/concat_spec.rb +0 -127
- data/spec/equality_map_spec.rb +0 -42
- data/spec/expander_spec.rb +0 -123
- data/spec/identity_spec.rb +0 -127
- data/spec/mapper_spec.rb +0 -77
- data/spec/mustermann_spec.rb +0 -81
- data/spec/pattern_spec.rb +0 -54
- data/spec/regexp_based_spec.rb +0 -9
- data/spec/regular_spec.rb +0 -119
- data/spec/simple_match_spec.rb +0 -11
- data/spec/sinatra_spec.rb +0 -836
- data/spec/to_pattern_spec.rb +0 -70
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0b15c2c5c75d712dde03df8b83d4f0b646455aa892eb59365f1b09ce01bfa7c
|
|
4
|
+
data.tar.gz: 358ce50be0eb8638e47ea8bb3cd65512f57e10eb65b93600098145214a2f6d39
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3360ad1465989d2179b97d67c64261d7a68cf22ca1cea2a02f2450bd5b0894948efd4d99581b7d7609dc7698d4ed0595d85613b67d79dce3ce79b84d08e614ff
|
|
7
|
+
data.tar.gz: 8c32fae7ff72697598dacf54c1ddae95ea80a48814fa887c61d91e18bca6a0a1c79768a981fba0cd4d60d986db76c0961a3f6dae5c5a7a8b8276978428fb105e
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'mustermann/ast/translator'
|
|
3
3
|
require 'mustermann/ast/compiler'
|
|
4
|
-
require 'ruby2_keywords'
|
|
5
4
|
|
|
6
5
|
module Mustermann
|
|
7
6
|
module AST
|
|
@@ -12,11 +11,11 @@ module Mustermann
|
|
|
12
11
|
class Expander < Translator
|
|
13
12
|
raises ExpandError
|
|
14
13
|
|
|
15
|
-
translate
|
|
14
|
+
translate Array do |*args, **options|
|
|
16
15
|
inject(t.pattern) do |pattern, element|
|
|
17
|
-
t.add_to(pattern, t(element, *args))
|
|
16
|
+
t.add_to(pattern, t(element, *args, **options))
|
|
18
17
|
end
|
|
19
|
-
end
|
|
18
|
+
end
|
|
20
19
|
|
|
21
20
|
translate :capture do |**options|
|
|
22
21
|
t.for_capture(node, **options)
|
|
@@ -123,7 +122,7 @@ module Mustermann
|
|
|
123
122
|
|
|
124
123
|
# @see Mustermann::AST::Translator#expand
|
|
125
124
|
# @!visibility private
|
|
126
|
-
|
|
125
|
+
def escape(string, *args, **options)
|
|
127
126
|
return super unless string.respond_to?(:=~)
|
|
128
127
|
|
|
129
128
|
# URI::Parser is pretty slow, let's not send every string to it, even if it's unnecessary
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'mustermann/ast/node'
|
|
3
3
|
require 'forwardable'
|
|
4
|
-
require 'ruby2_keywords'
|
|
5
4
|
require 'strscan'
|
|
6
5
|
|
|
7
6
|
module Mustermann
|
|
@@ -65,10 +64,10 @@ module Mustermann
|
|
|
65
64
|
# @param [Symbol] type node type
|
|
66
65
|
# @return [Mustermann::AST::Node]
|
|
67
66
|
# @!visibility private
|
|
68
|
-
|
|
67
|
+
def node(type, *args, **options, &block)
|
|
69
68
|
type = Node[type] unless type.respond_to? :new
|
|
70
69
|
start = pos
|
|
71
|
-
node = block ? type.parse(*args, &block) : type.new(*args)
|
|
70
|
+
node = block ? type.parse(*args, **options, &block) : type.new(*args, **options)
|
|
72
71
|
min_size(start, pos, node)
|
|
73
72
|
end
|
|
74
73
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'mustermann/ast/node'
|
|
3
3
|
require 'mustermann/error'
|
|
4
|
-
require 'ruby2_keywords'
|
|
5
4
|
require 'delegate'
|
|
6
5
|
|
|
7
6
|
module Mustermann
|
|
@@ -40,9 +39,9 @@ module Mustermann
|
|
|
40
39
|
|
|
41
40
|
# shorthand for translating a nested object
|
|
42
41
|
# @!visibility private
|
|
43
|
-
|
|
42
|
+
def t(*args, **options, &block)
|
|
44
43
|
return translator unless args.any?
|
|
45
|
-
translator.translate(*args, &block)
|
|
44
|
+
translator.translate(*args, **options, &block)
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
# @!visibility private
|
|
@@ -113,8 +112,8 @@ module Mustermann
|
|
|
113
112
|
|
|
114
113
|
# Start the translation dance for a (sub)tree.
|
|
115
114
|
# @!visibility private
|
|
116
|
-
|
|
117
|
-
result = decorator_for(node).translate(*args, &block)
|
|
115
|
+
def translate(node, *args, **options, &block)
|
|
116
|
+
result = decorator_for(node).translate(*args, **options, &block)
|
|
118
117
|
result = result.node while result.is_a? NodeTranslator
|
|
119
118
|
result
|
|
120
119
|
end
|
data/lib/mustermann/expander.rb
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'mustermann'
|
|
3
|
+
require 'mustermann/ast/pattern'
|
|
4
|
+
require 'mustermann/versions'
|
|
5
|
+
|
|
6
|
+
module Mustermann
|
|
7
|
+
# Rails style pattern implementation.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# Mustermann.new('/:foo', type: :rails) === '/bar' # => true
|
|
11
|
+
#
|
|
12
|
+
# @see Mustermann::Pattern
|
|
13
|
+
# @see file:README.md#rails Syntax description in the README
|
|
14
|
+
class Rails < AST::Pattern
|
|
15
|
+
extend Versions
|
|
16
|
+
register :rails
|
|
17
|
+
|
|
18
|
+
# first parser, no optional parts
|
|
19
|
+
version('2.3') do
|
|
20
|
+
on(nil) { |c| unexpected(c) }
|
|
21
|
+
on(?*) { |c| node(:named_splat) { scan(/\w+/) } }
|
|
22
|
+
on(?:) { |c| node(:capture) { scan(/\w+/) } }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# rack-mount
|
|
26
|
+
version('3.0', '3.1') do
|
|
27
|
+
on(?)) { |c| unexpected(c) }
|
|
28
|
+
on(?() { |c| node(:optional, node(:group) { read unless scan(?)) }) }
|
|
29
|
+
on(?\\) { |c| node(:char, expect(/./)) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# stand-alone journey
|
|
33
|
+
version('3.2') do
|
|
34
|
+
on(?|) { |c| raise ParseError, "the implementation of | is broken in ActionDispatch, cannot compile compatible pattern" }
|
|
35
|
+
on(?\\) { |c| node(:char, c) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# embedded journey, broken (ignored) escapes
|
|
39
|
+
version('4.0', '4.1') { on(?\\) { |c| read } }
|
|
40
|
+
|
|
41
|
+
# escapes got fixed in 4.2
|
|
42
|
+
version('4.2') { on(?\\) { |c| node(:char, expect(/./)) } }
|
|
43
|
+
|
|
44
|
+
# Rails 5.0 fixes |
|
|
45
|
+
version('5.0') { on(?|) { |c| node(:or) }}
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/mustermann/version.rb
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mustermann
|
|
3
|
+
# Mixin that adds support for multiple versions of the same type.
|
|
4
|
+
# @see Mustermann::Rails
|
|
5
|
+
# @!visibility private
|
|
6
|
+
module Versions
|
|
7
|
+
# Checks if class has mulitple versions available and picks one that matches the version option.
|
|
8
|
+
# @!visibility private
|
|
9
|
+
def new(*args, version: nil, **options)
|
|
10
|
+
return super(*args, **options) unless versions.any?
|
|
11
|
+
self[version].new(*args, **options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return [Hash] version to subclass mapping.
|
|
15
|
+
# @!visibility private
|
|
16
|
+
def versions
|
|
17
|
+
@versions ||= {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Defines a new version.
|
|
21
|
+
# @!visibility private
|
|
22
|
+
def version(*list, inherit_from: nil, &block)
|
|
23
|
+
superclass = self[inherit_from] || self
|
|
24
|
+
subclass = Class.new(superclass, &block)
|
|
25
|
+
list.each { |v| versions[v] = subclass }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Resolve a subclass for a given version string.
|
|
29
|
+
# @!visibility private
|
|
30
|
+
def [](version)
|
|
31
|
+
return versions.values.last unless version
|
|
32
|
+
detected = versions.detect { |v,_| version.start_with?(v) }
|
|
33
|
+
raise ArgumentError, 'unsupported version %p' % version unless detected
|
|
34
|
+
detected.last
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @!visibility private
|
|
38
|
+
def name
|
|
39
|
+
super || superclass.name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @!visibility private
|
|
43
|
+
def inspect
|
|
44
|
+
name
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mustermann
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0
|
|
4
|
+
version: 3.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Haase
|
|
@@ -9,21 +9,7 @@ authors:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
|
-
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: ruby2_keywords
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.0.1
|
|
20
|
-
type: :runtime
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.0.1
|
|
12
|
+
dependencies: []
|
|
27
13
|
description: A library implementing patterns that behave like regular expressions.
|
|
28
14
|
email: sinatrarb@googlegroups.com
|
|
29
15
|
executables: []
|
|
@@ -32,11 +18,6 @@ extra_rdoc_files: []
|
|
|
32
18
|
files:
|
|
33
19
|
- LICENSE
|
|
34
20
|
- README.md
|
|
35
|
-
- bench/capturing.rb
|
|
36
|
-
- bench/regexp.rb
|
|
37
|
-
- bench/simple_vs_sinatra.rb
|
|
38
|
-
- bench/template_vs_addressable.rb
|
|
39
|
-
- bench/uri_parser_object.rb
|
|
40
21
|
- lib/mustermann.rb
|
|
41
22
|
- lib/mustermann/ast/boundaries.rb
|
|
42
23
|
- lib/mustermann/ast/compiler.rb
|
|
@@ -60,6 +41,7 @@ files:
|
|
|
60
41
|
- lib/mustermann/mapper.rb
|
|
61
42
|
- lib/mustermann/pattern.rb
|
|
62
43
|
- lib/mustermann/pattern_cache.rb
|
|
44
|
+
- lib/mustermann/rails.rb
|
|
63
45
|
- lib/mustermann/regexp.rb
|
|
64
46
|
- lib/mustermann/regexp_based.rb
|
|
65
47
|
- lib/mustermann/regular.rb
|
|
@@ -70,21 +52,7 @@ files:
|
|
|
70
52
|
- lib/mustermann/sinatra/try_convert.rb
|
|
71
53
|
- lib/mustermann/to_pattern.rb
|
|
72
54
|
- lib/mustermann/version.rb
|
|
73
|
-
- mustermann.
|
|
74
|
-
- spec/ast_spec.rb
|
|
75
|
-
- spec/composite_spec.rb
|
|
76
|
-
- spec/concat_spec.rb
|
|
77
|
-
- spec/equality_map_spec.rb
|
|
78
|
-
- spec/expander_spec.rb
|
|
79
|
-
- spec/identity_spec.rb
|
|
80
|
-
- spec/mapper_spec.rb
|
|
81
|
-
- spec/mustermann_spec.rb
|
|
82
|
-
- spec/pattern_spec.rb
|
|
83
|
-
- spec/regexp_based_spec.rb
|
|
84
|
-
- spec/regular_spec.rb
|
|
85
|
-
- spec/simple_match_spec.rb
|
|
86
|
-
- spec/sinatra_spec.rb
|
|
87
|
-
- spec/to_pattern_spec.rb
|
|
55
|
+
- lib/mustermann/versions.rb
|
|
88
56
|
homepage: https://github.com/sinatra/mustermann
|
|
89
57
|
licenses:
|
|
90
58
|
- MIT
|
|
@@ -96,14 +64,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
96
64
|
requirements:
|
|
97
65
|
- - ">="
|
|
98
66
|
- !ruby/object:Gem::Version
|
|
99
|
-
version: 2.
|
|
67
|
+
version: 2.7.0
|
|
100
68
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
69
|
requirements:
|
|
102
70
|
- - ">="
|
|
103
71
|
- !ruby/object:Gem::Version
|
|
104
72
|
version: '0'
|
|
105
73
|
requirements: []
|
|
106
|
-
rubygems_version:
|
|
74
|
+
rubygems_version: 4.0.6
|
|
107
75
|
specification_version: 4
|
|
108
76
|
summary: Your personal string matching expert.
|
|
109
77
|
test_files: []
|
data/bench/capturing.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path('../lib', __dir__)
|
|
2
|
-
|
|
3
|
-
require 'benchmark'
|
|
4
|
-
require 'mustermann'
|
|
5
|
-
require 'mustermann/regexp_based'
|
|
6
|
-
require 'addressable/template'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Mustermann.register(:regexp, Class.new(Mustermann::RegexpBased) {
|
|
10
|
-
def compile(**options)
|
|
11
|
-
Regexp.new(@string)
|
|
12
|
-
end
|
|
13
|
-
}, load: false)
|
|
14
|
-
|
|
15
|
-
Mustermann.register(:addressable, Class.new(Mustermann::RegexpBased) {
|
|
16
|
-
def compile(**options)
|
|
17
|
-
Addressable::Template.new(@string)
|
|
18
|
-
end
|
|
19
|
-
}, load: false)
|
|
20
|
-
|
|
21
|
-
list = [
|
|
22
|
-
[:sinatra, '/*/:name' ],
|
|
23
|
-
[:rails, '/*prefix/:name' ],
|
|
24
|
-
[:simple, '/*/:name' ],
|
|
25
|
-
[:template, '{/prefix*}/{name}' ],
|
|
26
|
-
[:regexp, '\A\/(?<splat>.*?)\/(?<name>[^\/\?#]+)\Z' ],
|
|
27
|
-
[:addressable, '{/prefix*}/{name}' ]
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
def self.assert(value)
|
|
31
|
-
fail unless value
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
string = '/a/b/c/d'
|
|
35
|
-
name = 'd'
|
|
36
|
-
|
|
37
|
-
GC.disable
|
|
38
|
-
|
|
39
|
-
puts "Compilation:"
|
|
40
|
-
Benchmark.bmbm do |x|
|
|
41
|
-
list.each do |type, pattern|
|
|
42
|
-
x.report(type) { 1_000.times { Mustermann.new(pattern, type: type) } }
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
puts "", "Matching with two captures (one splat, one normal):"
|
|
47
|
-
Benchmark.bmbm do |x|
|
|
48
|
-
list.each do |type, pattern|
|
|
49
|
-
pattern = Mustermann.new(pattern, type: type)
|
|
50
|
-
x.report type do
|
|
51
|
-
10_000.times do
|
|
52
|
-
match = pattern.match(string)
|
|
53
|
-
assert match[:name] == name
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
data/bench/regexp.rb
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
require 'benchmark'
|
|
2
|
-
|
|
3
|
-
puts " atomic vs normal segments ".center(52, '=')
|
|
4
|
-
|
|
5
|
-
types = {
|
|
6
|
-
normal: /\A\/(?:a|%61)\/(?<b>[^\/\?#]+)(?:\/(?<c>[^\/\?#]+))?\Z/,
|
|
7
|
-
atomic: /\A\/(?:a|%61)\/(?<b>(?>[^\/\?#]+))(?:\/(?<c>(?>[^\/\?#]+)))?\Z/
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
Benchmark.bmbm do |x|
|
|
11
|
-
types.each do |name, regexp|
|
|
12
|
-
string = "/a/" << ?a * 10000 << "/" << ?a * 5000
|
|
13
|
-
fail unless regexp.match(string)
|
|
14
|
-
string << "/"
|
|
15
|
-
fail if regexp.match(string)
|
|
16
|
-
|
|
17
|
-
x.report name.to_s do
|
|
18
|
-
100.times { regexp.match(string) }
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
data/bench/simple_vs_sinatra.rb
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path('../lib', __dir__)
|
|
2
|
-
|
|
3
|
-
require 'benchmark'
|
|
4
|
-
require 'mustermann/simple'
|
|
5
|
-
require 'mustermann/sinatra'
|
|
6
|
-
|
|
7
|
-
[Mustermann::Simple, Mustermann::Sinatra].each do |klass|
|
|
8
|
-
puts "", " #{klass} ".center(64, '=')
|
|
9
|
-
Benchmark.bmbm do |x|
|
|
10
|
-
no_capture = klass.new("/simple")
|
|
11
|
-
x.report("no captures, match") { 1_000.times { no_capture.match('/simple') } }
|
|
12
|
-
x.report("no captures, miss") { 1_000.times { no_capture.match('/miss') } }
|
|
13
|
-
|
|
14
|
-
simple = klass.new("/:name")
|
|
15
|
-
x.report("simple, match") { 1_000.times { simple.match('/simple').captures } }
|
|
16
|
-
x.report("simple, miss") { 1_000.times { simple.match('/mi/ss') } }
|
|
17
|
-
|
|
18
|
-
splat = klass.new("/*")
|
|
19
|
-
x.report("splat, match") { 1_000.times { splat.match("/a/b/c").captures } }
|
|
20
|
-
x.report("splat, miss") { 1_000.times { splat.match("/a/b/c.miss") } }
|
|
21
|
-
end
|
|
22
|
-
puts
|
|
23
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path('../lib', __dir__)
|
|
2
|
-
|
|
3
|
-
require 'benchmark'
|
|
4
|
-
require 'mustermann/template'
|
|
5
|
-
require 'addressable/template'
|
|
6
|
-
|
|
7
|
-
[Mustermann::Template, Addressable::Template].each do |klass|
|
|
8
|
-
puts "", " #{klass} ".center(64, '=')
|
|
9
|
-
Benchmark.bmbm do |x|
|
|
10
|
-
no_capture = klass.new("/simple")
|
|
11
|
-
x.report("no captures, match") { 1_000.times { no_capture.match('/simple') } }
|
|
12
|
-
x.report("no captures, miss") { 1_000.times { no_capture.match('/miss') } }
|
|
13
|
-
|
|
14
|
-
simple = klass.new("/{match}")
|
|
15
|
-
x.report("simple, match") { 1_000.times { simple.match('/simple').captures } }
|
|
16
|
-
x.report("simple, miss") { 1_000.times { simple.match('/mi/ss') } }
|
|
17
|
-
|
|
18
|
-
explode = klass.new("{/segments*}")
|
|
19
|
-
x.report("explode, match") { 1_000.times { explode.match("/a/b/c").captures } }
|
|
20
|
-
x.report("explode, miss") { 1_000.times { explode.match("/a/b/c.miss") } }
|
|
21
|
-
|
|
22
|
-
expand = klass.new("/prefix/{foo}/something/{bar}")
|
|
23
|
-
x.report("expand") { 100.times { expand.expand(foo: 'foo', bar: 'bar').to_s } }
|
|
24
|
-
end
|
|
25
|
-
puts
|
|
26
|
-
end
|
data/bench/uri_parser_object.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
require "objspace"
|
|
2
|
-
require "uri"
|
|
3
|
-
require_relative "../lib/mustermann/ast/translator"
|
|
4
|
-
|
|
5
|
-
translator = Mustermann::AST::Translator.new
|
|
6
|
-
translator.escape("foo")
|
|
7
|
-
|
|
8
|
-
h1 = ObjectSpace.each_object.inject(Hash.new 0) { |h, o| h[o.class] += 1; h }
|
|
9
|
-
|
|
10
|
-
100.times do
|
|
11
|
-
translator.escape("foo")
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
h2 = ObjectSpace.each_object.inject(Hash.new 0) { |h, o| h[o.class] += 1; h }
|
|
15
|
-
|
|
16
|
-
raise if (h2[URI::RFC2396_Parser] - h1[URI::RFC2396_Parser] != 0)
|
data/mustermann.gemspec
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path("../lib", __FILE__)
|
|
2
|
-
require "mustermann/version"
|
|
3
|
-
|
|
4
|
-
Gem::Specification.new do |s|
|
|
5
|
-
s.name = "mustermann"
|
|
6
|
-
s.version = Mustermann::VERSION
|
|
7
|
-
s.authors = ["Konstantin Haase", "Zachary Scott"]
|
|
8
|
-
s.email = "sinatrarb@googlegroups.com"
|
|
9
|
-
s.homepage = "https://github.com/sinatra/mustermann"
|
|
10
|
-
s.summary = %q{Your personal string matching expert.}
|
|
11
|
-
s.description = %q{A library implementing patterns that behave like regular expressions.}
|
|
12
|
-
s.license = 'MIT'
|
|
13
|
-
s.required_ruby_version = '>= 2.6.0'
|
|
14
|
-
s.files = `git ls-files`.split("\n")
|
|
15
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
16
|
-
|
|
17
|
-
s.add_runtime_dependency('ruby2_keywords', '~> 0.0.1')
|
|
18
|
-
end
|
data/spec/ast_spec.rb
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
require 'support'
|
|
3
|
-
require 'mustermann/ast/node'
|
|
4
|
-
|
|
5
|
-
describe Mustermann::AST do
|
|
6
|
-
describe :type do
|
|
7
|
-
example { Mustermann::AST::Node[:char].type .should be == :char }
|
|
8
|
-
example { Mustermann::AST::Node[:char].new.type .should be == :char }
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
describe :min_size do
|
|
12
|
-
example { Mustermann::AST::Node[:char].new.min_size.should be == 1 }
|
|
13
|
-
example { Mustermann::AST::Node[:node].new.min_size.should be == 0 }
|
|
14
|
-
end
|
|
15
|
-
end
|
data/spec/composite_spec.rb
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
require 'support'
|
|
3
|
-
require 'mustermann'
|
|
4
|
-
|
|
5
|
-
describe Mustermann::Composite do
|
|
6
|
-
describe :new do
|
|
7
|
-
example 'with no argument' do
|
|
8
|
-
expect { Mustermann::Composite.new }.
|
|
9
|
-
to raise_error(ArgumentError, 'cannot create empty composite pattern')
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
example 'with one argument' do
|
|
13
|
-
pattern = Mustermann.new('/foo')
|
|
14
|
-
Mustermann::Composite.new(pattern).should be == pattern
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
example 'with supported type specific arguments' do
|
|
18
|
-
Mustermann::Composite.new("/a", "/b", greedy: true)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
example 'with unsupported type specific arguments' do
|
|
22
|
-
expect { Mustermann::Composite.new("/a", "/b", greedy: true, type: :identity) }.to raise_error(ArgumentError)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
context :| do
|
|
27
|
-
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second') }
|
|
28
|
-
|
|
29
|
-
describe :== do
|
|
30
|
-
example { subject.should be == subject }
|
|
31
|
-
example { subject.should be == Mustermann.new('/foo/:name', '/:first/:second') }
|
|
32
|
-
example { subject.should_not be == Mustermann.new('/foo/:name') }
|
|
33
|
-
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
describe :=== do
|
|
37
|
-
example { subject.should be === "/foo/bar" }
|
|
38
|
-
example { subject.should be === "/fox/bar" }
|
|
39
|
-
example { subject.should_not be === "/foo" }
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
describe :params do
|
|
43
|
-
example { subject.params("/foo/bar") .should be == { "name" => "bar" } }
|
|
44
|
-
example { subject.params("/fox/bar") .should be == { "first" => "fox", "second" => "bar" } }
|
|
45
|
-
example { subject.params("/foo") .should be_nil }
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
describe :=== do
|
|
49
|
-
example { subject.should match("/foo/bar") }
|
|
50
|
-
example { subject.should match("/fox/bar") }
|
|
51
|
-
example { subject.should_not match("/foo") }
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
describe :expand do
|
|
55
|
-
example { subject.should respond_to(:expand) }
|
|
56
|
-
example { subject.expand(name: 'bar') .should be == '/foo/bar' }
|
|
57
|
-
example { subject.expand(first: 'fox', second: 'bar') .should be == '/fox/bar' }
|
|
58
|
-
|
|
59
|
-
context "without expandable patterns" do
|
|
60
|
-
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', type: :simple) }
|
|
61
|
-
example { subject.should_not respond_to(:expand) }
|
|
62
|
-
example { expect { subject.expand(name: 'bar') }.to raise_error(NotImplementedError) }
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
describe :to_templates do
|
|
67
|
-
example { should respond_to(:to_templates) }
|
|
68
|
-
example { should generate_templates('/foo/{name}', '/{first}/{second}') }
|
|
69
|
-
|
|
70
|
-
context "without patterns implementing to_templates" do
|
|
71
|
-
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', type: :simple) }
|
|
72
|
-
example { should_not respond_to(:to_templates) }
|
|
73
|
-
example { expect { subject.to_templates }.to raise_error(NotImplementedError) }
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
describe :eql? do
|
|
78
|
-
example { should be_eql(pattern) }
|
|
79
|
-
example { should be_eql(Mustermann.new('/foo/:name', '/:first/:second', operator: :|)) }
|
|
80
|
-
example { should_not be_eql(Mustermann.new('/bar/:name', '/:first/:second', operator: :|)) }
|
|
81
|
-
example { should_not be_eql(Mustermann.new('/foo/:name', '/:first/:second', operator: :&)) }
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
context :& do
|
|
86
|
-
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
|
87
|
-
|
|
88
|
-
describe :== do
|
|
89
|
-
example { subject.should be == subject }
|
|
90
|
-
example { subject.should be == Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
|
91
|
-
example { subject.should_not be == Mustermann.new('/foo/:name') }
|
|
92
|
-
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second') }
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
describe :=== do
|
|
96
|
-
example { subject.should be === "/foo/bar" }
|
|
97
|
-
example { subject.should_not be === "/fox/bar" }
|
|
98
|
-
example { subject.should_not be === "/foo" }
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
describe :params do
|
|
102
|
-
example { subject.params("/foo/bar") .should be == { "name" => "bar" } }
|
|
103
|
-
example { subject.params("/fox/bar") .should be_nil }
|
|
104
|
-
example { subject.params("/foo") .should be_nil }
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
describe :match do
|
|
108
|
-
example { subject.should match("/foo/bar") }
|
|
109
|
-
example { subject.should_not match("/fox/bar") }
|
|
110
|
-
example { subject.should_not match("/foo") }
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
describe :expand do
|
|
114
|
-
example { subject.should_not respond_to(:expand) }
|
|
115
|
-
example { expect { subject.expand(name: 'bar') }.to raise_error(NotImplementedError) }
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
context :^ do
|
|
120
|
-
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', operator: :^) }
|
|
121
|
-
|
|
122
|
-
describe :== do
|
|
123
|
-
example { subject.should be == subject }
|
|
124
|
-
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second') }
|
|
125
|
-
example { subject.should_not be == Mustermann.new('/foo/:name') }
|
|
126
|
-
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
describe :=== do
|
|
130
|
-
example { subject.should_not be === "/foo/bar" }
|
|
131
|
-
example { subject.should be === "/fox/bar" }
|
|
132
|
-
example { subject.should_not be === "/foo" }
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
describe :params do
|
|
136
|
-
example { subject.params("/foo/bar") .should be_nil }
|
|
137
|
-
example { subject.params("/fox/bar") .should be == { "first" => "fox", "second" => "bar" } }
|
|
138
|
-
example { subject.params("/foo") .should be_nil }
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
describe :match do
|
|
142
|
-
example { subject.should_not match("/foo/bar") }
|
|
143
|
-
example { subject.should match("/fox/bar") }
|
|
144
|
-
example { subject.should_not match("/foo") }
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
describe :expand do
|
|
148
|
-
example { subject.should_not respond_to(:expand) }
|
|
149
|
-
example { expect { subject.expand(name: 'bar') }.to raise_error(NotImplementedError) }
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
describe :inspect do
|
|
154
|
-
let(:sinatra) { Mustermann.new('x') }
|
|
155
|
-
let(:shell) { Mustermann.new('x', type: :shell) }
|
|
156
|
-
let(:identity) { Mustermann.new('x', type: :identity) }
|
|
157
|
-
|
|
158
|
-
example { (sinatra | shell) .inspect.should include('(sinatra:"x" | shell:"x")') }
|
|
159
|
-
example { (sinatra ^ shell) .inspect.should include('(sinatra:"x" ^ shell:"x")') }
|
|
160
|
-
example { (sinatra | shell | identity) .inspect.should include('(sinatra:"x" | shell:"x" | identity:"x")') }
|
|
161
|
-
example { (sinatra | shell & identity) .inspect.should include('(sinatra:"x" | (shell:"x" & identity:"x"))') }
|
|
162
|
-
end
|
|
163
|
-
end
|