faster_path 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 145d0ead52899b0287c3854351371ed572753abf
4
- data.tar.gz: 26a96e5e5120c5697f44d1dd2aae6d0780f361c0
3
+ metadata.gz: f92e6ae04b2843b4ebbe35489a57a3761e549c5a
4
+ data.tar.gz: cf6a2778380a40beae6bd75f399c8e3ba3945c57
5
5
  SHA512:
6
- metadata.gz: d05a6334782f4994a0ff6d25f4b9e3851c08fc26dec8e32e8533ea459f602fe9df0ec2ac8a8d557ad4d278b713d7073db0ec641754f0537416e9bfa1ee3decf6
7
- data.tar.gz: 98e70ecc789fbdb19d945f07a0f3c2ab2844c719ef7d41794aace5e659a3b9fa0353d4ca409bea0a28f1549d0db698f494a1d819d7de2cf2158a5fa6def61dd9
6
+ metadata.gz: 0924b343e18fbe1444b5e1ebe8def4f7856dfe99298bd24b3ba1e5d1b2367900d6464063ba9c0b6508ea75799cee37085531d63627937e0a1b620e7002496742
7
+ data.tar.gz: 834d364fd05f66a698964e9fd9c9f71717a8026f114f04f0349fe5e6c700572e1f39d86b1083cc1b475c659605d13b708f116c2f4baf9075be3976d18b466c47
data/README.md CHANGED
@@ -86,7 +86,7 @@ Current methods implemented:
86
86
  |FasterPath Rust Implementation|Ruby 2.3.1 Implementation|Performance Improvement|
87
87
  |---|---|:---:|
88
88
  | `FasterPath.absolute?` | `Pathname#absolute?` | 1234.6% |
89
- | `FasterPath.chop_basename` | `Pathname#chop_basename` | 27.5% |
89
+ | `FasterPath.chop_basename` | `Pathname#chop_basename` | 46.7% |
90
90
  | `FasterPath.relative?` | `Pathname#relative?` | 1262.3% |
91
91
  | `FasterPath.blank?` | | |
92
92
 
@@ -115,8 +115,9 @@ FasterPath.sledgehammer_everything!
115
115
 
116
116
  The primary methods to target are mostly listed in the **Why** section above. You may find the Ruby
117
117
  source code useful for Pathname's [Ruby source](https://github.com/ruby/ruby/blob/32674b167bddc0d737c38f84722986b0f228b44b/ext/pathname/lib/pathname.rb),
118
- [C source](https://github.com/ruby/ruby/blob/32674b167bddc0d737c38f84722986b0f228b44b/ext/pathname/pathname.c), and
119
- [tests](https://github.com/ruby/ruby/blob/32674b167bddc0d737c38f84722986b0f228b44b/test/pathname/test_pathname.rb).
118
+ [C source](https://github.com/ruby/ruby/blob/32674b167bddc0d737c38f84722986b0f228b44b/ext/pathname/pathname.c),
119
+ [tests](https://github.com/ruby/ruby/blob/32674b167bddc0d737c38f84722986b0f228b44b/test/pathname/test_pathname.rb),
120
+ and checkout the [documentation](http://ruby-doc.org/stdlib-2.3.1/libdoc/pathname/rdoc/Pathname.html).
120
121
 
121
122
  Methods will be written as exclusively in Rust as possible. Even just writing a **not** in Ruby with a
122
123
  Rust method like `!absolute?` _(not absolute)_ drops 39% of the performance already gained in Rust.
@@ -16,4 +16,4 @@ Dir.chdir('../../') do
16
16
  system("rake clean_src")
17
17
  end
18
18
 
19
- create_makefile('faster_path/dummy')
19
+ create_makefile('faster_path/dummy')
data/faster_path.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/danielpclark/faster_path"
14
14
  spec.license = "MIT OR Apache-2.0"
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|assets)/}) }
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|assets|benches)/}) }
17
17
  spec.bindir = "exe"
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.extensions << "ext/faster_path/extconf.rb"
data/lib/faster_path.rb CHANGED
@@ -18,17 +18,18 @@ module FasterPath
18
18
  # to handle non-path strings.
19
19
  def self.chop_basename(pth)
20
20
  d,b = [Rust.dirname(pth), Rust.basename(pth)]
21
- if blank?(d) && blank?(b)
22
- nil
23
- else
24
- [d,b]
25
- end
21
+ [d,b] unless Rust.both_are_blank(d,b)
26
22
  end
27
23
 
28
24
  def self.blank?(str)
29
25
  Rust.is_blank(str)
30
26
  end
31
27
 
28
+ # EXAMPLE
29
+ #def self.one_and_two
30
+ # Rust.one_and_two.to_a
31
+ #end
32
+
32
33
  private
33
34
  module Rust
34
35
  extend FFI::Library
@@ -36,11 +37,25 @@ module FasterPath
36
37
  prefix = Gem.win_platform? ? "" : "lib"
37
38
  "#{File.expand_path("../target/release/", File.dirname(__FILE__))}/#{prefix}faster_path.#{FFI::Platform::LIBSUFFIX}"
38
39
  end
40
+
41
+ class FromRustArray < FFI::Struct
42
+ layout :len, :size_t, # dynamic array layout
43
+ :data, :pointer #
44
+
45
+ def to_a
46
+ self[:data].get_array_of_string(0, self[:len]).compact
47
+ end
48
+ end
49
+
39
50
  attach_function :is_absolute, [ :string ], :bool
40
51
  attach_function :is_relative, [ :string ], :bool
41
52
  attach_function :is_blank, [ :string ], :bool
53
+ attach_function :both_are_blank, [ :string, :string ], :bool
42
54
  attach_function :basename, [ :string ], :string
43
55
  attach_function :dirname, [ :string ], :string
56
+
57
+ # EXAMPLE
58
+ #attach_function :one_and_two, [], FromRustArray.by_value
44
59
  end
45
60
  private_constant :Rust
46
61
  end
@@ -1,3 +1,3 @@
1
1
  module FasterPath
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.8"
3
3
  end
data/src/basename.rs ADDED
@@ -0,0 +1,15 @@
1
+ #[no_mangle]
2
+ pub extern fn basename(string: *const c_char) -> *const c_char {
3
+ let c_str = unsafe {
4
+ assert!(!string.is_null());
5
+
6
+ CStr::from_ptr(string)
7
+ };
8
+
9
+ let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
10
+
11
+ let part = Path::new(r_str).file_name().unwrap_or(OsStr::new("")).to_str();
12
+
13
+ let output = CString::new(format!("{}", part.unwrap())).unwrap();
14
+ output.into_raw()
15
+ }
@@ -0,0 +1,14 @@
1
+ #[no_mangle]
2
+ pub extern fn both_are_blank(s1: *const c_char, s2: *const c_char) -> bool {
3
+ let c_str1 = unsafe {
4
+ assert!(!s1.is_null());
5
+ CStr::from_ptr(s1)
6
+ };
7
+ let c_str2 = unsafe {
8
+ assert!(!s2.is_null());
9
+ CStr::from_ptr(s2)
10
+ };
11
+
12
+ str::from_utf8(c_str1.to_bytes()).unwrap().trim().is_empty() &&
13
+ str::from_utf8(c_str2.to_bytes()).unwrap().trim().is_empty()
14
+ }
data/src/dirname.rs ADDED
@@ -0,0 +1,25 @@
1
+ #[no_mangle]
2
+ pub extern fn dirname(string: *const c_char) -> *const c_char {
3
+ let c_str = unsafe {
4
+ assert!(!string.is_null());
5
+
6
+ CStr::from_ptr(string)
7
+ };
8
+
9
+ let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
10
+
11
+ if r_str.is_empty() {
12
+ return string
13
+ }
14
+
15
+ let path = Path::new(r_str).parent().unwrap_or(Path::new(""));
16
+
17
+ let out_str = if !path.to_str().unwrap().is_empty() {
18
+ format!("{}{}", path.to_str().unwrap(), MAIN_SEPARATOR)
19
+ } else {
20
+ format!("{}", path.to_str().unwrap())
21
+ };
22
+
23
+ let output = CString::new(out_str).unwrap();
24
+ output.into_raw()
25
+ }
@@ -0,0 +1,12 @@
1
+ #[no_mangle]
2
+ pub extern fn is_absolute(string: *const c_char) -> bool {
3
+ let c_str = unsafe {
4
+ assert!(!string.is_null());
5
+
6
+ CStr::from_ptr(string)
7
+ };
8
+
9
+ let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or("");
10
+
11
+ r_str.chars().next().unwrap_or("muffins".chars().next().unwrap()) == MAIN_SEPARATOR
12
+ }
data/src/is_blank.rs ADDED
@@ -0,0 +1,10 @@
1
+ #[no_mangle]
2
+ pub extern fn is_blank(string: *const c_char) -> bool {
3
+ let c_str = unsafe {
4
+ assert!(!string.is_null());
5
+
6
+ CStr::from_ptr(string)
7
+ };
8
+
9
+ str::from_utf8(c_str.to_bytes()).unwrap().trim().is_empty()
10
+ }
@@ -0,0 +1,12 @@
1
+ #[no_mangle]
2
+ pub extern fn is_relative(string: *const c_char) -> bool {
3
+ let c_str = unsafe {
4
+ assert!(!string.is_null());
5
+
6
+ CStr::from_ptr(string)
7
+ };
8
+
9
+ let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or("");
10
+
11
+ r_str.chars().next().unwrap_or("muffins".chars().next().unwrap()) != MAIN_SEPARATOR
12
+ }
data/src/lib.rs CHANGED
@@ -10,82 +10,23 @@ use std::path::{Path,MAIN_SEPARATOR};
10
10
  use libc::c_char;
11
11
  use std::ffi::{CStr,CString,OsStr};
12
12
  use std::str;
13
-
14
- #[no_mangle]
15
- pub extern fn is_absolute(string: *const c_char) -> bool {
16
- let c_str = unsafe {
17
- assert!(!string.is_null());
18
-
19
- CStr::from_ptr(string)
20
- };
21
-
22
- let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or("");
23
-
24
- r_str.chars().next().unwrap_or("muffins".chars().next().unwrap()) == MAIN_SEPARATOR
25
- }
26
-
27
- #[no_mangle]
28
- pub extern fn is_relative(string: *const c_char) -> bool {
29
- let c_str = unsafe {
30
- assert!(!string.is_null());
31
-
32
- CStr::from_ptr(string)
33
- };
34
-
35
- let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or("");
36
-
37
- r_str.chars().next().unwrap_or("muffins".chars().next().unwrap()) != MAIN_SEPARATOR
38
- }
39
-
40
- #[no_mangle]
41
- pub extern fn is_blank(string: *const c_char) -> bool {
42
- let c_str = unsafe {
43
- assert!(!string.is_null());
44
-
45
- CStr::from_ptr(string)
46
- };
47
-
48
- str::from_utf8(c_str.to_bytes()).unwrap().trim().is_empty()
49
- }
50
-
51
- #[no_mangle]
52
- pub extern fn basename(string: *const c_char) -> *const c_char {
53
- let c_str = unsafe {
54
- assert!(!string.is_null());
55
-
56
- CStr::from_ptr(string)
57
- };
58
-
59
- let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
60
-
61
- let part = Path::new(r_str).file_name().unwrap_or(OsStr::new("")).to_str();
62
-
63
- let output = CString::new(format!("{}", part.unwrap())).unwrap();
64
- output.into_raw()
65
- }
66
-
67
- #[no_mangle]
68
- pub extern fn dirname(string: *const c_char) -> *const c_char {
69
- let c_str = unsafe {
70
- assert!(!string.is_null());
71
-
72
- CStr::from_ptr(string)
73
- };
74
-
75
- let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
76
-
77
- if r_str.is_empty() {
78
- return string
79
- }
80
-
81
- let path = Path::new(r_str).parent().unwrap_or(Path::new(""));
82
-
83
- let out_str = if !path.to_str().unwrap().is_empty() {
84
- format!("{}{}", path.to_str().unwrap(), MAIN_SEPARATOR)
85
- } else {
86
- format!("{}", path.to_str().unwrap())
87
- };
88
-
89
- let output = CString::new(out_str).unwrap();
90
- output.into_raw()
91
- }
13
+ use std::mem;
14
+
15
+ include!("ruby_string.rs");
16
+ include!("ruby_array.rs");
17
+ include!("is_absolute.rs");
18
+ include!("is_relative.rs");
19
+ include!("is_blank.rs");
20
+ include!("both_are_blank.rs");
21
+ include!("basename.rs");
22
+ include!("dirname.rs");
23
+
24
+ // EXAMPLE
25
+ //
26
+ //#[no_mangle]
27
+ //pub extern fn one_and_two() -> RubyArray {
28
+ // let mut words = vec![];
29
+ // words.push(RubyString::to_ruby(&"one".to_string()));
30
+ // words.push(RubyString::to_ruby(&"two".to_string()));
31
+ // RubyArray::from_vec(words)
32
+ //}
data/src/ruby_array.rs ADDED
@@ -0,0 +1,17 @@
1
+ #[repr(C)]
2
+ pub struct RubyArray {
3
+ len: libc::size_t,
4
+ data: *const libc::c_void,
5
+ }
6
+
7
+ impl RubyArray {
8
+ #[allow(dead_code)]
9
+ fn from_vec<T>(vec: Vec<T>) -> RubyArray {
10
+ let array = RubyArray {
11
+ data: vec.as_ptr() as *const libc::c_void,
12
+ len: vec.len() as libc::size_t
13
+ };
14
+ mem::forget(vec);
15
+ array
16
+ }
17
+ }
@@ -0,0 +1,30 @@
1
+ pub struct RubyString;
2
+
3
+ // Coercing strs into Strings has some loss of performance
4
+ // You may use these methods temporarily but it would be much better
5
+ // to write all of this code out in each method using just str.
6
+ //
7
+ // Using these methods you will still get you 10X (= 900%) performance
8
+ // gain regardless. But really consider not using String. If you do
9
+ // as I've intstructed the performance gains will go from 900% to 1250%.
10
+ impl RubyString {
11
+ #[allow(dead_code)]
12
+ // FOR QUICK IMPLEMENTATION. NOT FOR PRODUCTION.
13
+ // SEE BENCHMARKS FOR SANCTIONED IMPLEMENTATION.
14
+ fn from_ruby(s: *const c_char) -> String {
15
+ let c_str = unsafe {
16
+ assert!(!s.is_null());
17
+ CStr::from_ptr(s)
18
+ };
19
+ (*str::from_utf8(c_str.to_bytes()).unwrap_or("")).to_string()
20
+ }
21
+
22
+ #[allow(dead_code)]
23
+ // FOR QUICK IMPLEMENTATION. NOT FOR PRODUCTION.
24
+ // SEE BENCHMARKS FOR SANCTIONED IMPLEMENTATION.
25
+ fn to_ruby<S: Into<String>>(s: S) -> *const c_char {
26
+ let r_str = s.into();
27
+ let s_slice: &str = &r_str[..];
28
+ CString::new(s_slice).unwrap().into_raw()
29
+ }
30
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faster_path
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel P. Clark
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-06-11 00:00:00.000000000 Z
11
+ date: 2016-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -90,7 +90,15 @@ files:
90
90
  - lib/faster_path/optional/monkeypatches.rb
91
91
  - lib/faster_path/optional/refinements.rb
92
92
  - lib/faster_path/version.rb
93
+ - src/basename.rs
94
+ - src/both_are_blank.rs
95
+ - src/dirname.rs
96
+ - src/is_absolute.rs
97
+ - src/is_blank.rs
98
+ - src/is_relative.rs
93
99
  - src/lib.rs
100
+ - src/ruby_array.rs
101
+ - src/ruby_string.rs
94
102
  homepage: https://github.com/danielpclark/faster_path
95
103
  licenses:
96
104
  - MIT OR Apache-2.0