diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..41116a0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "rust-analyzer.linkedProjects": [ + "native/xler_native/Cargo.toml" + ] +} \ No newline at end of file diff --git a/config/config.exs b/config/config.exs index 70c1dba..694ce2e 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,6 +1,6 @@ # This file is responsible for configuring your application # and its dependencies with the aid of the Mix.Config module. -use Mix.Config +import Config # This configuration is loaded before any dependency and is restricted # to this project. If another project depends on this project, this diff --git a/mix.exs b/mix.exs index 0f0bc70..600c3d3 100644 --- a/mix.exs +++ b/mix.exs @@ -7,7 +7,7 @@ defmodule Xler.MixProject do version: "0.6.0", elixir: "~> 1.8", start_permanent: Mix.env() == :prod, - compilers: [:rustler] ++ Mix.compilers(), + compilers: Mix.compilers(), description: description(), package: package(), rustler_crates: rustler_crates(), @@ -35,7 +35,7 @@ defmodule Xler.MixProject do # Run "mix help deps" to learn about dependencies. defp deps() do [ - {:rustler, "~> 0.23.0"}, + {:rustler, "~> 0.34.0"}, {:ex_doc, ">= 0.0.0", only: :dev} ] end diff --git a/mix.lock b/mix.lock index 71e2ab2..5bd6a51 100644 --- a/mix.lock +++ b/mix.lock @@ -1,12 +1,21 @@ %{ + "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, "earmark": {:hex, :earmark, "1.4.4", "4821b8d05cda507189d51f2caeef370cf1e18ca5d7dfb7d31e9cafe6688106a4", [:mix], [], "hexpm", "1f93aba7340574847c0f609da787f0d79efcab51b044bb6e242cae5aca9d264d"}, "earmark_parser": {:hex, :earmark_parser, "1.4.31", "a93921cdc6b9b869f519213d5bc79d9e218ba768d7270d46fdcf1c01bacff9e2", [:mix], [], "hexpm", "317d367ee0335ef037a87e46c91a2269fef6306413f731e8ec11fc45a7efd059"}, "ex_doc": {:hex, :ex_doc, "0.29.3", "f07444bcafb302db86e4f02d8bbcd82f2e881a0dcf4f3e4740e4b8128b9353f7", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3dc6787d7b08801ec3b51e9bd26be5e8826fbf1a17e92d1ebc252e1a1c75bfe1"}, - "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, + "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, + "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, + "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, + "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, - "rustler": {:hex, :rustler, "0.23.0", "87162ffdf5a46b6aa03d624a77367070ff1263961ae35332c059225e136c4a87", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.5.2", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "f5ab6f0ec564f5569009c0f5685b0e5b379fd72655e82a8dc5a3c24f9fdda36a"}, - "toml": {:hex, :toml, "0.5.2", "e471388a8726d1ce51a6b32f864b8228a1eb8edc907a0edf2bb50eab9321b526", [:mix], [], "hexpm", "f1e3dabef71fb510d015fad18c0e05e7c57281001141504c6b69d94e99750a07"}, + "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, + "req": {:hex, :req, "0.5.4", "e375e4812adf83ffcf787871d7a124d873e983e3b77466e6608b973582f7f837", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "a17998ffe2ef54f79bfdd782ef9f4cbf987d93851e89444cbc466a6a25eee494"}, + "rustler": {:hex, :rustler, "0.34.0", "e9a73ee419fc296a10e49b415a2eb87a88c9217aa0275ec9f383d37eed290c1c", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "1d0c7449482b459513003230c0e2422b0252245776fe6fd6e41cb2b11bd8e628"}, + "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, + "toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"}, } diff --git a/native/xler_native/.gitignore b/native/xler_native/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/native/xler_native/.gitignore @@ -0,0 +1 @@ +/target diff --git a/native/xler_native/Cargo.lock b/native/xler_native/Cargo.lock index 2508795..6093c0c 100644 --- a/native/xler_native/Cargo.lock +++ b/native/xler_native/Cargo.lock @@ -1,11 +1,22 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "adler32" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + [[package]] name = "byteorder" version = "1.3.4" @@ -74,12 +85,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -dependencies = [ - "unicode-segmentation", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "inventory" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" [[package]] name = "lazy_static" @@ -119,11 +133,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.23" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ef7cd2518ead700af67bf9d1a658d90b6037d77110fd9c0445429d0ba1c6c9" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -138,42 +152,61 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] -name = "rustler" -version = "0.23.0" +name = "regex" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ac79e5fcfae809c16ff8da548daa291933b7ec8d66eadc197cdccec46891625" +checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" dependencies = [ - "lazy_static", + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "rustler" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94bdfa68c0388cbd725f1ca54e975956482c262599e5cced04a903eec918b7f" +dependencies = [ + "inventory", "rustler_codegen", "rustler_sys", ] [[package]] name = "rustler_codegen" -version = "0.23.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10d303c303a145c1f3d2a2993527128badb9500101070c55e36ef9bb2417666a" +checksum = "996dc019acb78b91b4e0c1bd6fa2cd509a835d309de762dc15213b97eac399da" dependencies = [ "heck", + "inventory", "proc-macro2", "quote", - "syn", + "syn 2.0.72", ] [[package]] name = "rustler_sys" -version = "2.1.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb96034ff33723615fd19223d58c987c1f6476342e83557a6e467ef95f83bda" +checksum = "3914a75a147934353c3772a77b774c79fdf80ba84e8347f52a50df0c164aaff2" dependencies = [ + "regex", "unreachable", ] @@ -194,6 +227,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "thiserror" version = "1.0.20" @@ -211,14 +255,14 @@ checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.42", ] [[package]] -name = "unicode-segmentation" -version = "1.6.0" +name = "unicode-ident" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-xid" diff --git a/native/xler_native/Cargo.toml b/native/xler_native/Cargo.toml index 1ad2223..4d5294e 100644 --- a/native/xler_native/Cargo.toml +++ b/native/xler_native/Cargo.toml @@ -9,6 +9,6 @@ path = "src/lib.rs" crate-type = ["dylib"] [dependencies] -rustler = "0.23.0" +rustler = "0.34.0" lazy_static = "1.4" calamine = "0.18.0" \ No newline at end of file diff --git a/native/xler_native/src/lib.rs b/native/xler_native/src/lib.rs index fcf5bc1..242eb86 100644 --- a/native/xler_native/src/lib.rs +++ b/native/xler_native/src/lib.rs @@ -1,77 +1,61 @@ -#[macro_use] extern crate rustler; -extern crate lazy_static; extern crate calamine; +extern crate lazy_static; +extern crate rustler; -use rustler::{Env, NifResult, Encoder, Term, SchedulerFlags}; -use calamine::{Reader, open_workbook_auto}; use calamine::Error as CaError; +use calamine::{open_workbook_auto, Reader}; +rustler::init!("Elixir.Xler.Native"); mod atoms { - rustler_atoms! { - atom ok; - atom error; + rustler::atoms! { + ok, + error, // Posix - atom enoent; // File does not exist - atom eacces; // Permission denied - atom epipe; // Broken pipe - atom eexist; // File exists + enoent, // File does not exist + eacces, // Permission denied + epipe, // Broken pipe + eexist, // File exists } } -rustler_export_nifs! { - "Elixir.Xler.Native", - [ - ("parse", 2, parse, SchedulerFlags::DirtyCpu), - ("worksheets", 1, worksheets, SchedulerFlags::DirtyCpu) - ], - None -} +type Sheet = Vec>; +type SheetName = String; +type Worksheets = Vec; -fn io_error_to_term<'a>(env: Env<'a>, err: &CaError) -> Term<'a> { +fn io_error_to_term(err: &CaError) -> String { let error = match err { - _ => format!("{}", err).encode(env), + _ => format!("{}", err), }; - (atoms::error(), error).encode(env) + error } -fn worksheets<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult> { - let filename: String = args[0].decode()?; - +#[rustler::nif(schedule = "DirtyCpu")] +fn worksheets(filename: String) -> Result { match open_workbook_auto(&filename) { - Err(ref error) => return Ok(io_error_to_term(env, error)), - Ok(ref inner) => Ok((atoms::ok(), inner.sheet_names().to_owned()).encode(env)), + Err(ref error) => Err(io_error_to_term(error)), + Ok(ref inner) => Ok(inner.sheet_names().to_owned()), } } - -fn parse<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult> { - let filename: String = args[0].decode()?; - let sheetname: String = args[1].decode()?; - +#[rustler::nif(schedule = "DirtyCpu")] +fn parse(filename: String, sheetname: SheetName) -> Result { let mut excel = match open_workbook_auto(&filename) { - Err(ref error) => return Ok(io_error_to_term(env, error)), + Err(ref error) => return Err(io_error_to_term(error)), Ok(inner) => inner, }; if let Some(Ok(range)) = excel.worksheet_range(&sheetname) { - let row: Vec<(Vec)> = range - .rows() - .into_iter() - .enumerate() - .map(|(_i, col)| - col - .iter() - .map(|c| - c.to_string() - ) - .collect::>() - ) - .collect::>(); + let row: Sheet = range + .rows() + .into_iter() + .enumerate() + .map(|(_i, col)| col.iter().map(|c| c.to_string()).collect::>()) + .collect::>(); - Ok((atoms::ok(), row.encode(env)).encode(env)) + Ok(row) } else { - Ok((atoms::error(), "Couldnt find the worksheet").encode(env)) + Err("Couldnt find the worksheet".to_string()) } }