fastsheet 0.0.7 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6965671d803c3232aae8e31b15a5ac5df9c6f109
4
- data.tar.gz: 8545afaf2906b9fa1fa363f2933ec29a6ded458e
3
+ metadata.gz: e6eb7e299b220f69ff05cb1dd1bb015409e4cc31
4
+ data.tar.gz: 972681080beecd7165e47d0e0ddda8305004e7a9
5
5
  SHA512:
6
- metadata.gz: 418f795f3bbbc469060f81a2703fd1f60308ca25643731bb421dc2eaa025156ec562270b39b61287d53193abe34e32a10bf3c09736a52147ec0dffdaa50a9130
7
- data.tar.gz: c5b02accdb8303fb3b7d4be7e74d14e69470f86ac4c0fa04d85dadcc74ea56b88623b194c4fe3d7baf47aa6549398ac83ca758eed9b8d45b7202872156558b33
6
+ metadata.gz: 9155761df20a035bfa2e550600db4f5daa50813dac66b6558604649a1cb22b2d07db828c96ad300c5b7213eb5213a9d7ad0e1946dbc9b709b7a51c10b373beb3
7
+ data.tar.gz: 730e69d383da0b13e1dafc49ea2a9e0c287ad7ea56583e08fe01ebae58f89814cd20c24e32e908ba9638a1021017af02cdaa7c8e4e666f2e0a7b0cb172774380
data/.gitignore CHANGED
@@ -1,13 +1,14 @@
1
- /.bundle/
2
- /.yardoc
3
- /*.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- /target/
11
- /**/*.so
12
- /*.gem
13
- /**/*.log
1
+ Makefile
2
+ .yardoc
3
+ .bundle/
4
+ _yardoc/
5
+ coverage/
6
+ doc/
7
+ pkg/
8
+ spec/reports/
9
+ tmp/
10
+ **/target/
11
+ **/*.so
12
+ **/*.gem
13
+ **/*.log
14
+ **/*.lock
data/README.md CHANGED
@@ -2,33 +2,10 @@
2
2
 
3
3
  Fastest ruby gem for reading Excel documents.
4
4
 
5
- Benchmark:
6
- ```shell
7
- $ bin/benchmark
8
- Benchmark reading row №2991 from `./first_file.xlsx` 15 times...
9
- ┌───────────┬───────────┐
10
- │ Reader │ Real Time │
11
- ├───────────┼───────────┤
12
- │ Roo │ 161.3275 │
13
- ├───────────┼───────────┤
14
- │ Fastsheet │ 4.3765 │
15
- └───────────┴───────────┘
16
- Fastsheet is 37 times faster
17
-
18
- $ bin/benchmark
19
- Benchmark reading row №7146 from `./second_file.xlsx` 15 times...
20
- ┌───────────┬───────────┐
21
- │ Reader │ Real Time │
22
- ├───────────┼───────────┤
23
- │ Roo │ 897.4474 │
24
- ├───────────┼───────────┤
25
- │ Fastsheet │ 19.0869 │
26
- └───────────┴───────────┘
27
- Fastsheet is 47 times faster
28
- ```
29
-
30
5
  ## Installation
31
6
 
7
+ **You should have rust installed to use this gem.**
8
+
32
9
  Add this line to your application's Gemfile:
33
10
 
34
11
  ```ruby
@@ -45,24 +22,38 @@ Or install it yourself as:
45
22
 
46
23
  ## Usage
47
24
 
48
- This lib returns sheet as array of arrays, so you are free to use it however you want:
25
+ Open a sheet:
49
26
 
50
27
  ```ruby
51
28
  require 'fastsheet'
52
29
 
53
- sheet = Xlsx.new('path/to/sheet.xlsx')
30
+ sheet = Fastsheet::Sheet.new('path/to/sheet.xlsx')
54
31
 
55
- # get all rows
56
- sheet.rows
32
+ # number of columns
33
+ sheet.width
34
+
35
+ # number of rows
36
+ sheet.height
57
37
  ```
58
38
 
59
- That's all API for now :smile: . Feel free to [open an issue](http://github.com/dkkoval/fastsheet/issues) if you need more.
39
+ Get rows or columns:
40
+
41
+ ```ruby
42
+ sheet.rows
43
+ sheet.columns
44
+
45
+ sheet.row(42)
46
+ sheet.column(1)
47
+ ```
60
48
 
61
- ## Development
49
+ Iterators (returns enumerator if no block given):
62
50
 
63
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
+ ```ruby
52
+ sheet.each_row { |r| ... }
53
+ sheet.each_column { |c| ... }
54
+ ```
64
55
 
65
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
56
+ That's all API for now. Feel free to [open an issue](http://github.com/dkkoval/fastsheet/issues) if you need more.
66
57
 
67
58
  ## Contributing
68
59
 
data/Rakefile CHANGED
@@ -1,11 +1,14 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- require 'rake/clean'
5
- require 'rake/testtask'
6
1
  require 'bundler/setup'
7
- require 'thermite/tasks'
8
2
 
9
- Thermite::Tasks.new
3
+ desc 'Build native extension'
4
+ task :build do
5
+ ruby 'extconf.rb'
6
+ end
7
+
8
+ # TODO
9
+ desc 'Run tests'
10
+ task :test do
11
+ puts "no tests"
12
+ end
10
13
 
11
- task default: 'thermite:build'
14
+ task default: [:build, :test]
data/bin/.keep ADDED
File without changes
@@ -1,16 +1,13 @@
1
1
  [package]
2
2
  name = "fastsheet"
3
3
  version = "0.1.0"
4
-
5
- [package.metadata.thermite]
6
- github_releases = true
7
- github_release_type = "latest"
4
+ publish = false
5
+ build = "build.rs"
8
6
 
9
7
  [lib]
10
8
  name = "fastsheet"
11
9
  crate-type = ["cdylib"]
12
10
 
13
11
  [dependencies]
14
- ruru = "0.9.3"
15
- lazy_static = "0.2.1"
16
12
  calamine = "0.11.8"
13
+ libc = "0.2"
@@ -0,0 +1,62 @@
1
+ use std::env;
2
+ use std::ffi::OsStr;
3
+ use std::process::Command;
4
+
5
+ fn rbconfig(key: &str) -> Vec<u8> {
6
+ let ruby = match env::var_os("RUBY") {
7
+ Some(val) => val.to_os_string(),
8
+ None => OsStr::new("ruby").to_os_string(),
9
+ };
10
+ let config = Command::new(ruby)
11
+ .arg("-e")
12
+ .arg(format!("print RbConfig::CONFIG['{}']", key))
13
+ .output()
14
+ .unwrap_or_else(|e| panic!("ruby not found: {}", e));
15
+
16
+ config.stdout
17
+ }
18
+
19
+ fn use_static() {
20
+ let ruby_libs = rbconfig("LIBS");
21
+ let libs = String::from_utf8_lossy(&ruby_libs);
22
+
23
+ // Ruby gives back the libs in the form: `-lpthread -lgmp`
24
+ // Cargo wants them as: `-l pthread -l gmp`
25
+ let transformed_lib_args = libs.replace("-l", "-l ");
26
+
27
+ println!("cargo:rustc-link-lib=static=ruby-static");
28
+ println!("cargo:rustc-flags={}", transformed_lib_args);
29
+ }
30
+
31
+ fn use_dylib(lib: Vec<u8>) {
32
+ println!("cargo:rustc-link-lib=dylib={}",
33
+ String::from_utf8_lossy(&lib));
34
+ }
35
+
36
+ fn main() {
37
+ let libdir = rbconfig("libdir");
38
+
39
+ let libruby_static = rbconfig("LIBRUBY_A");
40
+ let libruby_so = rbconfig("RUBY_SO_NAME");
41
+
42
+ match (libruby_static.is_empty(), libruby_so.is_empty()) {
43
+ (false, true) => use_static(),
44
+ (true, false) => use_dylib(libruby_so),
45
+ (false, false) => {
46
+ if env::var_os("RUBY_STATIC").is_some() {
47
+ use_static()
48
+ } else {
49
+ use_dylib(libruby_so)
50
+ }
51
+ },
52
+ _ => {
53
+ let msg = "Error! Could not find LIBRUBY_A or RUBY_SO_NAME. \
54
+ This means that no static, or dynamic libruby was found. \
55
+ Possible solution: build a new Ruby with the `--enable-shared` configure opt.";
56
+ panic!(msg)
57
+ }
58
+ }
59
+
60
+ println!("cargo:rustc-link-search={}",
61
+ String::from_utf8_lossy(&libdir));
62
+ }
@@ -0,0 +1,152 @@
1
+ extern crate libc;
2
+ extern crate calamine;
3
+
4
+ use std::ffi::{CString, CStr};
5
+ use libc::{c_int, c_void, c_char, c_double, uintptr_t};
6
+
7
+ use calamine::{Sheets, DataType};
8
+
9
+ //
10
+ // Prepare Ruby bindings
11
+ //
12
+
13
+ // VALUE (pointer to a ruby object)
14
+ type Value = uintptr_t;
15
+
16
+ // Some ruby constant values
17
+ const NIL: usize = 0x08;
18
+ const TRUE: usize = 0x14;
19
+ const FALSE: usize = 0x00;
20
+
21
+ // Load some Ruby API functions
22
+ extern "C" {
23
+ // Object class
24
+ static rb_cObject: Value;
25
+
26
+ // Modules and classes
27
+ fn rb_define_module(name: *const c_char) -> Value;
28
+ fn rb_define_class_under(outer: Value, name: *const c_char, superclass: Value) -> Value;
29
+ fn rb_define_method(class: Value, name: *const c_char, method: *const c_void, argc: c_int) -> Value;
30
+
31
+ // Set instance variables
32
+ fn rb_iv_set(object: Value, name: *const c_char, value: Value) -> Value;
33
+
34
+ // Array
35
+ fn rb_ary_new() -> Value;
36
+ fn rb_ary_push(array: Value, elem: Value) -> Value;
37
+
38
+ // C data to Ruby
39
+ fn rb_int2big(num: c_int) -> Value;
40
+ fn rb_float_new(num: c_double) -> Value;
41
+ fn rb_utf8_str_new_cstr(str: *const c_char) -> Value;
42
+
43
+ // Ruby string to C string
44
+ fn rb_string_value_cstr(str: *const Value) -> *const c_char;
45
+ }
46
+
47
+ //
48
+ // Utils
49
+ //
50
+
51
+ // C string from Rust string
52
+ pub fn cstr(string: &str) -> CString {
53
+ CString::new(string).unwrap()
54
+ }
55
+
56
+ // Rust string from Ruby string
57
+ pub fn rstr(string: Value) -> String {
58
+ unsafe {
59
+ let s = rb_string_value_cstr(&string);
60
+ CStr::from_ptr(s).to_string_lossy().into_owned()
61
+ }
62
+ }
63
+
64
+ //
65
+ // Functions to use in Ruby
66
+ //
67
+
68
+ // Read the sheet
69
+ unsafe fn read(this: Value, rb_file_name: Value) -> Value {
70
+ let mut document =
71
+ Sheets::open(rstr(rb_file_name))
72
+ .expect("Cannot open file!");
73
+
74
+ // Open first worksheet by default
75
+ //
76
+ // TODO: allow use different worksheets
77
+ let sheet = document.worksheet_range_by_index(0).unwrap();
78
+
79
+ let rows = rb_ary_new();
80
+
81
+ for row in sheet.rows() {
82
+ let new_row = rb_ary_new();
83
+
84
+ for (_, c) in row.iter().enumerate() {
85
+ rb_ary_push(
86
+ new_row,
87
+ match *c {
88
+ // vba error
89
+ DataType::Error(_) => NIL,
90
+ DataType::Empty => NIL,
91
+ DataType::Float(ref f) => rb_float_new(*f as c_double),
92
+ DataType::Int(ref i) => rb_int2big(*i as c_int),
93
+ DataType::Bool(ref b) => if *b { TRUE } else { FALSE },
94
+ DataType::String(ref s) => {
95
+ let st = s.trim();
96
+ if st.is_empty() {
97
+ NIL
98
+ } else {
99
+ rb_utf8_str_new_cstr(cstr(st).as_ptr())
100
+ }
101
+ }
102
+ }
103
+ );
104
+ }
105
+
106
+ rb_ary_push(rows, new_row);
107
+ }
108
+
109
+
110
+ // Set instance variables
111
+ rb_iv_set(
112
+ this,
113
+ cstr("@width").as_ptr(),
114
+ rb_int2big(sheet.width() as i32)
115
+ );
116
+
117
+ rb_iv_set(
118
+ this,
119
+ cstr("@height").as_ptr(),
120
+ rb_int2big(sheet.height() as i32)
121
+ );
122
+
123
+ rb_iv_set(
124
+ this,
125
+ cstr("@rows").as_ptr(),
126
+ rows
127
+ );
128
+
129
+ this
130
+ }
131
+
132
+ // Init_libfastsheet symbol is an entrypoint for the lib
133
+ //
134
+ // This function will be executed when we require the lib.
135
+ //
136
+ #[no_mangle]
137
+ #[allow(non_snake_case)]
138
+ pub unsafe extern fn Init_libfastsheet() {
139
+ let Fastsheet =
140
+ rb_define_module(cstr("Fastsheet").as_ptr());
141
+
142
+ let Sheet =
143
+ rb_define_class_under(Fastsheet, cstr("Sheet").as_ptr(), rb_cObject);
144
+
145
+ rb_define_method(
146
+ Sheet,
147
+ cstr("read!").as_ptr(),
148
+ // Rust function as pointer to C function
149
+ read as *const c_void,
150
+ 1 as c_int
151
+ );
152
+ }
data/extconf.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'mkmf'
2
+ require 'rake'
3
+
4
+ abort unless have_library 'ruby'
5
+ abort unless have_header 'ruby.h'
6
+
7
+ abort unless find_executable 'rustc'
8
+ abort unless cargo = find_executable(ENV.fetch('CARGO', 'cargo'))
9
+
10
+ target_file = 'libfastsheet.so'
11
+
12
+ target = File.join(__dir__, 'ext/fastsheet/target/release', target_file)
13
+ lib_dest = File.join(__dir__, 'lib/fastsheet', target_file)
14
+
15
+ # HACK: rubygems requires Makefile with tasks above
16
+ File.write 'Makefile', <<EOF
17
+ all:
18
+ install:
19
+ clean:
20
+ EOF
21
+ $makefile_created = true
22
+
23
+ Dir.chdir 'ext/fastsheet' do
24
+ when_writing 'Building fastsheet...' do
25
+ sh cargo, 'build', '--release'
26
+ cp target, lib_dest
27
+ end
28
+ end
data/fastsheet.gemspec CHANGED
@@ -20,13 +20,8 @@ Gem::Specification.new do |spec|
20
20
  end
21
21
  spec.bindir = 'bin'
22
22
  spec.require_paths = ['lib']
23
- spec.extensions << 'Rakefile'
23
+ spec.extensions = %w[extconf.rb]
24
24
 
25
- spec.add_runtime_dependency 'thermite', '~> 0.12.1'
26
-
27
- spec.add_development_dependency 'pry', '~> 0.10.4'
28
-
29
- # for pretty benchmark
30
- spec.add_development_dependency 'tty-spinner', '~> 0.7.0'
31
- spec.add_development_dependency 'tty-table', '~> 0.8.0'
25
+ spec.add_development_dependency 'rake', '~>12.0.0'
26
+ spec.add_development_dependency 'pry', '~>0.10.4'
32
27
  end
data/lib/fastsheet.rb CHANGED
@@ -1,5 +1,2 @@
1
- require 'fastsheet/xlsx'
2
- require 'libfastsheet'
3
-
4
- module Fastsheet
5
- end
1
+ require 'fastsheet/libfastsheet'
2
+ require 'fastsheet/sheet'
@@ -0,0 +1,44 @@
1
+ module Fastsheet
2
+ class Sheet
3
+ attr_reader :file_name,
4
+ :rows, :header,
5
+ :width, :height
6
+
7
+ def initialize(file_name, options = {})
8
+ # this method sets @rows, @height and @width
9
+ read!(file_name)
10
+
11
+ @header = @rows.shift if options[:header]
12
+ end
13
+
14
+ def row(n)
15
+ @rows[n]
16
+ end
17
+
18
+ def each_row
19
+ if block_given?
20
+ @rows.each { |r| yield r }
21
+ else
22
+ @rows.each
23
+ end
24
+ end
25
+
26
+ def column(n)
27
+ @rows.map { |r| r[n] }
28
+ end
29
+
30
+ def columns
31
+ (0...@width).inject([]) do |cols, i|
32
+ cols.push column(i)
33
+ end
34
+ end
35
+
36
+ def each_column
37
+ if block_given?
38
+ columns.each { |c| yield c }
39
+ else
40
+ columns.each
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module Fastsheet
2
- VERSION = '0.0.7'
2
+ VERSION = '0.1.0'
3
3
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastsheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Koval
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-12 00:00:00.000000000 Z
11
+ date: 2017-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: thermite
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.12.1
20
- type: :runtime
19
+ version: 12.0.0
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.12.1
26
+ version: 12.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,56 +38,28 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.10.4
41
- - !ruby/object:Gem::Dependency
42
- name: tty-spinner
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 0.7.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 0.7.0
55
- - !ruby/object:Gem::Dependency
56
- name: tty-table
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 0.8.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 0.8.0
69
41
  description: Fastest ruby gem for reading Excel documents.
70
42
  email:
71
43
  - dkoval@heliostech.fr
72
44
  executables: []
73
45
  extensions:
74
- - Rakefile
46
+ - extconf.rb
75
47
  extra_rdoc_files: []
76
48
  files:
77
49
  - ".gitignore"
78
- - Cargo.toml
79
50
  - Gemfile
80
- - Gemfile.lock
81
51
  - LICENSE.txt
82
52
  - README.md
83
53
  - Rakefile
84
- - bin/benchmark
85
- - bin/console
54
+ - bin/.keep
55
+ - ext/fastsheet/Cargo.toml
56
+ - ext/fastsheet/build.rs
57
+ - ext/fastsheet/src/lib.rs
58
+ - extconf.rb
86
59
  - fastsheet.gemspec
87
60
  - lib/fastsheet.rb
61
+ - lib/fastsheet/sheet.rb
88
62
  - lib/fastsheet/version.rb
89
- - lib/fastsheet/xlsx.rb
90
- - src/lib.rs
91
63
  homepage: https://github.com/dkkoval/fastsheet
92
64
  licenses:
93
65
  - MIT
@@ -108,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
80
  version: '0'
109
81
  requirements: []
110
82
  rubyforge_project:
111
- rubygems_version: 2.5.2
83
+ rubygems_version: 2.6.11
112
84
  signing_key:
113
85
  specification_version: 4
114
86
  summary: Fast XLSX reader
data/bin/benchmark DELETED
@@ -1,59 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- lib = File.expand_path('../../lib', __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
-
6
- require 'benchmark'
7
- require 'tty-spinner'
8
- require 'tty-table'
9
-
10
- require 'fastsheet'
11
- require 'roo'
12
-
13
- FILE = './second_file.xlsx'.freeze
14
- ROW = rand 9000
15
- N = 15
16
-
17
- options = {
18
- hide_cursor: true,
19
- format: :dots,
20
- interval: 20,
21
- clear: true
22
- }
23
-
24
- puts "Benchmark reading row №#{ROW} from `#{FILE}` #{N} times..."
25
-
26
- roo_time = Benchmark.measure('Roo') do
27
- spinner = TTY::Spinner.new('[:spinner] :progress', options)
28
- spinner.auto_spin
29
- N.times do |i|
30
- spinner.update(progress: "Roo: #{i + 1}/#{N} sheets opened ...")
31
- Roo::Excelx.new(FILE).sheet(0).row(ROW)
32
- end
33
- spinner.stop
34
- end
35
-
36
- fastsheet_time = Benchmark.measure('Fastsheet') do
37
- spinner = TTY::Spinner.new('[:spinner] :progress', options)
38
- spinner.auto_spin
39
- N.times do |i|
40
- spinner.update(progress: "Fastsheet: #{i + 1}/#{N} sheets opened ...")
41
- Xlsx.new(FILE).rows[ROW]
42
- end
43
- spinner.stop
44
- end
45
-
46
- table = TTY::Table.new(header: ['Reader', 'Real Time'])
47
-
48
- table << ['Roo', roo_time.real.round(4)]
49
- table << ['Fastsheet', fastsheet_time.real.round(4)]
50
-
51
- renderer = TTY::Table::Renderer::Unicode.new(table)
52
-
53
- renderer.alignments = %i[center center]
54
- renderer.padding = [0, 1, 0, 1]
55
- renderer.border.separator = :each_row
56
-
57
- puts renderer.render
58
-
59
- puts "Fastsheet is #{(roo_time.real / fastsheet_time.real).round} times faster"
data/bin/console DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- lib = File.expand_path('../../lib', __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
-
6
- require 'fastsheet'
7
-
8
- require 'pry'
9
- Pry.start
@@ -1,4 +0,0 @@
1
- module Fastsheet
2
- class Xlsx
3
- end
4
- end
data/src/lib.rs DELETED
@@ -1,74 +0,0 @@
1
- #[macro_use] extern crate ruru;
2
- #[macro_use] extern crate lazy_static;
3
-
4
- extern crate calamine;
5
-
6
- use ruru::{Array, Class, RString, Float, Fixnum, Boolean, Object, AnyObject, NilClass};
7
-
8
- use calamine::{Sheets, DataType};
9
-
10
- pub struct Reader {
11
- file: String,
12
- rows: Array
13
- }
14
-
15
- impl Reader {
16
- fn new(file: String) -> Self {
17
- let mut this = Reader {
18
- file: file,
19
- rows: Array::new()
20
- };
21
-
22
- let sheet = Sheets::open(&this.file).unwrap().worksheet_range_by_index(0).unwrap();
23
-
24
- for row in sheet.rows() {
25
- let mut new_row = Array::with_capacity(sheet.width());
26
-
27
- for (_, c) in row.iter().enumerate() {
28
- match *c {
29
- DataType::Error(_) => new_row.push(NilClass::new()),
30
- DataType::String(ref s) => new_row.push(RString::new(s)),
31
- DataType::Empty => new_row.push(NilClass::new()),
32
- DataType::Float(ref f) => new_row.push(Float::new(*f)),
33
- DataType::Int(ref i) => new_row.push(Fixnum::new(*i)),
34
- DataType::Bool(ref b) => new_row.push(Boolean::new(*b))
35
- };
36
- }
37
-
38
- this.rows.push(new_row);
39
- }
40
- this
41
- }
42
-
43
- fn get_rows(&self) -> AnyObject {
44
- self.rows.to_any_object()
45
- }
46
- }
47
-
48
- wrappable_struct!(Reader, ReaderWrapper, READER_WRAPPER);
49
-
50
- class!(Xlsx);
51
-
52
- methods!(
53
- Xlsx,
54
- itself,
55
-
56
- fn ruby_xlsx_new(file: RString) -> AnyObject {
57
- let xlsx_reader = Reader::new(file.unwrap().to_string());
58
-
59
- Class::from_existing("Xlsx").wrap_data(xlsx_reader, &*READER_WRAPPER)
60
- }
61
-
62
- fn ruby_xlsx_rows() -> AnyObject {
63
- itself.get_data(&*READER_WRAPPER).get_rows()
64
- }
65
- );
66
-
67
- #[no_mangle]
68
- #[allow(non_snake_case)]
69
- pub extern fn Init_libfastsheet() {
70
- Class::new("Xlsx", None).define(|itself| {
71
- itself.def_self("new", ruby_xlsx_new);
72
- itself.def("rows", ruby_xlsx_rows)
73
- });
74
- }