nyara 0.0.1.pre.8 → 0.0.1.pre.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nyara +17 -0
  3. data/changes +12 -0
  4. data/copying +10 -0
  5. data/ext/event.c +78 -68
  6. data/ext/extconf.rb +7 -0
  7. data/ext/inc/epoll.h +12 -20
  8. data/ext/inc/kqueue.h +8 -18
  9. data/ext/nyara.c +17 -2
  10. data/ext/nyara.h +7 -3
  11. data/ext/request.c +35 -7
  12. data/ext/request.h +3 -0
  13. data/ext/request_parse.c +26 -7
  14. data/ext/url_encoded.c +22 -11
  15. data/lib/nyara/command.rb +79 -0
  16. data/lib/nyara/config.rb +88 -26
  17. data/lib/nyara/controller.rb +175 -110
  18. data/lib/nyara/cookie.rb +2 -2
  19. data/lib/nyara/flash.rb +3 -2
  20. data/lib/nyara/hashes/config_hash.rb +18 -5
  21. data/lib/nyara/hashes/header_hash.rb +3 -2
  22. data/lib/nyara/hashes/param_hash.rb +2 -0
  23. data/lib/nyara/mime_types.rb +1 -0
  24. data/lib/nyara/nyara.rb +47 -25
  25. data/lib/nyara/part.rb +85 -39
  26. data/lib/nyara/request.rb +21 -4
  27. data/lib/nyara/route.rb +167 -8
  28. data/lib/nyara/session.rb +29 -22
  29. data/lib/nyara/templates/Gemfile +4 -0
  30. data/lib/nyara/templates/Rakefile +1 -0
  31. data/lib/nyara/templates/config/boot.rb +0 -0
  32. data/lib/nyara/templates/config/database.yml +28 -0
  33. data/lib/nyara/templates/config/development.rb +0 -0
  34. data/lib/nyara/templates/config/production.rb +0 -0
  35. data/lib/nyara/templates/config/session.key +1 -0
  36. data/lib/nyara/templates/config/test.rb +0 -0
  37. data/lib/nyara/templates/public/robot.txt +0 -0
  38. data/lib/nyara/templates/spec/spec_helper.rb +0 -0
  39. data/lib/nyara/test.rb +14 -11
  40. data/lib/nyara/view.rb +16 -9
  41. data/nyara.gemspec +18 -5
  42. data/rakefile +8 -2
  43. data/readme.md +26 -15
  44. data/spec/apps/connect.rb +1 -0
  45. data/spec/command_spec.rb +46 -0
  46. data/spec/config_spec.rb +14 -4
  47. data/spec/controller_spec.rb +24 -0
  48. data/spec/ext_route_spec.rb +3 -3
  49. data/spec/flash_spec.rb +0 -4
  50. data/spec/integration_spec.rb +63 -2
  51. data/spec/{part_spec.rb → multipart_spec.rb} +18 -0
  52. data/spec/raw_requests/multipart +20 -0
  53. data/spec/request_delegate_spec.rb +4 -0
  54. data/spec/request_spec.rb +8 -0
  55. data/spec/{route_entry_spec.rb → route_spec.rb} +58 -3
  56. data/spec/session_spec.rb +4 -4
  57. data/spec/spec_helper.rb +14 -7
  58. data/tools/hello.rb +21 -3
  59. metadata +42 -10
  60. data/lib/nyara/route_entry.rb +0 -111
@@ -1,6 +1,12 @@
1
1
  require_relative "spec_helper"
2
2
 
3
3
  class TestController < Nyara::Controller
4
+ attr_reader :before_invoked
5
+
6
+ before ":delete" do
7
+ @before_invoked = true
8
+ end
9
+
4
10
  meta '#index'
5
11
  get '/' do
6
12
  content_type 'txt'
@@ -12,6 +18,11 @@ class TestController < Nyara::Controller
12
18
  redirect_to '#index'
13
19
  end
14
20
 
21
+ post '/upload' do
22
+ params
23
+ # no response
24
+ end
25
+
15
26
  put '/send_file/%z' do |name|
16
27
  send_file Nyara.config.views_path name
17
28
  end
@@ -19,6 +30,16 @@ class TestController < Nyara::Controller
19
30
  delete '/render' do
20
31
  render 'edit.slim'
21
32
  end
33
+
34
+ patch '/stream' do
35
+ view = stream 'edit.slim'
36
+ view.resume
37
+ view.end
38
+ end
39
+
40
+ options '/error' do
41
+ raise 'error'
42
+ end
22
43
  end
23
44
 
24
45
  class MyTest
@@ -30,14 +51,23 @@ module Nyara
30
51
  before :all do
31
52
  configure do
32
53
  reset
33
- # set :env, 'test'
34
54
  map '/', TestController
35
55
  set :root, __dir__
56
+ set :logger, false
36
57
  end
37
58
  Nyara.setup
38
59
  @test = MyTest.new
39
60
  end
40
61
 
62
+ before :each do
63
+ GC.stress = false
64
+ end
65
+
66
+ it "decodes cookie" do
67
+ @test.get "/", {"Cookie" => 'foo=bar'}
68
+ assert_equal 'bar', @test.env.cookie['foo']
69
+ end
70
+
41
71
  it "response" do
42
72
  @test.get "/", {'Xample' => 'résumé'}
43
73
  assert @test.response.success?
@@ -64,7 +94,7 @@ module Nyara
64
94
  assert_equal '3', @test.session['a']
65
95
  end
66
96
 
67
- it "send file" do
97
+ it "send_file" do
68
98
  @test.put "/send_file/layout.erb"
69
99
  data = File.read Nyara.config.views_path('layout.erb')
70
100
  assert_equal data, @test.response.body
@@ -75,6 +105,26 @@ module Nyara
75
105
  assert_include @test.response.body, "slim:edit"
76
106
  end
77
107
 
108
+ it "stream" do
109
+ @test.patch '/stream'
110
+ assert_include @test.response.body, "slim:edit"
111
+ end
112
+
113
+ it "error" do
114
+ @test.options '/error'
115
+ assert_equal 500, @test.response.status
116
+ assert_equal false, @test.response.success?
117
+ end
118
+
119
+ it "multipart upload" do
120
+ data = File.binread(__dir__ + '/raw_requests/multipart')
121
+ @test.env.process_request_data data
122
+ param = @test.env.request.param
123
+ assert_equal 'foo', param['foo']
124
+ assert_equal 'bar', param['bar']['data']
125
+ assert_equal 'baz', param['baz']['你好']['data']
126
+ end
127
+
78
128
  context "public static content" do
79
129
  it "found file" do
80
130
  @test.get "/index.html"
@@ -98,5 +148,16 @@ module Nyara
98
148
  assert_equal 404, @test.response.status
99
149
  end
100
150
  end
151
+
152
+ context "before / after" do
153
+ it "invokes lifecycle callback" do
154
+ @test.get '/'
155
+ assert_nil @test.env.controller.before_invoked
156
+ assert @test.request.message_complete?
157
+
158
+ @test.delete "/render"
159
+ assert @test.env.controller.before_invoked
160
+ end
161
+ end
101
162
  end
102
163
  end
@@ -1,6 +1,18 @@
1
1
  require_relative "spec_helper"
2
2
 
3
3
  module Nyara
4
+ describe Ext do
5
+ it ".parse_multipart_boundary" do
6
+ header = HeaderHash.new
7
+ boundary = Ext.parse_multipart_boundary header
8
+ assert_nil boundary
9
+
10
+ header['Content-Type'] = 'multipart/form-data; boundary=----WebKitFormBoundaryn3ghstHtZs1Z3VTi'
11
+ boundary = Ext.parse_multipart_boundary header
12
+ assert_equal '------WebKitFormBoundaryn3ghstHtZs1Z3VTi', boundary
13
+ end
14
+ end
15
+
4
16
  describe Part do
5
17
  it "bottom case" do
6
18
  p = Part.new({})
@@ -48,5 +60,11 @@ module Nyara
48
60
  p.final
49
61
  assert_equal "a \x3F \x04", p['data']
50
62
  end
63
+
64
+ it "inspec and pp helpers" do
65
+ p = Part.new Hash.new
66
+ p.inspect
67
+ p.pretty_inspect
68
+ end
51
69
  end
52
70
  end
@@ -0,0 +1,20 @@
1
+ POST /upload HTTP/1.1
2
+ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
3
+ Content-Length: 431
4
+ Content-Type: multipart/form-data; boundary=----WebKitFormBoundarykkJ0CDXe4jYnH95C
5
+
6
+ ------WebKitFormBoundarykkJ0CDXe4jYnH95C
7
+ Content-Disposition: form-data; name="bar"; filename="bar"
8
+ Content-Type: application/octet-stream
9
+
10
+ bar
11
+ ------WebKitFormBoundarykkJ0CDXe4jYnH95C
12
+ Content-Disposition: form-data; name="baz[你好]"; filename="baz.txt"
13
+ Content-Type: text/plain
14
+
15
+ baz
16
+ ------WebKitFormBoundarykkJ0CDXe4jYnH95C
17
+ Content-Disposition: form-data; name="foo"
18
+
19
+ foo
20
+ ------WebKitFormBoundarykkJ0CDXe4jYnH95C--
@@ -56,6 +56,10 @@ module Nyara
56
56
  Ext.request_set_fd @request, @server.fileno
57
57
  end
58
58
 
59
+ after :each do
60
+ Ext.request_unset_fd @request
61
+ end
62
+
59
63
  def receive_header
60
64
  @c.send_header
61
65
  @server.close_write
data/spec/request_spec.rb CHANGED
@@ -58,6 +58,14 @@ module Nyara
58
58
  assert_equal %w[utf-8 iso-8859-1], @request.accept_charset
59
59
  end
60
60
 
61
+ it "#param" do
62
+ @request_attrs[:method_num] = HTTP_METHODS['POST']
63
+ @request_attrs[:body] = "foo[bar]=baz"
64
+ request_set_attrs
65
+ assert_equal({'foo' => {'bar' => 'baz'}}, @request.param)
66
+ assert_equal 'baz', @request.param[:foo][:bar]
67
+ end
68
+
61
69
  def request_set_attrs
62
70
  Ext.request_set_attrs @request, @request_attrs
63
71
  end
@@ -1,9 +1,9 @@
1
1
  require_relative "spec_helper"
2
2
 
3
3
  module Nyara
4
- describe RouteEntry do
4
+ describe Route do
5
5
  before :each do
6
- @r = RouteEntry.new
6
+ @r = Route.new
7
7
  end
8
8
 
9
9
  it "#compile prefix, suffix and conv" do
@@ -27,7 +27,7 @@ module Nyara
27
27
  end
28
28
 
29
29
  it "#set_accept_exts" do
30
- r = RouteEntry.new
30
+ r = Route.new
31
31
  r.set_accept_exts ['html', :js]
32
32
  assert_equal [%w"text html html", %w"application javascript js"], r.accept_mimes
33
33
  assert_equal ({'html'=>true, 'js'=>true}), r.accept_exts
@@ -70,5 +70,60 @@ module Nyara
70
70
  assert_equal '/', prefix
71
71
  assert_equal nil, suffix
72
72
  end
73
+
74
+ context "#matched_lifecycle_callbacks" do
75
+ before :each do
76
+ @r.http_method = HTTP_METHODS['DELETE']
77
+ @r.classes = %w[.foo .bar]
78
+ @r.id = '#foo'
79
+ end
80
+
81
+ it "returns empty set when filters empty" do
82
+ cbs = @r.matched_lifecycle_callbacks({})
83
+ assert_equal [], cbs
84
+ end
85
+
86
+ it "works" do
87
+ cbs = @r.matched_lifecycle_callbacks ':DELETE' => [:delete], '#foo' => [:foo], '.bar' => [:bar], '#baz' => [:baz]
88
+ assert_equal [:delete, :foo, :bar], cbs
89
+ end
90
+
91
+ it "when classes not set" do
92
+ @r.classes = nil
93
+ cbs = @r.matched_lifecycle_callbacks ':DELETE' => [:delete], '#foo' => [:foo], '.bar' => [:bar], '#baz' => [:baz]
94
+ assert_equal [:delete, :foo], cbs
95
+ end
96
+ end
97
+
98
+ context ".canonicalize_callback_selector" do
99
+ it "works" do
100
+ s = Route.canonicalize_callback_selector '#a'
101
+ assert_equal '#a', s
102
+ s = Route.canonicalize_callback_selector '.b'
103
+ assert_equal '.b', s
104
+ end
105
+
106
+ it "checks bad selectors" do
107
+ assert_raise ArgumentError do
108
+ Route.canonicalize_callback_selector ''
109
+ end
110
+ assert_raise ArgumentError do
111
+ Route.canonicalize_callback_selector '*'
112
+ end
113
+ assert_raise ArgumentError do
114
+ Route.canonicalize_callback_selector 'a#b'
115
+ end
116
+ end
117
+
118
+ it "removes classes and pseudo classes after id" do
119
+ s = Route.canonicalize_callback_selector "#a.b:c"
120
+ assert_equal '#a', s
121
+ end
122
+
123
+ it "does not remove pseudo class after class, and upcases it" do
124
+ s = Route.canonicalize_callback_selector ".b:c"
125
+ assert_equal '.b:C', s
126
+ end
127
+ end
73
128
  end
74
129
  end
data/spec/session_spec.rb CHANGED
@@ -21,19 +21,19 @@ module Nyara
21
21
 
22
22
  init_configure_with :session, :secure, false
23
23
  line = Session.encode_set_cookie @session, true
24
- assert_not_includes line, 'Secure'
24
+ assert_not_include line, 'Secure'
25
25
 
26
26
  init_configure_with :session, :secure, nil
27
27
  line = Session.encode_set_cookie @session, true
28
28
  assert_includes line, '; Secure'
29
29
  line = Session.encode_set_cookie @session, false
30
- assert_not_includes line, 'Secure'
30
+ assert_not_include line, 'Secure'
31
31
  end
32
32
 
33
33
  it "adds Expires" do
34
34
  init_configure_with :session, :expire, nil
35
35
  line = Session.encode_set_cookie @session, false
36
- assert_not_includes line, 'Expires'
36
+ assert_not_include line, 'Expires'
37
37
 
38
38
  init_configure_with :session, :expires, 30 * 60
39
39
  line = Session.encode_set_cookie @session, false
@@ -107,7 +107,7 @@ module Nyara
107
107
 
108
108
  session_data = cookie[Session.name].split('/')[1]
109
109
  if session_data
110
- assert_not_includes Base64.urlsafe_decode64(session_data), 'world'
110
+ assert_not_include Base64.urlsafe_decode64(session_data), 'world'
111
111
  end
112
112
 
113
113
  session2 = Session.decode cookie
data/spec/spec_helper.rb CHANGED
@@ -21,6 +21,17 @@ end
21
21
  require_relative "../lib/nyara/nyara"
22
22
  require_relative "../lib/nyara/test"
23
23
 
24
+ def stdout(&block)
25
+ original_stdout = $stdout
26
+ $stdout = fake = StringIO.new
27
+ begin
28
+ yield
29
+ ensure
30
+ $stdout = original_stdout
31
+ end
32
+ fake.string
33
+ end
34
+
24
35
  RSpec.configure do |config|
25
36
  config.expect_with :stdlib
26
37
  if config.formatters.first.class.to_s =~ /TextMate/
@@ -54,9 +65,10 @@ RSpec.configure do |config|
54
65
  obj
55
66
  end
56
67
  end
68
+ end
57
69
 
58
- elsif config.formatters.any?{|f|f.class.to_s =~ /Document/}
59
- puts "Enabling GC.stress with documentation formatter"
70
+ if ENV['STRESS']
71
+ puts "Enabling GC.stress mode"
60
72
 
61
73
  config.before :each do
62
74
  GC.stress = true
@@ -65,10 +77,5 @@ RSpec.configure do |config|
65
77
  config.after :each do
66
78
  GC.stress = false
67
79
  end
68
-
69
80
  end
70
81
  end
71
-
72
- configure do
73
- set :env, 'test'
74
- end
data/tools/hello.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  require_relative "../lib/nyara/nyara"
2
2
  # require "open-uri"
3
- # require "pry"
3
+ require "pry"
4
4
 
5
5
  configure do
6
6
  # set :env, 'production'
7
7
  # set :workers, 3
8
8
  map '/', 'my'
9
+ # set :logger, false
9
10
  end
10
11
 
11
12
  class MyController < Nyara::Controller
12
13
  get '/' do
14
+ p param
13
15
  send_string 'hello world'
14
16
  end
15
17
 
@@ -17,8 +19,24 @@ class MyController < Nyara::Controller
17
19
  exit
18
20
  end
19
21
 
20
- get '/redi' do
21
- redirect '/'
22
+ get '/form' do
23
+ send_string <<-HTML
24
+ <form action="/form" enctype="multipart/form-data" method="post" accept-charset="utf-8">
25
+ bar
26
+ <input type="file" name="bar">
27
+ <br>
28
+ baz
29
+ <input type="file" name="baz[你好]">
30
+ <br>
31
+ foo<input name="foo">
32
+ <br>
33
+ </form>
34
+ HTML
35
+ end
36
+
37
+ post '/form' do
38
+ b = request.body
39
+ binding.pry
22
40
  end
23
41
  end
24
42
 
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nyara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre.8
4
+ version: 0.0.1.pre.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zete Lui
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-06 00:00:00.000000000 Z
11
+ date: 2013-07-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Fast, slim and fuzzy ruby web framework + server, based on preforked
14
- event queue and Fiber. NO rack NOR eventmachine are used.
13
+ description: Fast and fuzzy ruby web framework + server
15
14
  email: nobody@example.com
16
- executables: []
15
+ executables:
16
+ - nyara
17
17
  extensions:
18
18
  - ext/extconf.rb
19
19
  extra_rdoc_files: []
@@ -21,11 +21,14 @@ files:
21
21
  - rakefile
22
22
  - nyara.gemspec
23
23
  - readme.md
24
+ - copying
25
+ - changes
24
26
  - example/factorial.rb
25
27
  - example/hello.rb
26
28
  - example/project.rb
27
29
  - example/stream.rb
28
30
  - ext/extconf.rb
31
+ - lib/nyara/command.rb
29
32
  - lib/nyara/config.rb
30
33
  - lib/nyara/controller.rb
31
34
  - lib/nyara/controllers/public_controller.rb
@@ -47,8 +50,12 @@ files:
47
50
  - lib/nyara/patches/to_query.rb
48
51
  - lib/nyara/request.rb
49
52
  - lib/nyara/route.rb
50
- - lib/nyara/route_entry.rb
51
53
  - lib/nyara/session.rb
54
+ - lib/nyara/templates/config/boot.rb
55
+ - lib/nyara/templates/config/development.rb
56
+ - lib/nyara/templates/config/production.rb
57
+ - lib/nyara/templates/config/test.rb
58
+ - lib/nyara/templates/spec/spec_helper.rb
52
59
  - lib/nyara/test.rb
53
60
  - lib/nyara/view.rb
54
61
  - lib/nyara/view_handlers/erb.rb
@@ -57,7 +64,9 @@ files:
57
64
  - lib/nyara/view_handlers/slim.rb
58
65
  - lib/nyara.rb
59
66
  - spec/apps/connect.rb
67
+ - spec/command_spec.rb
60
68
  - spec/config_spec.rb
69
+ - spec/controller_spec.rb
61
70
  - spec/cpu_counter_spec.rb
62
71
  - spec/evented_io_spec.rb
63
72
  - spec/ext_mime_match_spec.rb
@@ -67,7 +76,7 @@ files:
67
76
  - spec/hashes_spec.rb
68
77
  - spec/integration_spec.rb
69
78
  - spec/mini_support_spec.rb
70
- - spec/part_spec.rb
79
+ - spec/multipart_spec.rb
71
80
  - spec/path_helper_spec.rb
72
81
  - spec/performance/escape.rb
73
82
  - spec/performance/layout_render.rb
@@ -77,7 +86,7 @@ files:
77
86
  - spec/performance_spec.rb
78
87
  - spec/request_delegate_spec.rb
79
88
  - spec/request_spec.rb
80
- - spec/route_entry_spec.rb
89
+ - spec/route_spec.rb
81
90
  - spec/session_spec.rb
82
91
  - spec/spec_helper.rb
83
92
  - spec/url_encoded_spec.rb
@@ -117,6 +126,7 @@ files:
117
126
  - spec/performance/page.slim
118
127
  - spec/public/empty file.html
119
128
  - spec/public/index.html
129
+ - spec/raw_requests/multipart
120
130
  - spec/views/edit.haml
121
131
  - spec/views/edit.slim
122
132
  - spec/views/index.liquid
@@ -127,12 +137,33 @@ files:
127
137
  - ext/http-parser/CONTRIBUTIONS
128
138
  - ext/http-parser/LICENSE-MIT
129
139
  - ext/multipart-parser-c/README.md
140
+ - lib/nyara/templates/config/database.yml
141
+ - lib/nyara/templates/config/session.key
142
+ - lib/nyara/templates/Gemfile
143
+ - lib/nyara/templates/public/robot.txt
144
+ - lib/nyara/templates/Rakefile
145
+ - bin/nyara
130
146
  homepage: https://github.com/luikore/nyara
131
147
  licenses:
132
148
  - BSD 3-Clause
133
149
  metadata: {}
134
150
  post_install_message:
135
- rdoc_options: []
151
+ rdoc_options:
152
+ - -v
153
+ - --markup=markdown
154
+ - --main
155
+ - readme.md
156
+ - --line-numbers
157
+ - -x
158
+ - ext/http-parser/.*
159
+ - -x
160
+ - ext/multipart-parser-c/.*
161
+ - -x
162
+ - ext/inc/.*
163
+ - -x
164
+ - .*\.o
165
+ - -x
166
+ - .*\.bundle
136
167
  require_paths:
137
168
  - lib
138
169
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -150,5 +181,6 @@ rubyforge_project:
150
181
  rubygems_version: 2.0.3
151
182
  signing_key:
152
183
  specification_version: 4
153
- summary: Fast, slim and fuzzy ruby web framework + server
184
+ summary: Fast and fuzzy ruby web framework + server
154
185
  test_files: []
186
+ has_rdoc:
@@ -1,111 +0,0 @@
1
- module Nyara
2
- class RouteEntry
3
- REQUIRED_ATTRS = [:http_method, :scope, :prefix, :suffix, :controller, :id, :conv]
4
- attr_reader *REQUIRED_ATTRS
5
- attr_writer :http_method, :id
6
- # stores symbol for C conenience, and returns string for Ruby side goodness
7
- def id
8
- @id.to_s
9
- end
10
-
11
- # optional
12
- attr_accessor :accept_exts, :accept_mimes
13
-
14
- # tmp
15
- attr_accessor :path, :blk
16
-
17
- def initialize &p
18
- instance_eval &p if p
19
- end
20
-
21
- def path_template
22
- File.join @scope, (@path.gsub '%z', '%s')
23
- end
24
-
25
- # compute prefix, suffix, conv
26
- # NOTE route_entries may be inherited, so late-setting controller is necessary
27
- def compile controller, scope
28
- @controller = controller
29
- @scope = scope
30
-
31
- path = scope.sub /\/?$/, @path
32
- if path.empty?
33
- path = '/'
34
- end
35
- @prefix, suffix = analyse_path path
36
- @suffix, @conv = compile_re suffix
37
- end
38
-
39
- # compute accept_exts, accept_mimes
40
- def set_accept_exts a
41
- @accept_exts = {}
42
- @accept_mimes = []
43
- if a
44
- a.each do |e|
45
- e = e.to_s.dup.freeze
46
- @accept_exts[e] = true
47
- if MIME_TYPES[e]
48
- v1, v2 = MIME_TYPES[e].split('/')
49
- raise "bad mime type: #{MIME_TYPES[e].inspect}" if v1.nil? or v2.nil?
50
- @accept_mimes << [v1, v2, e]
51
- end
52
- end
53
- end
54
- @accept_mimes = nil if @accept_mimes.empty?
55
- @accept_exts = nil if @accept_exts.empty?
56
- end
57
-
58
- def validate
59
- REQUIRED_ATTRS.each do |attr|
60
- unless instance_variable_get("@#{attr}")
61
- raise ArgumentError, "missing #{attr}"
62
- end
63
- end
64
- raise ArgumentError, "id must be symbol" unless @id.is_a?(Symbol)
65
- end
66
-
67
- # private
68
-
69
- # returns [str_re, conv]
70
- def compile_re suffix
71
- return ['', []] unless suffix
72
- conv = []
73
- re_segs = suffix.split(/(?<=%[dfsuxz])|(?=%[dfsuxz])/).map do |s|
74
- case s
75
- when '%d'
76
- conv << :to_i
77
- '(-?[0-9]+)'
78
- when '%f'
79
- conv << :to_f
80
- # just copied from scanf
81
- '([-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))'
82
- when '%u'
83
- conv << :to_i
84
- '([0-9]+)'
85
- when '%x'
86
- conv << :hex
87
- '(\h+)'
88
- when '%s'
89
- conv << :to_s
90
- '([^/]+)'
91
- when '%z'
92
- conv << :to_s
93
- '(.*)'
94
- else
95
- Regexp.quote s
96
- end
97
- end
98
- ["^#{re_segs.join}$", conv]
99
- end
100
-
101
- # split the path into 2 parts: <br>
102
- # fixed prefix and variable suffix
103
- def analyse_path path
104
- raise 'path must contain no new line' if path.index "\n"
105
- raise 'path must start with /' unless path.start_with? '/'
106
- path = path.sub(/\/$/, '') if path != '/'
107
-
108
- path.split(/(?=%[dfsuxz])/, 2)
109
- end
110
- end
111
- end