faster_path 0.1.13 → 0.2.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/Cargo.lock +26 -1
- data/Cargo.toml +1 -1
- data/Rakefile +32 -2
- data/lib/faster_path.rb +43 -65
- data/lib/faster_path/optional/monkeypatches.rb +2 -1
- data/lib/faster_path/optional/refinements.rb +1 -1
- data/lib/faster_path/version.rb +1 -1
- data/src/basename.rs +16 -34
- data/src/chop_basename.rs +46 -48
- data/src/dirname.rs +23 -38
- data/src/extname.rs +4 -11
- data/src/lib.rs +134 -28
- data/src/plus.rs +4 -31
- data/src/rust_arch_bits.rs +1 -1
- metadata +2 -14
- data/src/add_trailing_separator.rs +0 -29
- data/src/basename_for_chop.rs +0 -31
- data/src/both_are_blank.rs +0 -22
- data/src/dirname_for_chop.rs +0 -36
- data/src/entries.rs +0 -30
- data/src/has_trailing_separator.rs +0 -27
- data/src/is_absolute.rs +0 -17
- data/src/is_blank.rs +0 -15
- data/src/is_directory.rs +0 -18
- data/src/is_relative.rs +0 -16
- data/src/ruby_array.rs +0 -20
- data/src/ruby_string.rs +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b227f5a94ba3ae27a33eab04fa65c80d95b9842
|
4
|
+
data.tar.gz: 6cf955a639547780ecd12279dd50c8f00343b772
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2571373e3f523f8db360b7b68593d192b10b4e718ba8f12cdc47292479c9e6facb74498d799dca7121aa4e895a7d2088b8d921855bd6857a3c9f1c7512617fcb
|
7
|
+
data.tar.gz: 3e2c243a5921e93c3e0f47e028aa2e7b10cbdf5eb304830093e869a6abca1159b6b86dc627516c548e404b5ce738ecbc8fd2f5a5b5e48ef802d8e20a7c392d34
|
data/Cargo.lock
CHANGED
@@ -3,7 +3,7 @@ name = "faster_path"
|
|
3
3
|
version = "0.0.1"
|
4
4
|
dependencies = [
|
5
5
|
"array_tool 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
6
|
-
"
|
6
|
+
"ruru 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
7
7
|
]
|
8
8
|
|
9
9
|
[[package]]
|
@@ -11,11 +11,36 @@ name = "array_tool"
|
|
11
11
|
version = "0.4.1"
|
12
12
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
13
13
|
|
14
|
+
[[package]]
|
15
|
+
name = "lazy_static"
|
16
|
+
version = "0.2.8"
|
17
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
18
|
+
|
14
19
|
[[package]]
|
15
20
|
name = "libc"
|
16
21
|
version = "0.2.30"
|
17
22
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
18
23
|
|
24
|
+
[[package]]
|
25
|
+
name = "ruby-sys"
|
26
|
+
version = "0.2.20"
|
27
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
28
|
+
dependencies = [
|
29
|
+
"libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
30
|
+
]
|
31
|
+
|
32
|
+
[[package]]
|
33
|
+
name = "ruru"
|
34
|
+
version = "0.9.3"
|
35
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
36
|
+
dependencies = [
|
37
|
+
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
38
|
+
"ruby-sys 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
39
|
+
]
|
40
|
+
|
19
41
|
[metadata]
|
20
42
|
"checksum array_tool 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a07ccb27c611e5cda99e498e99ba71b3ecdb7db5df02096cef42a3df5b84542"
|
43
|
+
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
|
21
44
|
"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915"
|
45
|
+
"checksum ruby-sys 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e71509f17ce93733dc196258e168b58050490a156b04563816a8120a74ba04c7"
|
46
|
+
"checksum ruru 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6486d6c50b7a08246a492a61893635c1977d41c138041d443eb603f6298e0273"
|
data/Cargo.toml
CHANGED
data/Rakefile
CHANGED
@@ -24,8 +24,38 @@ task :sysinfo do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
desc "Add libruby to deps"
|
28
|
+
task :libruby_release do
|
29
|
+
filename = RbConfig::CONFIG["LIBRUBY_ALIASES"].split(" ").first
|
30
|
+
libfile = File.join(RbConfig::CONFIG["libdir"], filename)
|
31
|
+
deps = "target/release/deps"
|
32
|
+
|
33
|
+
printf "Copying libruby.so ... "
|
34
|
+
unless File.exist? "#{deps}/#{filename}"
|
35
|
+
FileUtils.mkdir_p deps
|
36
|
+
FileUtils.cp libfile, deps
|
37
|
+
end
|
38
|
+
exit 1 unless File.exist? "#{deps}/#{filename}"
|
39
|
+
puts "libruby.so copied."
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Add libruby to debug deps"
|
43
|
+
task :libruby_debug do
|
44
|
+
filename = RbConfig::CONFIG["LIBRUBY_ALIASES"].split(" ").first
|
45
|
+
libfile = File.join(RbConfig::CONFIG["libdir"], filename)
|
46
|
+
deps = "target/debug/deps"
|
47
|
+
|
48
|
+
printf "Copying libruby.so ... "
|
49
|
+
unless File.exist? "#{deps}/#{filename}"
|
50
|
+
FileUtils.mkdir_p deps
|
51
|
+
FileUtils.cp libfile, deps
|
52
|
+
end
|
53
|
+
exit 1 unless File.exist? "#{deps}/#{filename}"
|
54
|
+
puts "libruby.so copied."
|
55
|
+
end
|
56
|
+
|
27
57
|
desc "Build Rust extension"
|
28
|
-
task :
|
58
|
+
task build_src: :libruby_release do
|
29
59
|
puts "Building extension..."
|
30
60
|
sh "cargo build --release"
|
31
61
|
end
|
@@ -58,7 +88,7 @@ task :lint do
|
|
58
88
|
end
|
59
89
|
|
60
90
|
desc "Run Rust Tests"
|
61
|
-
task :
|
91
|
+
task cargo: :libruby_debug do
|
62
92
|
sh "cargo test -- --nocapture"
|
63
93
|
end
|
64
94
|
|
data/lib/faster_path.rb
CHANGED
@@ -4,6 +4,26 @@ require "ffi"
|
|
4
4
|
require 'faster_path/asset_resolution'
|
5
5
|
|
6
6
|
module FasterPath
|
7
|
+
FFI_LIBRARY = begin
|
8
|
+
prefix = Gem.win_platform? ? "" : "lib"
|
9
|
+
"#{File.expand_path("../target/release/", __dir__)}/#{prefix}faster_path.#{FFI::Platform::LIBSUFFIX}"
|
10
|
+
end
|
11
|
+
require 'fiddle'
|
12
|
+
library = Fiddle.dlopen(FFI_LIBRARY)
|
13
|
+
Fiddle::Function.
|
14
|
+
new(library['Init_faster_pathname'], [], Fiddle::TYPE_VOIDP).
|
15
|
+
call
|
16
|
+
|
17
|
+
FasterPathname.class_eval do
|
18
|
+
private :add_trailing_separator
|
19
|
+
private :basename
|
20
|
+
private :chop_basename
|
21
|
+
private :dirname
|
22
|
+
private :entries
|
23
|
+
private :extname
|
24
|
+
private :plus
|
25
|
+
end
|
26
|
+
|
7
27
|
def self.rust_arch_bits
|
8
28
|
Rust.rust_arch_bits
|
9
29
|
end
|
@@ -12,102 +32,60 @@ module FasterPath
|
|
12
32
|
1.size * 8
|
13
33
|
end
|
14
34
|
|
15
|
-
# Spec to Pathname#absolute?
|
16
35
|
def self.absolute?(pth)
|
17
|
-
|
36
|
+
FasterPathname.allocate.send(:absolute?, pth)
|
18
37
|
end
|
19
38
|
|
20
|
-
|
21
|
-
|
22
|
-
Rust.is_directory(pth)
|
39
|
+
def self.add_trailing_separator(pth)
|
40
|
+
FasterPathname.allocate.send(:add_trailing_separator, pth)
|
23
41
|
end
|
24
42
|
|
25
|
-
|
26
|
-
|
27
|
-
Rust.is_relative(pth)
|
43
|
+
def self.blank?(str)
|
44
|
+
"#{str}".strip.empty?
|
28
45
|
end
|
29
46
|
|
30
|
-
def self.
|
31
|
-
|
47
|
+
def self.basename(pth, ext="")
|
48
|
+
FasterPathname.allocate.send(:basename, pth, ext)
|
32
49
|
end
|
33
50
|
|
34
|
-
# Spec to Pathname#chop_basename
|
35
|
-
# WARNING! Pathname#chop_basename in STDLIB doesn't handle blank strings correctly!
|
36
|
-
# This implementation correctly handles blank strings just as Pathname had intended
|
37
|
-
# to handle non-path strings.
|
38
51
|
def self.chop_basename(pth)
|
39
|
-
|
40
|
-
|
41
|
-
[d, b] unless Rust.both_are_blank(d, b)
|
52
|
+
result = FasterPathname.allocate.send(:chop_basename, pth)
|
53
|
+
result unless result.empty?
|
42
54
|
end
|
43
55
|
|
44
|
-
def self.
|
45
|
-
|
56
|
+
def self.directory?(pth)
|
57
|
+
FasterPathname.allocate.send(:directory?, pth)
|
46
58
|
end
|
47
59
|
|
48
|
-
def self.
|
49
|
-
|
60
|
+
def self.dirname(pth)
|
61
|
+
FasterPathname.allocate.send(:dirname, pth)
|
50
62
|
end
|
51
63
|
|
52
|
-
def self.
|
53
|
-
|
64
|
+
def self.entries(pth)
|
65
|
+
FasterPathname.allocate.send(:entries, pth)
|
54
66
|
end
|
55
67
|
|
56
|
-
def self.
|
57
|
-
|
68
|
+
def self.extname(pth)
|
69
|
+
FasterPathname.allocate.send(:extname, pth)
|
58
70
|
end
|
59
71
|
|
60
72
|
def self.has_trailing_separator?(pth)
|
61
|
-
|
73
|
+
FasterPathname.allocate.send(:has_trailing_separator?, pth)
|
62
74
|
end
|
63
75
|
|
64
|
-
def self.
|
65
|
-
|
76
|
+
def self.plus(pth, pth2)
|
77
|
+
FasterPathname.allocate.send(:plus, pth, pth2)
|
66
78
|
end
|
67
79
|
|
68
|
-
def self.
|
69
|
-
|
80
|
+
def self.relative?(pth)
|
81
|
+
FasterPathname.allocate.send(:relative?, pth)
|
70
82
|
end
|
71
83
|
|
72
|
-
# EXAMPLE
|
73
|
-
# def self.one_and_two
|
74
|
-
# Rust.one_and_two.to_a
|
75
|
-
# end
|
76
|
-
|
77
84
|
module Rust
|
78
85
|
extend FFI::Library
|
79
|
-
ffi_lib
|
80
|
-
prefix = Gem.win_platform? ? "" : "lib"
|
81
|
-
"#{File.expand_path("../target/release/", __dir__)}/#{prefix}faster_path.#{FFI::Platform::LIBSUFFIX}"
|
82
|
-
end
|
83
|
-
|
84
|
-
class FromRustArray < FFI::Struct
|
85
|
-
layout :len, :size_t, # dynamic array layout
|
86
|
-
:data, :pointer #
|
87
|
-
|
88
|
-
def to_a
|
89
|
-
self[:data].get_array_of_string(0, self[:len]).compact
|
90
|
-
end
|
91
|
-
end
|
86
|
+
ffi_lib ::FasterPath::FFI_LIBRARY
|
92
87
|
|
93
88
|
attach_function :rust_arch_bits, [], :int32
|
94
|
-
attach_function :is_absolute, [ :string ], :bool
|
95
|
-
attach_function :is_directory, [ :string ], :bool
|
96
|
-
attach_function :is_relative, [ :string ], :bool
|
97
|
-
attach_function :is_blank, [ :string ], :bool
|
98
|
-
attach_function :both_are_blank, [ :string, :string ], :bool
|
99
|
-
attach_function :basename, [ :string, :string ], :string
|
100
|
-
attach_function :plus, [ :string, :string ], :string
|
101
|
-
attach_function :dirname, [ :string ], :string
|
102
|
-
attach_function :basename_for_chop, [ :string ], :string # decoupling behavior
|
103
|
-
attach_function :dirname_for_chop, [ :string ], :string # decoupling behavior
|
104
|
-
attach_function :add_trailing_separator, [ :string ], :string
|
105
|
-
attach_function :has_trailing_separator, [ :string ], :bool
|
106
|
-
attach_function :extname, [ :string ], :string
|
107
|
-
attach_function :entries, [ :string ], FromRustArray.by_value
|
108
|
-
|
109
|
-
# EXAMPLE
|
110
|
-
# attach_function :one_and_two, [], FromRustArray.by_value
|
111
89
|
end
|
112
90
|
private_constant :Rust
|
113
91
|
end
|
@@ -3,11 +3,12 @@ require 'pathname'
|
|
3
3
|
module FasterPath
|
4
4
|
module MonkeyPatches
|
5
5
|
# rubocop:disable Metrics/CyclomaticComplexity
|
6
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
6
7
|
def self._ruby_core_file!
|
7
8
|
::File.class_eval do
|
8
9
|
def self.basename(pth, ext = '')
|
9
10
|
pth = pth.to_path if pth.respond_to? :to_path
|
10
|
-
raise TypeError unless pth.is_a? String
|
11
|
+
raise TypeError unless pth.is_a?(String) && ext.is_a?(String)
|
11
12
|
FasterPath.basename(pth, ext)
|
12
13
|
end
|
13
14
|
|
data/lib/faster_path/version.rb
CHANGED
data/src/basename.rs
CHANGED
@@ -1,41 +1,23 @@
|
|
1
|
-
|
2
|
-
use
|
1
|
+
extern crate array_tool;
|
2
|
+
use path_parsing::extract_last_path_segment;
|
3
|
+
use self::array_tool::string::Squeeze;
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
return
|
5
|
+
pub fn basename(pth: &str, ext: &str) -> String {
|
6
|
+
// Known edge case
|
7
|
+
match &pth.squeeze("/")[..] {
|
8
|
+
"/" => { return "/".to_string() }
|
9
|
+
_ => {}
|
8
10
|
}
|
9
|
-
let pth = unsafe { CStr::from_ptr(c_pth) }.to_str().unwrap();
|
10
|
-
let ext = unsafe { CStr::from_ptr(c_ext) }.to_str().unwrap();
|
11
11
|
|
12
|
-
let name =
|
13
|
-
|
14
|
-
CString::new(name).unwrap().into_raw()
|
15
|
-
}
|
16
|
-
|
17
|
-
pub mod rust {
|
18
|
-
extern crate array_tool;
|
19
|
-
use path_parsing::extract_last_path_segment;
|
20
|
-
use self::array_tool::string::Squeeze;
|
12
|
+
let mut name = extract_last_path_segment(pth);
|
21
13
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
"/" => { return "/".to_string() }
|
26
|
-
_ => {}
|
14
|
+
if ext == ".*" {
|
15
|
+
if let Some(dot_i) = name.rfind('.') {
|
16
|
+
name = &name[0..dot_i];
|
27
17
|
}
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
if let Some(dot_i) = name.rfind('.') {
|
33
|
-
name = &name[0..dot_i];
|
34
|
-
}
|
35
|
-
} else if name.ends_with(ext) {
|
36
|
-
name = &name[..name.len() - ext.len()];
|
37
|
-
};
|
38
|
-
name.to_string()
|
39
|
-
}
|
18
|
+
} else if name.ends_with(ext) {
|
19
|
+
name = &name[..name.len() - ext.len()];
|
20
|
+
};
|
21
|
+
name.to_string()
|
40
22
|
}
|
41
23
|
|
data/src/chop_basename.rs
CHANGED
@@ -1,56 +1,54 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
use std::str;
|
1
|
+
use std::path::MAIN_SEPARATOR;
|
2
|
+
use std::str;
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
pub fn chop_basename(input: &str) -> Option<(String,String)> {
|
5
|
+
if input.is_empty() {
|
6
|
+
return None;
|
7
|
+
}
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
}
|
9
|
+
let mut offset = 0;
|
10
|
+
let mut trailing_slashes = input.chars().rev();
|
11
|
+
loop {
|
12
|
+
match trailing_slashes.next() {
|
13
|
+
Some(MAIN_SEPARATOR) => { offset = offset + 1 },
|
14
|
+
_ => { break },
|
17
15
|
}
|
16
|
+
}
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
if directory.is_empty() && (base.is_empty() || base == "/") {
|
24
|
-
return None
|
25
|
-
};
|
18
|
+
let input = &input[0..input.len()-offset];
|
19
|
+
let base = input.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("");
|
20
|
+
let directory = &input[0..input.len()-base.len()];
|
26
21
|
|
27
|
-
|
28
|
-
|
22
|
+
if directory.is_empty() && (base.is_empty() || base.chars().next().unwrap() == MAIN_SEPARATOR) {
|
23
|
+
return None
|
24
|
+
};
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
assert_eq!(chop_basename(&""[..]), None);
|
33
|
-
assert_eq!(chop_basename(&"/"[..]), None);
|
34
|
-
assert_eq!(
|
35
|
-
chop_basename(&"."[..]),
|
36
|
-
Some(("".to_string(), ".".to_string()))
|
37
|
-
);
|
38
|
-
assert_eq!(
|
39
|
-
chop_basename(&"asdf/asdf"[..]),
|
40
|
-
Some(("asdf/".to_string(), "asdf".to_string()))
|
41
|
-
);
|
42
|
-
assert_eq!(
|
43
|
-
chop_basename(&"asdf.txt"[..]),
|
44
|
-
Some(("".to_string(), "asdf.txt".to_string()))
|
45
|
-
);
|
46
|
-
assert_eq!(
|
47
|
-
chop_basename(&"asdf/"[..]),
|
48
|
-
Some(("".to_string(), "asdf".to_string()))
|
49
|
-
);
|
50
|
-
assert_eq!(
|
51
|
-
chop_basename(&"/asdf/"[..]),
|
52
|
-
Some(("/".to_string(), "asdf".to_string()))
|
53
|
-
);
|
54
|
-
}
|
26
|
+
Some((directory.to_string(), base.to_string()))
|
27
|
+
}
|
55
28
|
|
29
|
+
#[test]
|
30
|
+
fn it_chops_the_basename_and_dirname() {
|
31
|
+
assert_eq!(chop_basename(&""[..]), None);
|
32
|
+
assert_eq!(chop_basename(&"/"[..]), None);
|
33
|
+
assert_eq!(
|
34
|
+
chop_basename(&"."[..]),
|
35
|
+
Some(("".to_string(), ".".to_string()))
|
36
|
+
);
|
37
|
+
assert_eq!(
|
38
|
+
chop_basename(&"asdf/asdf"[..]),
|
39
|
+
Some(("asdf/".to_string(), "asdf".to_string()))
|
40
|
+
);
|
41
|
+
assert_eq!(
|
42
|
+
chop_basename(&"asdf.txt"[..]),
|
43
|
+
Some(("".to_string(), "asdf.txt".to_string()))
|
44
|
+
);
|
45
|
+
assert_eq!(
|
46
|
+
chop_basename(&"asdf/"[..]),
|
47
|
+
Some(("".to_string(), "asdf".to_string()))
|
48
|
+
);
|
49
|
+
assert_eq!(
|
50
|
+
chop_basename(&"/asdf/"[..]),
|
51
|
+
Some(("/".to_string(), "asdf".to_string()))
|
52
|
+
);
|
56
53
|
}
|
54
|
+
|
data/src/dirname.rs
CHANGED
@@ -1,46 +1,31 @@
|
|
1
|
-
use
|
2
|
-
use
|
1
|
+
use std::path::MAIN_SEPARATOR;
|
2
|
+
use path_parsing::{last_sep_i, last_non_sep_i, last_non_sep_i_before};
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
if
|
7
|
-
return
|
4
|
+
pub fn dirname(path: &str) -> String {
|
5
|
+
let r_str = path;
|
6
|
+
if r_str.is_empty() {
|
7
|
+
return ".".to_string();
|
8
8
|
}
|
9
|
-
let
|
10
|
-
|
11
|
-
|
12
|
-
}
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
return MAIN_SEPARATOR.to_string();
|
26
|
-
}
|
27
|
-
let sep_i = last_sep_i(r_str, non_sep_i);
|
28
|
-
if sep_i == -1 {
|
29
|
-
return ".".to_string();
|
30
|
-
}
|
31
|
-
if sep_i == 0 {
|
32
|
-
return MAIN_SEPARATOR.to_string();
|
33
|
-
}
|
34
|
-
let non_sep_i2 = last_non_sep_i_before(r_str, sep_i);
|
35
|
-
if non_sep_i2 != -1 {
|
36
|
-
return r_str[..(non_sep_i2 + 1) as usize].to_string();
|
37
|
-
} else {
|
38
|
-
return MAIN_SEPARATOR.to_string();
|
39
|
-
}
|
9
|
+
let non_sep_i = last_non_sep_i(r_str);
|
10
|
+
if non_sep_i == -1 {
|
11
|
+
return MAIN_SEPARATOR.to_string();
|
12
|
+
}
|
13
|
+
let sep_i = last_sep_i(r_str, non_sep_i);
|
14
|
+
if sep_i == -1 {
|
15
|
+
return ".".to_string();
|
16
|
+
}
|
17
|
+
if sep_i == 0 {
|
18
|
+
return MAIN_SEPARATOR.to_string();
|
19
|
+
}
|
20
|
+
let non_sep_i2 = last_non_sep_i_before(r_str, sep_i);
|
21
|
+
if non_sep_i2 != -1 {
|
22
|
+
return r_str[..(non_sep_i2 + 1) as usize].to_string();
|
23
|
+
} else {
|
24
|
+
return MAIN_SEPARATOR.to_string();
|
40
25
|
}
|
41
26
|
}
|
42
27
|
|
43
28
|
#[test]
|
44
29
|
fn returns_dot_for_empty_string(){
|
45
|
-
assert_eq!(
|
30
|
+
assert_eq!(dirname(""), ".".to_string());
|
46
31
|
}
|
data/src/extname.rs
CHANGED
@@ -1,20 +1,13 @@
|
|
1
|
-
use libc::c_char;
|
2
|
-
use std::ffi::{CStr, CString};
|
3
1
|
use path_parsing::extract_last_path_segment;
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
if c_pth.is_null() {
|
8
|
-
return c_pth
|
9
|
-
}
|
10
|
-
|
11
|
-
let name = extract_last_path_segment(unsafe { CStr::from_ptr(c_pth) }.to_str().unwrap());
|
3
|
+
pub fn extname(pth: &str) -> String {
|
4
|
+
let name = extract_last_path_segment(pth);
|
12
5
|
|
13
6
|
if let Some(dot_i) = name.rfind('.') {
|
14
7
|
if dot_i > 0 && dot_i < name.len() - 1 && name[..dot_i].chars().rev().next().unwrap() != '.' {
|
15
|
-
return
|
8
|
+
return String::from(&name[dot_i..])
|
16
9
|
}
|
17
10
|
}
|
18
11
|
|
19
|
-
|
12
|
+
String::from("")
|
20
13
|
}
|
data/src/lib.rs
CHANGED
@@ -4,34 +4,140 @@
|
|
4
4
|
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
5
5
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
6
6
|
// copied, modified, or distributed except according to those terms.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
pub mod plus;
|
18
|
-
pub mod dirname;
|
19
|
-
pub mod chop_basename;
|
20
|
-
pub mod basename_for_chop;
|
21
|
-
pub mod dirname_for_chop;
|
22
|
-
pub mod add_trailing_separator;
|
23
|
-
pub mod has_trailing_separator;
|
24
|
-
pub mod extname;
|
25
|
-
pub mod entries;
|
7
|
+
#[macro_use]
|
8
|
+
extern crate ruru;
|
9
|
+
|
10
|
+
class!(FasterPathname);
|
11
|
+
|
12
|
+
mod basename;
|
13
|
+
mod chop_basename;
|
14
|
+
mod dirname;
|
15
|
+
mod extname;
|
16
|
+
mod plus;
|
26
17
|
pub mod rust_arch_bits;
|
27
18
|
mod path_parsing;
|
28
19
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
20
|
+
use ruru::{Class, Object, RString, Boolean, Array};
|
21
|
+
use std::path::{MAIN_SEPARATOR,Path};
|
22
|
+
use std::fs;
|
23
|
+
|
24
|
+
methods!(
|
25
|
+
FasterPathname,
|
26
|
+
_itself,
|
27
|
+
|
28
|
+
fn r_add_trailing_separator(pth: RString) -> RString {
|
29
|
+
let p = pth.ok().unwrap();
|
30
|
+
let x = format!("{}{}", p.to_str(), "a");
|
31
|
+
match x.rsplit_terminator(MAIN_SEPARATOR).next() {
|
32
|
+
Some("a") => p,
|
33
|
+
_ => RString::new(format!("{}{}", p.to_str(), MAIN_SEPARATOR).as_str())
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
fn r_is_absolute(pth: RString) -> Boolean {
|
38
|
+
Boolean::new(match pth.ok().unwrap_or(RString::new("")).to_str().chars().next() {
|
39
|
+
Some(c) => c == MAIN_SEPARATOR,
|
40
|
+
None => false
|
41
|
+
})
|
42
|
+
}
|
43
|
+
|
44
|
+
fn r_basename(pth: RString, ext: RString) -> RString {
|
45
|
+
RString::new(
|
46
|
+
&basename::basename(
|
47
|
+
pth.ok().unwrap_or(RString::new("")).to_str(),
|
48
|
+
ext.ok().unwrap_or(RString::new("")).to_str()
|
49
|
+
)[..]
|
50
|
+
)
|
51
|
+
}
|
52
|
+
|
53
|
+
fn r_chop_basename(pth: RString) -> Array {
|
54
|
+
let mut arr = Array::with_capacity(2);
|
55
|
+
let results = chop_basename::chop_basename(pth.ok().unwrap_or(RString::new("")).to_str());
|
56
|
+
match results {
|
57
|
+
Some((dirname, basename)) => {
|
58
|
+
arr.push(RString::new(&dirname[..]));
|
59
|
+
arr.push(RString::new(&basename[..]));
|
60
|
+
arr
|
61
|
+
},
|
62
|
+
None => arr
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
fn r_is_directory(pth: RString) -> Boolean {
|
67
|
+
Boolean::new(
|
68
|
+
Path::new(
|
69
|
+
pth.ok().unwrap_or(RString::new("")).to_str()
|
70
|
+
).is_dir()
|
71
|
+
)
|
72
|
+
}
|
73
|
+
|
74
|
+
fn r_dirname(pth: RString) -> RString {
|
75
|
+
RString::new(
|
76
|
+
&dirname::dirname(
|
77
|
+
pth.ok().unwrap_or(RString::new("")).to_str()
|
78
|
+
)[..]
|
79
|
+
)
|
80
|
+
}
|
81
|
+
|
82
|
+
fn r_entries(pth: RString) -> Array {
|
83
|
+
let files = fs::read_dir(pth.ok().unwrap_or(RString::new("")).to_str()).unwrap();
|
84
|
+
let mut arr = Array::new();
|
85
|
+
|
86
|
+
arr.push(RString::new("."));
|
87
|
+
arr.push(RString::new(".."));
|
88
|
+
|
89
|
+
for file in files {
|
90
|
+
let file_name_str = file.unwrap().file_name().into_string().unwrap();
|
91
|
+
arr.push(RString::new(&file_name_str[..]));
|
92
|
+
}
|
93
|
+
|
94
|
+
arr
|
95
|
+
}
|
96
|
+
|
97
|
+
fn r_extname(pth: RString) -> RString {
|
98
|
+
RString::new(
|
99
|
+
&extname::extname(pth.ok().unwrap_or(RString::new("")).to_str())[..]
|
100
|
+
)
|
101
|
+
}
|
102
|
+
|
103
|
+
fn r_has_trailing_separator(pth: RString) -> Boolean {
|
104
|
+
let v = pth.ok().unwrap_or(RString::new(""));
|
105
|
+
match chop_basename::chop_basename(v.to_str()) {
|
106
|
+
Some((a,b)) => {
|
107
|
+
Boolean::new(a.len() + b.len() < v.to_str().len())
|
108
|
+
},
|
109
|
+
_ => Boolean::new(false)
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
fn r_plus(pth1: RString, pth2: RString) -> RString {
|
114
|
+
RString::new(&plus::plus_paths(pth1.ok().unwrap().to_str(), pth2.ok().unwrap().to_str())[..])
|
115
|
+
}
|
116
|
+
|
117
|
+
fn r_is_relative(pth: RString) -> Boolean {
|
118
|
+
Boolean::new(
|
119
|
+
match pth.ok().unwrap_or(RString::new(&MAIN_SEPARATOR.to_string()[..])).to_str().chars().next() {
|
120
|
+
Some(c) => c != MAIN_SEPARATOR,
|
121
|
+
None => true
|
122
|
+
}
|
123
|
+
)
|
124
|
+
}
|
125
|
+
);
|
126
|
+
|
127
|
+
#[allow(non_snake_case)]
|
128
|
+
#[no_mangle]
|
129
|
+
pub extern "C" fn Init_faster_pathname(){
|
130
|
+
Class::new("FasterPathname", None).define(|itself| {
|
131
|
+
itself.def("absolute?", r_is_absolute);
|
132
|
+
itself.def("add_trailing_separator", r_add_trailing_separator);
|
133
|
+
itself.def("basename", r_basename);
|
134
|
+
itself.def("chop_basename", r_chop_basename);
|
135
|
+
itself.def("directory?", r_is_directory);
|
136
|
+
itself.def("dirname", r_dirname);
|
137
|
+
itself.def("entries", r_entries);
|
138
|
+
itself.def("extname", r_extname);
|
139
|
+
itself.def("has_trailing_separator?", r_has_trailing_separator);
|
140
|
+
itself.def("plus", r_plus);
|
141
|
+
itself.def("relative?", r_is_relative);
|
142
|
+
});
|
143
|
+
}
|
data/src/plus.rs
CHANGED
@@ -1,40 +1,13 @@
|
|
1
1
|
extern crate array_tool;
|
2
2
|
use std::path::Path;
|
3
|
-
use libc::c_char;
|
4
|
-
use std::ffi::{CStr,CString};
|
5
3
|
use std::str;
|
6
|
-
use chop_basename::
|
7
|
-
use basename::
|
8
|
-
use dirname::
|
4
|
+
use chop_basename::chop_basename;
|
5
|
+
use basename::basename;
|
6
|
+
use dirname::dirname;
|
9
7
|
use self::array_tool::vec::Shift;
|
10
8
|
use std::ops::Index;
|
11
9
|
|
12
|
-
|
13
|
-
pub extern fn plus(string: *const c_char, string2: *const c_char) -> *const c_char {
|
14
|
-
let c_str = unsafe {
|
15
|
-
if string.is_null() {
|
16
|
-
return string;
|
17
|
-
}
|
18
|
-
CStr::from_ptr(string)
|
19
|
-
};
|
20
|
-
|
21
|
-
let c_str2 = unsafe {
|
22
|
-
if string2.is_null() {
|
23
|
-
return string2;
|
24
|
-
}
|
25
|
-
CStr::from_ptr(string2)
|
26
|
-
};
|
27
|
-
|
28
|
-
let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
|
29
|
-
let r_str2 = str::from_utf8(c_str2.to_bytes()).unwrap();
|
30
|
-
|
31
|
-
let result = plus_paths(r_str, r_str2);
|
32
|
-
|
33
|
-
let output = CString::new(result).unwrap();
|
34
|
-
output.into_raw()
|
35
|
-
}
|
36
|
-
|
37
|
-
fn plus_paths(path1: &str, path2: &str) -> String {
|
10
|
+
pub fn plus_paths(path1: &str, path2: &str) -> String {
|
38
11
|
let mut prefix2 = path2.to_string();
|
39
12
|
let mut index_list2: Vec<usize> = vec![];
|
40
13
|
let mut basename_list2: Vec<String> = vec![];
|
data/src/rust_arch_bits.rs
CHANGED
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.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel P. Clark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -173,25 +173,13 @@ files:
|
|
173
173
|
- lib/faster_path/optional/monkeypatches.rb
|
174
174
|
- lib/faster_path/optional/refinements.rb
|
175
175
|
- lib/faster_path/version.rb
|
176
|
-
- src/add_trailing_separator.rs
|
177
176
|
- src/basename.rs
|
178
|
-
- src/basename_for_chop.rs
|
179
|
-
- src/both_are_blank.rs
|
180
177
|
- src/chop_basename.rs
|
181
178
|
- src/dirname.rs
|
182
|
-
- src/dirname_for_chop.rs
|
183
|
-
- src/entries.rs
|
184
179
|
- src/extname.rs
|
185
|
-
- src/has_trailing_separator.rs
|
186
|
-
- src/is_absolute.rs
|
187
|
-
- src/is_blank.rs
|
188
|
-
- src/is_directory.rs
|
189
|
-
- src/is_relative.rs
|
190
180
|
- src/lib.rs
|
191
181
|
- src/path_parsing.rs
|
192
182
|
- src/plus.rs
|
193
|
-
- src/ruby_array.rs
|
194
|
-
- src/ruby_string.rs
|
195
183
|
- src/rust_arch_bits.rs
|
196
184
|
homepage: https://github.com/danielpclark/faster_path
|
197
185
|
licenses:
|
@@ -1,29 +0,0 @@
|
|
1
|
-
use std::path::{Path, MAIN_SEPARATOR};
|
2
|
-
use libc::c_char;
|
3
|
-
use std::ffi::{CStr, CString};
|
4
|
-
use std::str;
|
5
|
-
|
6
|
-
#[no_mangle]
|
7
|
-
pub extern fn add_trailing_separator(string: *const c_char) -> *const c_char {
|
8
|
-
let c_str = unsafe {
|
9
|
-
if string.is_null() {
|
10
|
-
return string;
|
11
|
-
}
|
12
|
-
CStr::from_ptr(string)
|
13
|
-
};
|
14
|
-
let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or("");
|
15
|
-
|
16
|
-
if r_str.is_empty() {
|
17
|
-
return string;
|
18
|
-
}
|
19
|
-
|
20
|
-
let path = Path::new(r_str);
|
21
|
-
let out_str = if !(path.to_str().unwrap().chars().last().unwrap() == '/') {
|
22
|
-
format!("{}{}", path.to_str().unwrap(), MAIN_SEPARATOR)
|
23
|
-
} else {
|
24
|
-
path.to_str().unwrap().to_string()
|
25
|
-
};
|
26
|
-
|
27
|
-
let output = CString::new(out_str).unwrap();
|
28
|
-
output.into_raw()
|
29
|
-
}
|
data/src/basename_for_chop.rs
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
use std::path::MAIN_SEPARATOR;
|
2
|
-
use libc::c_char;
|
3
|
-
use std::ffi::{CStr,CString};
|
4
|
-
use std::str;
|
5
|
-
|
6
|
-
#[no_mangle]
|
7
|
-
pub extern fn basename_for_chop(string: *const c_char) -> *const c_char {
|
8
|
-
let c_str = unsafe {
|
9
|
-
if string.is_null() {
|
10
|
-
return string;
|
11
|
-
}
|
12
|
-
CStr::from_ptr(string)
|
13
|
-
};
|
14
|
-
|
15
|
-
let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
|
16
|
-
|
17
|
-
let mut offset = 0;
|
18
|
-
let mut trailing_slashes = r_str.chars().rev();
|
19
|
-
loop {
|
20
|
-
match trailing_slashes.next() {
|
21
|
-
Some(MAIN_SEPARATOR) => { offset = offset + 1 },
|
22
|
-
_ => { break },
|
23
|
-
}
|
24
|
-
}
|
25
|
-
|
26
|
-
let r_str = &r_str[0..r_str.len()-offset];
|
27
|
-
let part = r_str.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("");
|
28
|
-
|
29
|
-
let output = CString::new(part).unwrap();
|
30
|
-
output.into_raw()
|
31
|
-
}
|
data/src/both_are_blank.rs
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
use libc::c_char;
|
2
|
-
use std::ffi::{CStr};
|
3
|
-
use std::str;
|
4
|
-
|
5
|
-
#[no_mangle]
|
6
|
-
pub extern fn both_are_blank(s1: *const c_char, s2: *const c_char) -> bool {
|
7
|
-
let c_str1 = unsafe {
|
8
|
-
if s1.is_null() {
|
9
|
-
return true;
|
10
|
-
}
|
11
|
-
CStr::from_ptr(s1)
|
12
|
-
};
|
13
|
-
let c_str2 = unsafe {
|
14
|
-
if s2.is_null() {
|
15
|
-
return true;
|
16
|
-
}
|
17
|
-
CStr::from_ptr(s2)
|
18
|
-
};
|
19
|
-
|
20
|
-
str::from_utf8(c_str1.to_bytes()).unwrap().trim().is_empty() &&
|
21
|
-
str::from_utf8(c_str2.to_bytes()).unwrap().trim().is_empty()
|
22
|
-
}
|
data/src/dirname_for_chop.rs
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
use std::path::MAIN_SEPARATOR;
|
2
|
-
use libc::c_char;
|
3
|
-
use std::ffi::{CStr,CString};
|
4
|
-
use std::str;
|
5
|
-
|
6
|
-
#[no_mangle]
|
7
|
-
pub extern fn dirname_for_chop(string: *const c_char) -> *const c_char {
|
8
|
-
let c_str = unsafe {
|
9
|
-
if string.is_null() {
|
10
|
-
return string
|
11
|
-
}
|
12
|
-
CStr::from_ptr(string)
|
13
|
-
};
|
14
|
-
|
15
|
-
let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
|
16
|
-
|
17
|
-
if r_str.is_empty() {
|
18
|
-
return string
|
19
|
-
}
|
20
|
-
|
21
|
-
let mut offset = 0;
|
22
|
-
let mut trailing_slashes = r_str.chars().rev();
|
23
|
-
loop {
|
24
|
-
match trailing_slashes.next() {
|
25
|
-
Some(MAIN_SEPARATOR) => { offset = offset + 1 },
|
26
|
-
_ => { break },
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
let r_str = &r_str[0..r_str.len()-offset];
|
31
|
-
|
32
|
-
let base = r_str.rsplit_terminator(MAIN_SEPARATOR).nth(0).unwrap_or("");
|
33
|
-
|
34
|
-
let output = CString::new(&r_str[0..r_str.len()-base.len()]).unwrap();
|
35
|
-
output.into_raw()
|
36
|
-
}
|
data/src/entries.rs
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
use libc::c_char;
|
2
|
-
use std::ffi::{CStr,CString};
|
3
|
-
use std::str;
|
4
|
-
use std::fs;
|
5
|
-
use ruby_array::RubyArray;
|
6
|
-
|
7
|
-
#[no_mangle]
|
8
|
-
pub extern fn entries(string: *const c_char) -> RubyArray {
|
9
|
-
let c_str = unsafe {
|
10
|
-
assert!(!string.is_null());
|
11
|
-
|
12
|
-
CStr::from_ptr(string)
|
13
|
-
};
|
14
|
-
|
15
|
-
let r_str = str::from_utf8(c_str.to_bytes()).unwrap();
|
16
|
-
|
17
|
-
let files = fs::read_dir(r_str).unwrap();
|
18
|
-
let mut files_vec = vec![];
|
19
|
-
|
20
|
-
files_vec.push(CString::new(".").unwrap().into_raw());
|
21
|
-
files_vec.push(CString::new("..").unwrap().into_raw());
|
22
|
-
|
23
|
-
for file in files {
|
24
|
-
let file_name_str = file.unwrap().file_name().into_string().unwrap();
|
25
|
-
let file_name_cstr = CString::new(file_name_str).unwrap().into_raw();
|
26
|
-
files_vec.push(file_name_cstr);
|
27
|
-
}
|
28
|
-
|
29
|
-
RubyArray::from_vec(files_vec)
|
30
|
-
}
|
@@ -1,27 +0,0 @@
|
|
1
|
-
use std::path::{Path, MAIN_SEPARATOR};
|
2
|
-
use libc::c_char;
|
3
|
-
use std::ffi::CStr;
|
4
|
-
use std::str;
|
5
|
-
|
6
|
-
#[no_mangle]
|
7
|
-
pub extern "C" fn has_trailing_separator(string: *const c_char) -> bool {
|
8
|
-
let c_str = unsafe {
|
9
|
-
if string.is_null() {
|
10
|
-
return false
|
11
|
-
}
|
12
|
-
CStr::from_ptr(string)
|
13
|
-
};
|
14
|
-
|
15
|
-
let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or("");
|
16
|
-
let path = Path::new(r_str);
|
17
|
-
let last_component = path.iter().last();
|
18
|
-
if last_component.is_none() {
|
19
|
-
false
|
20
|
-
} else {
|
21
|
-
let mut parts: Vec<&str> = r_str.rsplit_terminator(MAIN_SEPARATOR).collect();
|
22
|
-
parts.retain(|x| !x.is_empty());
|
23
|
-
let last_part = parts.first().unwrap_or(&"").chars().last().unwrap_or(MAIN_SEPARATOR);
|
24
|
-
let last_char = r_str.chars().last().unwrap();
|
25
|
-
(last_part != last_char) && (last_char == MAIN_SEPARATOR)
|
26
|
-
}
|
27
|
-
}
|
data/src/is_absolute.rs
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
use libc::c_char;
|
2
|
-
use std::ffi::{CStr};
|
3
|
-
use std::path::MAIN_SEPARATOR;
|
4
|
-
|
5
|
-
|
6
|
-
#[no_mangle]
|
7
|
-
pub extern fn is_absolute(path: *const c_char) -> bool {
|
8
|
-
if path.is_null() {
|
9
|
-
return false;
|
10
|
-
}
|
11
|
-
let r_str = unsafe { CStr::from_ptr(path) }.to_str().unwrap();
|
12
|
-
|
13
|
-
match r_str.chars().next() {
|
14
|
-
Some(c) => c == MAIN_SEPARATOR,
|
15
|
-
None => false
|
16
|
-
}
|
17
|
-
}
|
data/src/is_blank.rs
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
use libc::c_char;
|
2
|
-
use std::ffi::{CStr};
|
3
|
-
use std::str;
|
4
|
-
|
5
|
-
#[no_mangle]
|
6
|
-
pub extern fn is_blank(string: *const c_char) -> bool {
|
7
|
-
let c_str = unsafe {
|
8
|
-
if string.is_null() {
|
9
|
-
return true;
|
10
|
-
}
|
11
|
-
CStr::from_ptr(string)
|
12
|
-
};
|
13
|
-
|
14
|
-
str::from_utf8(c_str.to_bytes()).unwrap().trim().is_empty()
|
15
|
-
}
|
data/src/is_directory.rs
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
use libc::c_char;
|
2
|
-
use std::ffi::{CStr};
|
3
|
-
use std::str;
|
4
|
-
use std::path::Path;
|
5
|
-
|
6
|
-
#[no_mangle]
|
7
|
-
pub extern fn is_directory(string: *const c_char) -> bool {
|
8
|
-
let c_str = unsafe {
|
9
|
-
if string.is_null() {
|
10
|
-
return false;
|
11
|
-
}
|
12
|
-
CStr::from_ptr(string)
|
13
|
-
};
|
14
|
-
|
15
|
-
let r_str = str::from_utf8(c_str.to_bytes()).unwrap_or("");
|
16
|
-
|
17
|
-
Path::new(r_str).is_dir()
|
18
|
-
}
|
data/src/is_relative.rs
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
use std::path::MAIN_SEPARATOR;
|
2
|
-
use libc::c_char;
|
3
|
-
use std::ffi::{CStr};
|
4
|
-
|
5
|
-
#[no_mangle]
|
6
|
-
pub extern fn is_relative(path: *const c_char) -> bool {
|
7
|
-
if path.is_null() {
|
8
|
-
return false;
|
9
|
-
}
|
10
|
-
let r_str = unsafe { CStr::from_ptr(path) }.to_str().unwrap();
|
11
|
-
|
12
|
-
match r_str.chars().next() {
|
13
|
-
Some(c) => c != MAIN_SEPARATOR,
|
14
|
-
None => true
|
15
|
-
}
|
16
|
-
}
|
data/src/ruby_array.rs
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
use libc;
|
2
|
-
use std::mem;
|
3
|
-
|
4
|
-
#[repr(C)]
|
5
|
-
pub struct RubyArray {
|
6
|
-
len: libc::size_t,
|
7
|
-
data: *const libc::c_void,
|
8
|
-
}
|
9
|
-
|
10
|
-
impl RubyArray {
|
11
|
-
#[allow(dead_code)]
|
12
|
-
pub fn from_vec<T>(vec: Vec<T>) -> RubyArray {
|
13
|
-
let array = RubyArray {
|
14
|
-
data: vec.as_ptr() as *const libc::c_void,
|
15
|
-
len: vec.len() as libc::size_t
|
16
|
-
};
|
17
|
-
mem::forget(vec);
|
18
|
-
array
|
19
|
-
}
|
20
|
-
}
|
data/src/ruby_string.rs
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
use libc::c_char;
|
2
|
-
use std::ffi::{CStr,CString};
|
3
|
-
use std::str;
|
4
|
-
|
5
|
-
pub struct RubyString;
|
6
|
-
|
7
|
-
// Coercing strs into Strings has some loss of performance
|
8
|
-
// You may use these methods temporarily but it would be much better
|
9
|
-
// to write all of this code out in each method using just str.
|
10
|
-
//
|
11
|
-
// Using these methods you will still get you 10X (= 900%) performance
|
12
|
-
// gain regardless. But really consider not using String. If you do
|
13
|
-
// as I've intstructed the performance gains will go from 900% to 1250%.
|
14
|
-
impl RubyString {
|
15
|
-
#[allow(dead_code)]
|
16
|
-
// FOR QUICK IMPLEMENTATION. NOT FOR PRODUCTION.
|
17
|
-
// SEE BENCHMARKS FOR SANCTIONED IMPLEMENTATION.
|
18
|
-
fn from_ruby(s: *const c_char) -> String {
|
19
|
-
let c_str = unsafe {
|
20
|
-
assert!(!s.is_null());
|
21
|
-
CStr::from_ptr(s)
|
22
|
-
};
|
23
|
-
(*str::from_utf8(c_str.to_bytes()).unwrap_or("")).to_string()
|
24
|
-
}
|
25
|
-
|
26
|
-
#[allow(dead_code)]
|
27
|
-
// FOR QUICK IMPLEMENTATION. NOT FOR PRODUCTION.
|
28
|
-
// SEE BENCHMARKS FOR SANCTIONED IMPLEMENTATION.
|
29
|
-
fn to_ruby<S: Into<String>>(s: S) -> *const c_char {
|
30
|
-
let r_str = s.into();
|
31
|
-
let s_slice: &str = &r_str[..];
|
32
|
-
CString::new(s_slice).unwrap().into_raw()
|
33
|
-
}
|
34
|
-
}
|