uvrb 0.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.
Files changed (79) hide show
  1. data/.gitignore +17 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +13 -0
  5. data/Formula/libuv.rb +20 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +24 -0
  8. data/README.rdoc +70 -0
  9. data/Rakefile +29 -0
  10. data/examples/example +0 -0
  11. data/examples/example.c +37 -0
  12. data/examples/example.rb +29 -0
  13. data/examples/example_oop.rb +26 -0
  14. data/examples/python.py +1 -0
  15. data/examples/ruby.rb +1 -0
  16. data/examples/tcp_client_oop.rb +31 -0
  17. data/examples/tcp_example +0 -0
  18. data/examples/tcp_example.c +68 -0
  19. data/examples/tcp_example.rb +41 -0
  20. data/examples/tcp_example_oop.rb +43 -0
  21. data/examples/tcp_example_plain.rb +19 -0
  22. data/examples/tty_example.rb +20 -0
  23. data/features/async.feature +38 -0
  24. data/features/idle.feature +44 -0
  25. data/features/pipe.feature +150 -0
  26. data/features/prepare_and_check.feature +49 -0
  27. data/features/step_definitions/additional_cli_steps.rb +20 -0
  28. data/features/support/env.rb +6 -0
  29. data/lib/uv.rb +248 -0
  30. data/lib/uv/assertions.rb +24 -0
  31. data/lib/uv/async.rb +24 -0
  32. data/lib/uv/check.rb +27 -0
  33. data/lib/uv/error.rb +58 -0
  34. data/lib/uv/file.rb +221 -0
  35. data/lib/uv/file/stat.rb +35 -0
  36. data/lib/uv/filesystem.rb +335 -0
  37. data/lib/uv/fs_event.rb +21 -0
  38. data/lib/uv/handle.rb +65 -0
  39. data/lib/uv/idle.rb +27 -0
  40. data/lib/uv/listener.rb +26 -0
  41. data/lib/uv/loop.rb +326 -0
  42. data/lib/uv/net.rb +31 -0
  43. data/lib/uv/pipe.rb +47 -0
  44. data/lib/uv/prepare.rb +27 -0
  45. data/lib/uv/resource.rb +20 -0
  46. data/lib/uv/stream.rb +105 -0
  47. data/lib/uv/tasks.rb +27 -0
  48. data/lib/uv/tasks/mac.rb +23 -0
  49. data/lib/uv/tasks/unix.rb +23 -0
  50. data/lib/uv/tasks/win.rb +2 -0
  51. data/lib/uv/tcp.rb +162 -0
  52. data/lib/uv/timer.rb +48 -0
  53. data/lib/uv/tty.rb +30 -0
  54. data/lib/uv/types.rb +249 -0
  55. data/lib/uv/types/darwin_x64.rb +10 -0
  56. data/lib/uv/types/linux.rb +6 -0
  57. data/lib/uv/types/unix.rb +12 -0
  58. data/lib/uv/types/windows.rb +13 -0
  59. data/lib/uv/udp.rb +215 -0
  60. data/lib/uv/version.rb +3 -0
  61. data/lib/uvrb.rb +1 -0
  62. data/spec/shared_examples/handle.rb +54 -0
  63. data/spec/shared_examples/stream.rb +109 -0
  64. data/spec/spec_helper.rb +26 -0
  65. data/spec/uv/async_spec.rb +18 -0
  66. data/spec/uv/check_spec.rb +30 -0
  67. data/spec/uv/file_spec.rb +177 -0
  68. data/spec/uv/filesystem_spec.rb +246 -0
  69. data/spec/uv/fs_event_spec.rb +10 -0
  70. data/spec/uv/idle_spec.rb +30 -0
  71. data/spec/uv/loop_spec.rb +241 -0
  72. data/spec/uv/pipe_spec.rb +54 -0
  73. data/spec/uv/prepare_spec.rb +30 -0
  74. data/spec/uv/tcp_spec.rb +134 -0
  75. data/spec/uv/timer_spec.rb +61 -0
  76. data/spec/uv/tty_spec.rb +53 -0
  77. data/spec/uv/udp_spec.rb +190 -0
  78. data/uvrb.gemspec +28 -0
  79. metadata +247 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ html
6
+ pkg
7
+ doc
8
+ tmp
9
+ rerun.txt
10
+ Gemfile.lock
11
+ .bundle
12
+ .idea
13
+ *.rbc
14
+ .yardoc
15
+ bin
16
+ Gemfile-custom
17
+ ext/*
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "ext/libuv"]
2
+ path = ext/libuv
3
+ url = git://github.com/avalanche123/libuv.git
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ branches:
6
+ only:
7
+ - master
8
+ before_install:
9
+ - sudo apt-get install subversion
10
+ - git submodule update --init --recursive
11
+ - echo "yes" | gem uninstall ffi -a
12
+ before_script:
13
+ - rake libuv
data/Formula/libuv.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'formula'
2
+
3
+ class Libuv < Formula
4
+ homepage 'https://github.com/joyent/libuv'
5
+ head 'https://github.com/avalanche123/libuv.git'
6
+
7
+ def install
8
+ system "svn", "co", "http://gyp.googlecode.com/svn/trunk", "build/gyp"
9
+ system './gyp_uv -f xcode -Dtarget_arch=x64'
10
+ system 'xcodebuild', '-project', 'uv.xcodeproj', '-configuration', 'Release', '-target', 'All'
11
+
12
+ cd 'include' do
13
+ include.install Dir['*.h']
14
+ (include+"uv-private").install Dir['uv-private/*.h']
15
+ end
16
+
17
+ lib.install 'build/Release/libuv.a'
18
+ lib.install 'build/Release/libuv.dylib'
19
+ end
20
+ end
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2004-2012 Bulat Shakirzyanov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is furnished
8
+ to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
21
+ ===
22
+
23
+ This license applies to all parts of uvrb (Ruby FFI bindings for libuv only)
24
+ Libuv itself [is using Node license](https://github.com/joyent/libuv/blob/master/LICENSE)
data/README.rdoc ADDED
@@ -0,0 +1,70 @@
1
+ = uv.rb - libuv FFI bindings for Ruby
2
+ {<img src="https://secure.travis-ci.org/avalanche123/uvrb.png?branch=master" alt="Build Status" />}[http://travis-ci.org/avalanche123/uvrb]
3
+
4
+ {Libuv}[https://github.com/joyent/libuv] is a cross platform asynchronous IO implementation that powers NodeJS. It supports sockets, both UDP and TCP, filesystem operations, TTY, Pipes and other asynchronous primitives like timer, check, prepare and idle.
5
+
6
+ UV.rb is FFI Ruby bindings for libuv.
7
+
8
+ == Usage
9
+
10
+ Create a uv loop or use a default one
11
+
12
+ require 'uv'
13
+
14
+ loop = UV::Loop.default
15
+ # or
16
+ # loop = UV::Loop.new
17
+
18
+ timer = loop.timer
19
+ timer.start(50000, 0) do |error|
20
+ p error if error
21
+ puts "50 seconds passed"
22
+ timer.close
23
+ end
24
+
25
+ loop.run
26
+
27
+ Find more examples in examples directory
28
+
29
+ == Installation
30
+
31
+ gem install uvrb
32
+
33
+ or
34
+
35
+ git clone ...
36
+ cd ...
37
+ bundle install
38
+
39
+ Make sure you have libuv compiled and a shared library (`.dylib`|`.so`|`.dll`) file available in your lib path.
40
+
41
+ To compile libuv from a local submodule version:
42
+
43
+ git submodule update --init
44
+ rake libuv
45
+
46
+ Or to compile libuv on mac, you can install provided Homebrew formula by running:
47
+
48
+ brew install Formula/libuv.rb --HEAD
49
+
50
+ == What's supported
51
+
52
+ * TCP
53
+ * UDP
54
+ * TTY
55
+ * Pipe
56
+ * Timer
57
+ * Prepare
58
+ * Check
59
+ * Idle
60
+ * Async
61
+ * Filesystem
62
+ * File
63
+ * FSEvent
64
+ * Errors
65
+
66
+ == TODO
67
+
68
+ * Port rest of libuv - ares, getaddrinfo, process, work queue, mutexes and locks
69
+ * Tests tests tests
70
+ * Docs docs docs
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'cucumber'
6
+ require 'cucumber/rake/task'
7
+ require 'rdoc/task'
8
+ require 'ffi'
9
+ require 'rake/clean'
10
+ require 'uv/tasks'
11
+
12
+ RSpec::Core::RakeTask.new
13
+
14
+ Cucumber::Rake::Task.new(:features)
15
+
16
+ RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", :rerdoc => "rdoc:force") do |rd|
17
+ rd.main = "README.rdoc"
18
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
19
+ rd.options << "--title=UV.rb - libuv bindings for Ruby"
20
+ rd.options << "--markup=tomdoc"
21
+ end
22
+
23
+ task :test => [:spec, :features]
24
+ task :default => :test
25
+
26
+ desc "Compile libuv from submodule"
27
+ task :libuv => ["ext/libuv.#{FFI::Platform::LIBSUFFIX}"]
28
+
29
+ CLOBBER.include("ext/libuv.#{FFI::Platform::LIBSUFFIX}")
data/examples/example ADDED
Binary file
@@ -0,0 +1,37 @@
1
+ # include <uv.h>
2
+ # include <stdio.h>
3
+
4
+ static int count = 0;
5
+
6
+ void close_cb(uv_handle_t* handle)
7
+ {
8
+ // free(handle);
9
+ }
10
+
11
+ void timer_cb(uv_timer_t* timer, int status)
12
+ {
13
+ puts("1");
14
+ if (count >= 10) {
15
+ // uv_unref(uv_default_loop());
16
+ // uv_timer_stop(timer);
17
+ uv_close((uv_handle_t*)timer, close_cb);
18
+ }
19
+ count++;
20
+ }
21
+
22
+ int main(int argc, char* argv[])
23
+ {
24
+ uv_timer_t timer;
25
+ printf("sizeof timer is %ld\n", sizeof(uv_timer_t));
26
+ printf("sizeof tcp is %ld\n", sizeof(uv_tcp_t));
27
+ printf("sizeof handle is %ld\n", sizeof(uv_handle_t));
28
+ printf("sizeof tty is %ld\n", sizeof(uv_tty_t));
29
+ printf("sizeof udp is %ld\n", sizeof(uv_udp_t));
30
+ // printf("sizeof timer is %ld\n", sizeof(uv_timer_t));
31
+ // printf("sizeof timer is %ld\n", sizeof(uv_timer_t));
32
+
33
+ uv_timer_init(uv_default_loop(), &timer);
34
+ uv_timer_start(&timer, timer_cb, 1, 1);
35
+ uv_run(uv_default_loop());
36
+ uv_loop_delete(uv_default_loop());
37
+ }
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'uvrb'
4
+
5
+ start = Time.now
6
+
7
+ loop = UV.default_loop
8
+
9
+ timer = UV.create_handle(:uv_timer)
10
+ # timer = FFI::MemoryPointer.new(UV::Timer, UV::Timer.size, 1)
11
+ count = 0
12
+ UV.timer_init(loop, timer)
13
+ $stdout << "\r\n"
14
+
15
+ close_cb = proc {|ptr| UV.free(ptr); $stdout << "\n"; }
16
+
17
+ timer_cb = Proc.new do |ptr, status|
18
+ $stdout << "#{count}\r"
19
+ if count >= 10000
20
+ UV.close(ptr, close_cb)
21
+ end
22
+ count += 1
23
+ end
24
+
25
+ UV.timer_start(timer, timer_cb, 1, 1)
26
+ UV.run(loop)
27
+ UV.loop_delete(loop)
28
+
29
+ puts Time.now - start
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'uvrb'
4
+
5
+ start = Time.now
6
+
7
+ loop = UV::Loop.default
8
+
9
+ count = 0
10
+ timer = loop.timer
11
+ $stdout << "\r\n"
12
+
13
+ timer.start(1, 1) do |status|
14
+ $stdout << "\r#{count}"
15
+ if count >= 10000
16
+ timer.close do
17
+ $stdout << "\n"
18
+ end
19
+ end
20
+ count += 1
21
+ end
22
+
23
+ loop.run
24
+ $stdout << "\n"
25
+
26
+ puts Time.now - start
@@ -0,0 +1 @@
1
+ print('hello world')
data/examples/ruby.rb ADDED
@@ -0,0 +1 @@
1
+ puts 'hello world'
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'uvrb'
4
+
5
+ loop = UV::Loop.default
6
+
7
+ client = loop.tcp
8
+
9
+ client.connect("127.0.0.1", 10000) do |err|
10
+ if err
11
+ p err
12
+ exit 1
13
+ end
14
+ client.write("GET /\r\nHost: localhost:10000\r\nAccept: *\r\n\r\n\n") do |err|
15
+ if err
16
+ p err
17
+ exit 1
18
+ end
19
+ client.start_read do |data, err|
20
+ if err
21
+ p err
22
+ exit 1
23
+ end
24
+ puts data
25
+ client.close
26
+ end
27
+ end
28
+ # client.close
29
+ end
30
+
31
+ loop.run
Binary file
@@ -0,0 +1,68 @@
1
+ #include <uv.h>
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+
5
+ #define RESPONSE \
6
+ "HTTP/1.1 200 OK\r\n" \
7
+ "Content-Type: text/plain\r\n" \
8
+ "Content-Length: 12\r\n" \
9
+ "\r\n" \
10
+ "hello world\n"
11
+
12
+ static uv_buf_t resbuf;
13
+
14
+ void on_close(uv_handle_t* handle)
15
+ {
16
+ free(handle);
17
+ }
18
+
19
+ void after_shutdown(uv_shutdown_t* req, int status) {
20
+ free(req);
21
+ uv_close((uv_handle_t*)req->handle, on_close);
22
+ }
23
+
24
+ void after_write(uv_write_t* req, int status) {
25
+ uv_shutdown_t* shutdown_req = malloc(sizeof(uv_shutdown_t));
26
+
27
+ free(req);
28
+ // uv_shutdown(shutdown_req, req->handle, after_shutdown);
29
+ uv_close((uv_handle_t*)req->handle, on_close);
30
+ }
31
+
32
+ void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf)
33
+ {
34
+ uv_write_t* write_req = malloc(sizeof(uv_write_t));
35
+
36
+ uv_write(write_req, tcp, &resbuf, 1, after_write);
37
+ }
38
+
39
+ uv_buf_t on_alloc(uv_handle_t* client, size_t suggested_size)
40
+ {
41
+ return uv_buf_init(malloc(suggested_size), suggested_size);
42
+ }
43
+
44
+ void on_connect(uv_stream_t* server, int status)
45
+ {
46
+ uv_tcp_t* client = malloc(sizeof(uv_tcp_t));
47
+
48
+ uv_tcp_init(uv_default_loop(), client);
49
+ uv_accept(server, (uv_stream_t*) client);
50
+ uv_read_start((uv_stream_t*) client, on_alloc, on_read);
51
+ }
52
+
53
+ int main(int argc, char* argv[])
54
+ {
55
+ uv_tcp_t tcp;
56
+
57
+ resbuf.base = RESPONSE;
58
+ resbuf.len = sizeof(RESPONSE);
59
+
60
+ uv_tcp_init(uv_default_loop(), &tcp);
61
+
62
+ struct sockaddr_in address = uv_ip4_addr("0.0.0.0", 10000);
63
+ uv_tcp_bind(&tcp, address);
64
+ uv_listen((uv_stream_t*)&tcp, 128, on_connect);
65
+
66
+ uv_run(uv_default_loop());
67
+ uv_loop_delete(uv_default_loop());
68
+ }
@@ -0,0 +1,41 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'uvrb'
4
+
5
+ def on_read(client, nread, buf)
6
+ if nread == -1
7
+ ptr = UV.last_error(@loop)
8
+ p [UV.err_name(ptr), UV.strerror(ptr)]
9
+ else
10
+ puts buf[:base].read_string(nread)
11
+ end
12
+ UV.free(buf[:base])
13
+ UV.close(client, proc {|client| })
14
+ end
15
+
16
+ def on_alloc(handle, suggested_size)
17
+ UV.buf_init(UV.malloc(suggested_size), suggested_size)
18
+ end
19
+
20
+ def on_connect(server, status)
21
+ client = FFI::AutoPointer.new(UV.create_handle(:uv_tcp), UV.method(:free))
22
+ UV.tcp_init(@loop, client)
23
+
24
+ UV.accept(server, client)
25
+ UV.read_start(client, method(:on_alloc), method(:on_read))
26
+ end
27
+
28
+ def main
29
+ @loop = UV.default_loop
30
+
31
+ server = FFI::AutoPointer.new(UV.create_handle(:uv_tcp), UV.method(:free))
32
+ UV.tcp_init(@loop, server)
33
+
34
+ UV.tcp_bind(server, UV.ip4_addr('0.0.0.0', 10000))
35
+ UV.listen(server, 128, method(:on_connect))
36
+
37
+ UV.run(@loop)
38
+ UV.loop_delete(@loop)
39
+ end
40
+
41
+ main