diff --git a/.gitignore b/.gitignore index 46366ee..4dda793 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,35 @@ -# The directory Mix will write compiled artifacts to. -/_build/ - -# If you run "mix test --cover", coverage assets end up here. -/cover/ - -# The directory Mix downloads your dependencies sources to. -/deps/ - -# Where third-party dependencies like ExDoc output generated docs. -/doc/ - -# Ignore .fetch files in case you like to edit your project deps locally. -/.fetch - -# If the VM crashes, it generates a dump, let's ignore it too. -erl_crash.dump - -# Also ignore archive artifacts (built via "mix archive.build"). -*.ez - -# Ignore package tarball (built via "mix hex.build"). -ortex-*.tar - -# Temporary files, for example, from tests. -/tmp/ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +ortex-*.tar + +# Temporary files, for example, from tests. +/tmp/ + +# Priv output +/priv/native + +/lib/framework +/lib/mix +compile.bat +compile.sh +test.bat \ No newline at end of file diff --git a/config/config.exs b/config/config.exs index f693371..a31df1c 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,18 +1,19 @@ -import Config -# Something is setting this to IEx.Pry so we're overriding it for now. Remove -# if you need to do real debugging -config :elixir, :dbg_callback, {Macro, :dbg, []} - -config :ortex, - add_backend_on_inspect: config_env() != :test - -# Set the cargo feature flags required to use the matching execution provider -# based on the OS we're running on -ortex_features = - case :os.type() do - {:win32, _} -> ["directml"] - {:unix, :darwin} -> ["coreml"] - {:unix, _} -> ["cuda", "tensorrt"] - end - -config :ortex, Ortex.Native, features: ortex_features +import Config +# Something is setting this to IEx.Pry so we're overriding it for now. Remove +# if you need to do real debugging +config :elixir, :dbg_callback, {Macro, :dbg, []} + +config :ortex, + add_backend_on_inspect: config_env() != :test + +# Set the cargo feature flags required to use the matching execution provider +# based on the OS we're running on +ortex_features = + case :os.type() do + {:win32, _} -> ["directml"] + {:unix, :darwin} -> ["coreml"] + {:unix, _} -> ["cuda", "tensorrt"] + end + +#config :nx, default_backend: {Torchx.Backend, device: :cuda} +config :ortex, Ortex.Native, features: ortex_features diff --git a/lib/ortex/image.ex b/lib/ortex/image.ex new file mode 100644 index 0000000..b5e0f4f --- /dev/null +++ b/lib/ortex/image.ex @@ -0,0 +1,5 @@ +defmodule Ortex.Image do + def prepare(image, width, height, size \\ 640) do + Ortex.Native.prepare_image(image, width, height, size) + end +end diff --git a/lib/ortex/model.ex b/lib/ortex/model.ex index 2a5a2f9..b29e13b 100644 --- a/lib/ortex/model.ex +++ b/lib/ortex/model.ex @@ -1,90 +1,107 @@ -defmodule Ortex.Model do - @moduledoc """ - A model for running Ortex inference with. - - Implements a human-readable representation of a model including the name, dimension, and - type of each input and output - - ``` - #Ortex.Model< - inputs: [{"x", "Int32", [nil, 100]}, {"y", "Float32", [nil, 100]}] - outputs: [ - {"9", "Float32", [nil, 10]}, - {"onnx::Add_7", "Float32", [nil, 10]}, - {"onnx::Add_8", "Float32", [nil, 10]} - ]> - ``` - - `nil` values represent dynamic dimensions - """ - - @enforce_keys [:reference] - defstruct [:reference] - - @doc false - def load(path, eps \\ [:cpu], opt \\ 3) do - case Ortex.Native.init(path, eps, opt) do - {:error, msg} -> - raise msg - - model -> - %Ortex.Model{reference: model} - end - end - - @doc false - def run(%Ortex.Model{} = model, tensor) when not is_tuple(tensor) do - run(model, {tensor}) - end - - @doc false - def run(%Ortex.Model{reference: model}, tensors) do - # Move tensors into Ortex backend and pass the reference to the Ortex NIF - output = - case Ortex.Native.run( - model, - tensors - |> Tuple.to_list() - |> Enum.map(fn x -> x |> Nx.backend_transfer(Ortex.Backend) end) - |> Enum.map(fn %Nx.Tensor{data: %Ortex.Backend{ref: x}} -> x end) - ) do - {:error, msg} -> raise msg - output -> output - end - - # Pack the output into new Ortex.Backend tensor(s) - output - |> Enum.map(fn {ref, shape, dtype_atom, dtype_bits} -> - %Nx.Tensor{ - data: %Ortex.Backend{ref: ref}, - shape: shape |> List.to_tuple(), - type: {dtype_atom, dtype_bits}, - names: List.duplicate(nil, length(shape)) - } - end) - |> List.to_tuple() - end -end - -defimpl Inspect, for: Ortex.Model do - import Inspect.Algebra - - def inspect(%Ortex.Model{reference: model}, inspect_opts) do - case Ortex.Native.show_session(model) do - {:error, msg} -> - raise msg - - {inputs, outputs} -> - force_unfit( - concat([ - color("#Ortex.Model<", :map, inspect_opts), - line(), - nest(concat([" inputs: ", Inspect.List.inspect(inputs, inspect_opts)]), 2), - line(), - nest(concat([" outputs: ", Inspect.List.inspect(outputs, inspect_opts)]), 2), - color(">", :map, inspect_opts) - ]) - ) - end - end -end +defmodule Ortex.Model do + @moduledoc """ + A model for running Ortex inference with. + + Implements a human-readable representation of a model including the name, dimension, and + type of each input and output + + ``` + #Ortex.Model< + inputs: [{"x", "Int32", [nil, 100]}, {"y", "Float32", [nil, 100]}] + outputs: [ + {"9", "Float32", [nil, 10]}, + {"onnx::Add_7", "Float32", [nil, 10]}, + {"onnx::Add_8", "Float32", [nil, 10]} + ]> + ``` + + `nil` values represent dynamic dimensions + """ + + @enforce_keys [:reference] + defstruct [:reference] + + @doc false + def load(path, eps \\ [:cpu], opt \\ 3) do + case Ortex.Native.init(path, eps, opt) do + {:error, msg} -> + raise msg + + model -> + %Ortex.Model{reference: model} + end + end + + @doc false + def run(%Ortex.Model{} = model, tensor) when not is_tuple(tensor) do + run(model, {tensor}) + end + + @doc false + def run(%Ortex.Model{reference: model}, tensors) do + # Move tensors into Ortex backend and pass the reference to the Ortex NIF + output = + case Ortex.Native.run( + model, + tensors + |> Tuple.to_list() + |> Enum.map(fn x -> x |> Nx.backend_transfer(Ortex.Backend) end) + |> Enum.map(fn %Nx.Tensor{data: %Ortex.Backend{ref: x}} -> x end) + ) do + {:error, msg} -> raise msg + output -> output + end + + # Pack the output into new Ortex.Backend tensor(s) + output + |> Enum.map(fn {ref, shape, dtype_atom, dtype_bits} -> + %Nx.Tensor{ + data: %Ortex.Backend{ref: ref}, + shape: shape |> List.to_tuple(), + type: {dtype_atom, dtype_bits}, + names: List.duplicate(nil, length(shape)) + } + end) + |> List.to_tuple() + end + + def create_mask(coefficients, mask_prototypes, threshold \\ 0.5) do + prototypes_bin = Nx.to_binary(mask_prototypes) + # Tuple like {1, 32, 240, 240} + {_, _, width, height} = proto_shape = Nx.shape(mask_prototypes) + + Ortex.Native.create_mask(coefficients, prototypes_bin, proto_shape, threshold) + |> case do + binary_mask when is_binary(binary_mask) -> + binary_mask + |> Nx.from_binary(:u8) + |> Nx.reshape({width, height}) + + error -> + error + end + end +end + +defimpl Inspect, for: Ortex.Model do + import Inspect.Algebra + + def inspect(%Ortex.Model{reference: model}, inspect_opts) do + case Ortex.Native.show_session(model) do + {:error, msg} -> + raise msg + + {inputs, outputs} -> + force_unfit( + concat([ + color("#Ortex.Model<", :map, inspect_opts), + line(), + nest(concat([" inputs: ", Inspect.List.inspect(inputs, inspect_opts)]), 2), + line(), + nest(concat([" outputs: ", Inspect.List.inspect(outputs, inspect_opts)]), 2), + color(">", :map, inspect_opts) + ]) + ) + end + end +end diff --git a/lib/ortex/native.ex b/lib/ortex/native.ex index ee16c07..a214c35 100644 --- a/lib/ortex/native.ex +++ b/lib/ortex/native.ex @@ -1,42 +1,45 @@ -defmodule Ortex.Native do - @moduledoc false - - @rustler_version Application.spec(:rustler, :vsn) |> to_string() |> Version.parse!() - - # We have to compile the crate before `use Rustler` compiles the crate since - # cargo downloads the onnxruntime shared libraries and they are not available - # to load or copy into Elixir's during the on_load or Elixir compile steps. - # In the future, this may be configurable in Rustler. - if Version.compare(@rustler_version, "0.30.0") in [:gt, :eq] do - Rustler.Compiler.compile_crate(:ortex, Application.compile_env(:ortex, __MODULE__, []), - otp_app: :ortex, - crate: :ortex - ) - else - Rustler.Compiler.compile_crate(__MODULE__, otp_app: :ortex, crate: :ortex) - end - - Ortex.Util.copy_ort_libs() - - use Rustler, - otp_app: :ortex, - crate: :ortex, - skip_compilation?: true - - # When loading a NIF module, dummy clauses for all NIF function are required. - # NIF dummies usually just error out when called when the NIF is not loaded, as that should never normally happen. - def init(_model_path, _execution_providers, _optimization_level), - do: :erlang.nif_error(:nif_not_loaded) - - def run(_model, _inputs), do: :erlang.nif_error(:nif_not_loaded) - def from_binary(_bin, _shape, _type), do: :erlang.nif_error(:nif_not_loaded) - def to_binary(_reference, _bits, _limit), do: :erlang.nif_error(:nif_not_loaded) - def show_session(_model), do: :erlang.nif_error(:nif_not_loaded) - - def slice(_tensor, _start_indicies, _lengths, _strides), - do: :erlang.nif_error(:nif_not_loaded) - - def reshape(_tensor, _shape), do: :erlang.nif_error(:nif_not_loaded) - - def concatenate(_tensors_refs, _type, _axis), do: :erlang.nif_error(:nif_not_loaded) -end +defmodule Ortex.Native do + @moduledoc false + + @rustler_version Application.spec(:rustler, :vsn) |> to_string() |> Version.parse!() + + # We have to compile the crate before `use Rustler` compiles the crate since + # cargo downloads the onnxruntime shared libraries and they are not available + # to load or copy into Elixir's during the on_load or Elixir compile steps. + # In the future, this may be configurable in Rustler. + if Version.compare(@rustler_version, "0.30.0") in [:gt, :eq] do + Rustler.Compiler.compile_crate(:ortex, Application.compile_env(:ortex, __MODULE__, []), + otp_app: :ortex, + crate: :ortex + ) + else + Rustler.Compiler.compile_crate(__MODULE__, otp_app: :ortex, crate: :ortex) + end + + Ortex.Util.copy_ort_libs() + + use Rustler, + otp_app: :ortex, + crate: :ortex, + skip_compilation?: true + + # When loading a NIF module, dummy clauses for all NIF function are required. + # NIF dummies usually just error out when called when the NIF is not loaded, as that should never normally happen. + def init(_model_path, _execution_providers, _optimization_level), + do: :erlang.nif_error(:nif_not_loaded) + + def run(_model, _inputs), do: :erlang.nif_error(:nif_not_loaded) + def from_binary(_bin, _shape, _type), do: :erlang.nif_error(:nif_not_loaded) + def to_binary(_reference, _bits, _limit), do: :erlang.nif_error(:nif_not_loaded) + def show_session(_model), do: :erlang.nif_error(:nif_not_loaded) + + def slice(_tensor, _start_indicies, _lengths, _strides), + do: :erlang.nif_error(:nif_not_loaded) + + def reshape(_tensor, _shape), do: :erlang.nif_error(:nif_not_loaded) + + def concatenate(_tensors_refs, _type, _axis), do: :erlang.nif_error(:nif_not_loaded) + + def create_mask(_coefficients, _prototypes_bin, _proto_shape_term, _threshold), do: :erlang.nif_error(:nif_not_loaded) + def prepare_image(_binary, _width, _height, _size), do: :erlang.nif_error(:nif_not_loaded) +end diff --git a/mix.exs b/mix.exs index 0ff357e..827214e 100644 --- a/mix.exs +++ b/mix.exs @@ -1,52 +1,55 @@ -defmodule Ortex.MixProject do - use Mix.Project - - def project do - [ - app: :ortex, - version: "0.1.10", - elixir: "~> 1.14", - start_permanent: Mix.env() == :prod, - deps: deps(), - - # Docs - name: "Ortex", - source_url: "https://github.com/elixir-nx/ortex", - homepage_url: "http://github.com/elixir-nx/ortex", - docs: [ - main: "readme", - extras: ["README.md"] - ], - package: package() - ] - end - - # Run "mix help compile.app" to learn about applications. - def application do - [ - extra_applications: [:logger] - ] - end - - # Run "mix help deps" to learn about dependencies. - defp deps do - [ - {:rustler, "~> 0.27"}, - {:nx, "~> 0.6"}, - {:tokenizers, "~> 0.4", only: :dev}, - {:ex_doc, "0.29.4", only: :dev, runtime: false}, - {:exla, "~> 0.6", only: :dev}, - {:torchx, "~> 0.6", only: :dev} - ] - end - - defp package do - [ - files: ~w(lib .formatter.exs mix.exs README* LICENSE* native/ortex/src/ config/config.exs - native/ortex/Cargo.lock native/ortex/Cargo.toml native/ortex/.cargo/config.toml), - licenses: ["MIT"], - links: %{"GitHub" => "https://github.com/elixir-nx/ortex"}, - description: "ONNX Runtime bindings for Elixir" - ] - end -end +defmodule Ortex.MixProject do + use Mix.Project + + def project do + [ + app: :ortex, + version: "0.1.10", + elixir: "~> 1.14", + start_permanent: Mix.env() == :prod, + deps: deps(), + + # Docs + name: "Ortex", + source_url: "https://github.com/elixir-nx/ortex", + homepage_url: "http://github.com/elixir-nx/ortex", + docs: [ + main: "readme", + extras: ["README.md"] + ], + package: package() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:rustler, "~> 0.37"}, + {:nx, "~> 0.10"}, + {:tokenizers, "~> 0.5", only: :dev}, + {:ex_doc, "~> 0.38", only: :dev, runtime: false}, + # {:exla, "~> 0.6", only: :dev}, + # {:torchx, "~> 0.6", only: :dev} + {:typed_struct, "~> 0.3.0"}, + {:evision, "~> 0.2.14"} + # {:torchx, "~> 0.10"} + ] + end + + defp package do + [ + files: ~w(lib .formatter.exs mix.exs README* LICENSE* native/ortex/src/ config/config.exs + native/ortex/Cargo.lock native/ortex/Cargo.toml native/ortex/.cargo/config.toml), + licenses: ["MIT"], + links: %{"GitHub" => "https://github.com/elixir-nx/ortex"}, + description: "ONNX Runtime bindings for Elixir" + ] + end +end diff --git a/mix.lock b/mix.lock index 8b9284d..5327f1b 100644 --- a/mix.lock +++ b/mix.lock @@ -1,30 +1,21 @@ %{ - "axon": {:hex, :axon, "0.5.1", "1ae3a2193df45e51fca912158320b2ca87cb7fba4df242bd3ebe245504d0ea1a", [:mix], [{:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}, {:kino_vega_lite, "~> 0.1.7", [hex: :kino_vega_lite, repo: "hexpm", optional: true]}, {:nx, "~> 0.5.0", [hex: :nx, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: true]}], "hexpm", "d36f2a11c34c6c2b458f54df5c71ffdb7ed91c6a9ccd908faba909c84cc6a38e"}, - "axon_onnx": {:hex, :axon_onnx, "0.4.0", "7be4b5ac7a44340ec65eb59c24122a8fe2aa8105da33b3321a378b455a6cd9c6", [:mix], [{:axon, "~> 0.5", [hex: :axon, repo: "hexpm", optional: false]}, {:nx, "~> 0.5", [hex: :nx, repo: "hexpm", optional: false]}, {:protox, "~> 1.6.10", [hex: :protox, repo: "hexpm", optional: false]}], "hexpm", "b98c84e5656caf156ef8998296836349a62bc35598f05cc21eececbbef022d09"}, - "castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, - "cc_precompiler": {:hex, :cc_precompiler, "0.1.7", "77de20ac77f0e53f20ca82c563520af0237c301a1ec3ab3bc598e8a96c7ee5d9", [:mix], [{:elixir_make, "~> 0.7.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2768b28bf3c2b4f788c995576b39b8cb5d47eb788526d93bd52206c1d8bf4b75"}, - "complex": {:hex, :complex, "0.5.0", "af2d2331ff6170b61bb738695e481b27a66780e18763e066ee2cd863d0b1dd92", [:mix], [], "hexpm", "2683bd3c184466cfb94fad74cbfddfaa94b860e27ad4ca1bffe3bff169d91ef1"}, - "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, - "dll_loader_helper": {:hex, :dll_loader_helper, "1.1.0", "e7d015e980942a0d67e306827ec907e7e853a21186bd92bb968d986698591a0f", [:mix], [{:dll_loader_helper_beam, "~> 1.1", [hex: :dll_loader_helper_beam, repo: "hexpm", optional: false]}], "hexpm", "2b6c11ee7bb48f6a132ce8f872202f9e828c019988da1e2d40ad41496195df0c"}, - "dll_loader_helper_beam": {:hex, :dll_loader_helper_beam, "1.2.0", "557c43befb8e3b119b718da302adccde3bd855acdb999498a14a2a8d2814b8b9", [:rebar3], [], "hexpm", "a2115d4bf1cca488a7b33f3c648847f64019b32c0382d10286d84dd5c3cbc0e5"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.32", "fa739a0ecfa34493de19426681b23f6814573faee95dfd4b4aafe15a7b5b32c6", [:mix], [], "hexpm", "b8b0dd77d60373e77a3d7e8afa598f325e49e8663a51bcc2b88ef41838cca755"}, - "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, - "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [: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", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"}, - "exla": {:hex, :exla, "0.6.1", "a4400933a04d018c5fb508c75a080c73c3c1986f6c16a79bbfee93ba22830d4d", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nx, "~> 0.6.1", [hex: :nx, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:xla, "~> 0.5.0", [hex: :xla, repo: "hexpm", optional: false]}], "hexpm", "f0e95b0f91a937030cf9fcbe900c9d26933cb31db2a26dfc8569aa239679e6d4"}, - "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, - "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.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, - "nx": {:hex, :nx, "0.6.2", "f1d137f477b1a6f84f8db638f7a6d5a0f8266caea63c9918aa4583db38ebe1d6", [:mix], [{:complex, "~> 0.5", [hex: :complex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ac913b68d53f25f6eb39bddcf2d2cd6ea2e9bcb6f25cf86a79e35d0411ba96ad"}, - "protox": {:hex, :protox, "1.6.10", "41d0b0c5b9190e7d5e6a2b1a03a09257ead6f3d95e6a0cf8b81430b526126908", [:mix], [{:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "9769fca26ae7abfc5cc61308a1e8d9e2400ff89a799599cee7930d21132832d9"}, - "rustler": {:hex, :rustler, "0.29.1", "880f20ae3027bd7945def6cea767f5257bc926f33ff50c0d5d5a5315883c084d", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "109497d701861bfcd26eb8f5801fe327a8eef304f56a5b63ef61151ff44ac9b6"}, - "rustler_precompiled": {:hex, :rustler_precompiled, "0.7.0", "5d0834fc06dbc76dd1034482f17b1797df0dba9b491cef8bb045fcaca94bcade", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "fdf43a6835f4e4de5bfbc4c019bfb8c46d124bd4635fefa3e20d9a2bbbec1512"}, - "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, - "tokenizers": {:hex, :tokenizers, "0.4.0", "140283ca74a971391ddbd83cd8cbdb9bd03736f37a1b6989b82d245a95e1eb97", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.6", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "ef1a9824f5a893cd3b831c0e5b3d72caa250d2ec462035cc6afef6933b13a82e"}, + "castore": {:hex, :castore, "1.0.15", "8aa930c890fe18b6fe0a0cff27b27d0d4d231867897bd23ea772dee561f032a3", [:mix], [], "hexpm", "96ce4c69d7d5d7a0761420ef743e2f4096253931a3ba69e5ff8ef1844fe446d3"}, + "complex": {:hex, :complex, "0.6.0", "b0130086a7a8c33574d293b2e0e250f4685580418eac52a5658a4bd148f3ccf1", [:mix], [], "hexpm", "0a5fa95580dcaf30fcd60fe1aaf24327c0fe401e98c24d892e172e79498269f9"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"}, + "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, + "evision": {:hex, :evision, "0.2.14", "6005e44b38ea61a33109694c5b097d42e81c767723c55d0c230d9662d6c87987", [:make, :mix, :rebar3], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.11", [hex: :kino, repo: "hexpm", optional: true]}, {:nx, "~> 0.6", [hex: :nx, repo: "hexpm", optional: false]}, {:progress_bar, "~> 2.0 or ~> 3.0", [hex: :progress_bar, repo: "hexpm", optional: true]}], "hexpm", "630714395f2c242e488944b4c9c75a5de96cbb95d3cbb69f0525bdb3e0a88775"}, + "ex_doc": {:hex, :ex_doc, "0.38.4", "ab48dff7a8af84226bf23baddcdda329f467255d924380a0cf0cee97bb9a9ede", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "f7b62346408a83911c2580154e35613eb314e0278aeea72ed7fedef9c1f165b2"}, + "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.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, + "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, + "makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"}, + "nx": {:hex, :nx, "0.10.0", "128e4a094cb790f663e20e1334b127c1f2a4df54edfb8b13c22757ec33133b4f", [:mix], [{:complex, "~> 0.6", [hex: :complex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3db8892c124aeee091df0e6fbf8e5bf1b81f502eb0d4f5ba63e6378ebcae7da4"}, + "rustler": {:hex, :rustler, "0.37.1", "721434020c7f6f8e1cdc57f44f75c490435b01de96384f8ccb96043f12e8a7e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "24547e9b8640cf00e6a2071acb710f3e12ce0346692e45098d84d45cdb54fd79"}, + "rustler_precompiled": {:hex, :rustler_precompiled, "0.8.3", "4e741024b0b097fe783add06e53ae9a6f23ddc78df1010f215df0c02915ef5a8", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "c23f5f33cb6608542de4d04faf0f0291458c352a4648e4d28d17ee1098cddcc4"}, + "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, + "tokenizers": {:hex, :tokenizers, "0.5.1", "b0975d92b4ee5b18e8f47b5d65b9d5f1e583d9130189b1a2620401af4e7d4b35", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.6", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "5f08d97cc7f2ed3d71d370d68120da6d3de010948ccf676c9c0eb591ba4bacc9"}, "toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"}, - "torchx": {:hex, :torchx, "0.6.1", "2a9862ebc4b397f42c51f0fa3f9f4e3451a83df6fba42882f8523cbc925c8ae1", [:make, :mix], [{:dll_loader_helper, "~> 0.1 or ~> 1.0", [hex: :dll_loader_helper, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nx, "~> 0.6.1", [hex: :nx, repo: "hexpm", optional: false]}], "hexpm", "99b3fc73b52d6cfbe5cad8bdd74277ddc99297ce8fc6765b1dabec80681e8d9d"}, - "useful": {:hex, :useful, "1.11.0", "b2d89223563c3354fd56f4da75b63f07f52cb32b243289a7f1fcc37869bcf9c2", [:mix], [], "hexpm", "2e5b2a47acc191bfb38e936f5f1bc57dad3b11133e0defe59a32fda10ebafcff"}, - "xla": {:hex, :xla, "0.5.1", "8ba4c2c51c1a708ff54e9d4f88158c1a75b7f2cb3e5db02bf222b5b3852afffd", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "82a2490f6e9a76c8a29d1aedb47f07c59e3d5081095eac5a74db34d46c8212bc"}, + "torchx": {:hex, :torchx, "0.10.1", "05497c08f1e6439a5e3b674b8e7d3f2f8359aae6b4c13dc4de8f004b4ee54187", [:mix], [{:nx, "~> 0.10.0", [hex: :nx, repo: "hexpm", optional: false]}], "hexpm", "906fac492f8062b20ca0bb656caea54350860d3987f4974724c24c9ba5ea2e19"}, + "typed_struct": {:hex, :typed_struct, "0.3.0", "939789e3c1dca39d7170c87f729127469d1315dcf99fee8e152bb774b17e7ff7", [:mix], [], "hexpm", "c50bd5c3a61fe4e198a8504f939be3d3c85903b382bde4865579bc23111d1b6d"}, } diff --git a/native/ortex/Cargo.lock b/native/ortex/Cargo.lock index cd74a84..7ba1a68 100644 --- a/native/ortex/Cargo.lock +++ b/native/ortex/Cargo.lock @@ -1,33 +1,141 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] -name = "aho-corasick" -version = "0.7.20" +name = "aligned-vec" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" dependencies = [ - "memchr", + "equator", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "av1-grain" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "aws-lc-rs" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879b6c89592deb404ba4dc0ae6b58ffd1795c78991cbb5b8bc441c48a070440d" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b715a6010afb9e457ca2b7c9d2b9c344baa8baed7b38dc476034c171b32575" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", + "libloading", +] + [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bindgen" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.4.2", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" @@ -41,6 +149,12 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + [[package]] name = "block-buffer" version = "0.10.4" @@ -50,19 +164,70 @@ dependencies = [ "generic-array", ] +[[package]] +name = "built" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + [[package]] name = "cc" -version = "1.0.83" +version = "1.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" dependencies = [ + "jobserver", "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec 1.13.1", + "target-lexicon", ] [[package]] @@ -71,6 +236,48 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -89,6 +296,31 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crunchy" version = "0.2.2" @@ -105,6 +337,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "pem-rfc7468", + "zeroize", +] + [[package]] name = "digest" version = "0.10.7" @@ -115,6 +357,44 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.8" @@ -122,7 +402,57 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec 1.13.1", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", ] [[package]] @@ -134,28 +464,46 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] -name = "form_urlencoded" -version = "1.2.1" +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "percent-encoding", + "foreign-types-shared", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "generic-array" version = "0.14.7" @@ -177,30 +525,154 @@ dependencies = [ "wasi", ] +[[package]] +name = "gif" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + [[package]] name = "half" -version = "2.3.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] -name = "heck" -version = "0.4.1" +name = "hashbrown" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] -name = "idna" +name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "image" +version = "0.25.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "inventory" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "rustversion", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", ] [[package]] @@ -209,12 +681,38 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libfuzzer-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.2", +] + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -223,11 +721,17 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.17" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "cfg-if", + "imgref", ] [[package]] @@ -240,27 +744,71 @@ dependencies = [ ] [[package]] -name = "matrixmultiply" -version = "0.3.2" +name = "matrixmultiply" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" +dependencies = [ + "rawpointer", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "rawpointer", + "adler2", + "simd-adler32", ] [[package]] -name = "memchr" -version = "2.5.0" +name = "moxcms" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "c588e11a3082784af229e23e8e4ecf5bcc6fbe4f69101e0421ce8d79da7f0b40" +dependencies = [ + "num-traits", + "pxfm", +] [[package]] -name = "miniz_oxide" -version = "0.7.2" +name = "native-tls" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ - "adler", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] @@ -278,6 +826,28 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -288,6 +858,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-complex" version = "0.4.3" @@ -297,6 +878,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -307,11 +899,22 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -322,23 +925,68 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "openssl" +version = "0.10.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "ort" -version = "2.0.0-rc.8" +version = "2.0.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11826e6118cc42fea0cb2b102f7d006c1bb339cb167f8badb5fb568616438234" +checksum = "1fa7e49bd669d32d7bc2a15ec540a527e7764aec722a45467814005725bcd721" dependencies = [ "half", "ndarray", "ort-sys", + "smallvec 2.0.0-alpha.10", "tracing", ] [[package]] name = "ort-sys" -version = "2.0.0-rc.8" +version = "2.0.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4780a8b8681e653b2bed85c7f0e2c6e8547224c3e983e5ad27bf0457e012407" +checksum = "e2aba9f5c7c479925205799216e7e5d07cc1d4fa76ea8058c60a9a30f6a4e890" dependencies = [ "flate2", "pkg-config", @@ -352,12 +1000,15 @@ name = "ortex" version = "0.1.0" dependencies = [ "half", + "image", "ndarray", "num-traits", "ort", + "ort-sys", "rustler", "rustls", "tracing-subscriber", + "wide", ] [[package]] @@ -366,6 +1017,21 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -384,6 +1050,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "png" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" +dependencies = [ + "bitflags 2.4.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "portable-atomic" version = "1.9.0" @@ -399,30 +1078,192 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "pxfm" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" +dependencies = [ + "num-traits", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" -version = "1.0.27" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + [[package]] name = "rawpointer" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -438,8 +1279,6 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ - "aho-corasick", - "memchr", "regex-syntax", ] @@ -452,12 +1291,24 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + [[package]] name = "regex-syntax" version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "rgb" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" + [[package]] name = "ring" version = "0.17.8" @@ -470,9 +1321,15 @@ dependencies = [ "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustix" version = "0.38.31" @@ -483,71 +1340,162 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustler" -version = "0.29.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884cb623b9f43d3e2c51f9071c5e96a5acf3e6e6007866812884ff0cb983f1e" +checksum = "fb867bb35b291ef105abbe0a0d04bd4d7af372e023d08845698687bc254f222b" dependencies = [ - "lazy_static", + "inventory", + "libloading", + "regex-lite", "rustler_codegen", - "rustler_sys", ] [[package]] name = "rustler_codegen" -version = "0.29.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e277af754f2560cf4c4ebedb68c1a735292fb354505c6133e47ec406e699cf" +checksum = "90993223c5ac0fb580ff966fb9477289c4e8a610a2f4639912a2639c5e7b5095" dependencies = [ "heck", + "inventory", "proc-macro2", "quote", "syn", ] [[package]] -name = "rustler_sys" -version = "2.3.2" +name = "rustls" +version = "0.23.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76ba8524729d7c9db2b3e80f2269d1fdef39b5a60624c33fd794797e69b558" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ - "regex", - "unreachable", + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] -name = "rustls" -version = "0.22.4" +name = "rustls-pemfile" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "log", - "ring", "rustls-pki-types", - "rustls-webpki", - "subtle", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ "zeroize", ] [[package]] -name = "rustls-pki-types" -version = "1.3.0" +name = "rustls-webpki" +version = "0.103.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "safe_arch" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb5032219cc30e5bb98749b19a18ceb2cf15e24ba8d517a7e64dff4f1f1eca5" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "security-framework" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048a63e5b3ac996d78d402940b5fa47973d2d080c6c6fffa1d0f19c4445310b7" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "rustls-webpki" -version = "0.102.2" +name = "serde_spanned" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", + "serde", ] [[package]] @@ -570,12 +1518,39 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "smallvec" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +[[package]] +name = "smallvec" +version = "2.0.0-alpha.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d44cfb396c3caf6fbfd0ab422af02631b69ddd96d2eff0b0f0724f9024051b" + [[package]] name = "socks" version = "0.3.4" @@ -601,15 +1576,28 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.16" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + [[package]] name = "tar" version = "0.4.40" @@ -621,6 +1609,45 @@ dependencies = [ "xattr", ] +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -632,19 +1659,52 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tiff" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" dependencies = [ - "tinyvec_macros", + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", ] [[package]] -name = "tinyvec_macros" -version = "0.1.1" +name = "toml" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] [[package]] name = "tracing" @@ -689,7 +1749,7 @@ dependencies = [ "once_cell", "regex", "sharded-slab", - "smallvec", + "smallvec 1.13.1", "thread_local", "tracing", "tracing-core", @@ -702,36 +1762,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -dependencies = [ - "void", -] - [[package]] name = "untrusted" version = "0.9.0" @@ -740,30 +1776,50 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.6" +version = "3.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f214ce18d8b2cbe84ed3aa6486ed3f5b285cf8d8fbdbce9f3f767a724adc35" +checksum = "9f0fde9bc91026e381155f8c67cb354bcd35260b2f4a29bcc84639f762760c39" dependencies = [ "base64", + "der", "log", - "once_cell", - "rustls", + "native-tls", + "percent-encoding", + "rustls-pemfile", "rustls-pki-types", - "rustls-webpki", "socks", - "url", - "webpki-roots", + "ureq-proto", + "utf-8", + "webpki-root-certs 0.26.11", ] [[package]] -name = "url" -version = "2.5.0" +name = "ureq-proto" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7" dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", + "base64", + "http", + "httparse", + "log", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", ] [[package]] @@ -773,16 +1829,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] -name = "version_check" -version = "0.9.4" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] -name = "void" -version = "1.0.2" +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" @@ -791,14 +1853,98 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "webpki-roots" -version = "0.26.1" +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "webpki-root-certs" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" +dependencies = [ + "webpki-root-certs 1.0.1", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "86138b15b2b7d561bc4469e77027b8dd005a43dc502e9031d1f5afc8ce1f280e" dependencies = [ "rustls-pki-types", ] +[[package]] +name = "weezl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "wide" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e9aba2ca45c04ecbf5c516b21b4a16ddb2cc43f69c10adb08956c2fe1ec081" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "winapi" version = "0.3.9" @@ -827,65 +1973,154 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] [[package]] name = "xattr" @@ -898,8 +2133,52 @@ dependencies = [ "rustix", ] +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +dependencies = [ + "zune-core", +] diff --git a/native/ortex/Cargo.toml b/native/ortex/Cargo.toml index 4052470..5d4c435 100644 --- a/native/ortex/Cargo.toml +++ b/native/ortex/Cargo.toml @@ -1,26 +1,42 @@ -[package] -name = "ortex" -version = "0.1.0" -authors = [] -edition = "2018" - -[lib] -name = "ortex" -path = "src/lib.rs" -crate-type = ["cdylib"] - -[dependencies] -rustler = "0.29.0" -ort = { version = "2.0.0-rc.8" } -ndarray = "0.16.1" -half = "2.2.1" -tracing-subscriber = { version = "0.3", features = [ "env-filter", "fmt" ] } -num-traits = "0.2.15" -rustls = "0.22.4" - -[features] -# ONNXRuntime Execution providers -directml = ["ort/directml"] -coreml = ["ort/coreml"] -cuda = ["ort/cuda"] -tensorrt = ["ort/tensorrt"] +[package] +authors = [] +edition = "2021" +name = "ortex" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] +name = "ortex" +path = "src/lib.rs" + +[workspace] +resolver = "2" + +[dependencies] +half = "2.7.1" +image = "0.25" +ndarray = "0.16.1" +num-traits = "0.2.19" +ort = {version = "2.0.0-rc.10", features = [ + "half", + "cuda", + # "directml", + "tensorrt", + # "coreml", +]} +ort-sys = {version = "=2.0.0-rc.10", default-features = false} +rustler = "0.37" +rustls = "0.23.34" +tracing-subscriber = {version = "0.3", features = ["env-filter", "fmt"]} +wide = "0.8.1" + +# [profile.dev] +# debug = true # Enables full DWARF/PDB symbols (default on most platforms) + +[features] +# ONNXRuntime Execution providers +# coreml = ["ort/coreml"] +# directml = ["ort/directml"] +cuda = ["ort/cuda"] +# directml = ["ort/directml"] +tensorrt = ["ort/tensorrt"] diff --git a/native/ortex/src/image.rs b/native/ortex/src/image.rs new file mode 100644 index 0000000..1f6382c --- /dev/null +++ b/native/ortex/src/image.rs @@ -0,0 +1,217 @@ +use image::{DynamicImage, GenericImage, ImageBuffer, Rgb, Rgba}; +use rustler::{Binary, Encoder, Env, Error, NifResult, OwnedBinary, Term}; +//use std::time::Instant; +use wide::{f32x16, u8x16}; // For optional profiling + +mod atoms { + rustler::atoms! { + ok, + error, + } +} + +pub fn prepare_image<'a>( + env: Env<'a>, + bin: Binary, + width: u32, + height: u32, + size: u32, +) -> NifResult> { + let input_vec: Vec = bin.as_slice().to_vec(); + + match resize_and_normalize_to_tensor(input_vec, width, height, size) { + Ok(f32_bytes) => { + // Create Binary via OwnedBinary for allocation and copy (handle Option safely) + let mut owned = match OwnedBinary::new(f32_bytes.len()) { + Some(o) => o, + None => return Err(Error::BadArg.into()), + }; + owned.as_mut_slice().copy_from_slice(&f32_bytes); + let output_bin = Binary::from_owned(owned, env); + + Ok((atoms::ok(), output_bin).encode(env)) + } + Err(e) => { + // Create error Binary via OwnedBinary (handle Option safely) + let mut owned = match OwnedBinary::new(e.len()) { + Some(o) => o, + None => return Err(Error::BadArg.into()), + }; + owned.as_mut_slice().copy_from_slice(e.as_bytes()); + let err_bin = Binary::from_owned(owned, env); + Ok((atoms::error(), err_bin).encode(env)) + } + } +} + +fn custom_letterbox_resize( + original: &DynamicImage, + target_w: u32, + target_h: u32, + pad_val: u8, +) -> DynamicImage { + let orig_img = original.to_rgb8(); + let (orig_w, orig_h) = orig_img.dimensions(); + let orig_raw = orig_img.as_raw(); + + let scale_w = target_w as f32 / orig_w as f32; + let scale_h = target_h as f32 / orig_h as f32; + let scale = scale_w.min(scale_h); + + let new_w = (orig_w as f32 * scale).round() as u32; + let new_h = (orig_h as f32 * scale).round() as u32; + + // Resize to new size (nearest) + let mut resized_raw = Vec::with_capacity((new_w * new_h * 3) as usize); + resized_raw.resize((new_w * new_h * 3) as usize, 0u8); + + let scale_x = orig_w as f32 / new_w as f32; + let scale_y = orig_h as f32 / new_h as f32; + + for y in 0..new_h { + for x in 0..new_w { + let src_x = (x as f32 * scale_x).round() as usize; + let src_y = (y as f32 * scale_y).round() as usize; + + let src_x = src_x.min((orig_w - 1) as usize); + let src_y = src_y.min((orig_h - 1) as usize); + + let src_offset = ((src_y * orig_w as usize + src_x) * 3) as usize; + let dst_offset = ((y * new_w + x) * 3) as usize; + + resized_raw[dst_offset] = orig_raw[src_offset]; // R + resized_raw[dst_offset + 1] = orig_raw[src_offset + 1]; // G + resized_raw[dst_offset + 2] = orig_raw[src_offset + 2]; // B + } + } + + let resized_img: ImageBuffer, Vec> = + ImageBuffer::from_raw(new_w, new_h, resized_raw).unwrap(); + + // Pad to target (center, with pad_val) + let pad_x = ((target_w - new_w) / 2) as usize; + let pad_y = ((target_h - new_h) / 2) as usize; + + let mut padded_raw = Vec::with_capacity((target_w * target_h * 3) as usize); + padded_raw.resize((target_w * target_h * 3) as usize, pad_val); + + let padded_img = ImageBuffer::from_raw(target_w, target_h, padded_raw).unwrap(); + let mut padded = DynamicImage::ImageRgb8(padded_img); + + // Copy resized to center (convert Rgb to Rgba for put_pixel) + for y in 0..new_h { + for x in 0..new_w { + if let Some(px) = resized_img.get_pixel_checked(x, y) { + let rgba_px = Rgba([px.0[0], px.0[1], px.0[2], 255u8]); + padded.put_pixel(pad_x as u32 + x, pad_y as u32 + y, rgba_px); + } + } + } + + //let _ = padded.save("C:/tmp/test.jpg"); + + padded +} + +fn resize_and_normalize_to_tensor( + input: Vec, + width: u32, + height: u32, + size: u32, +) -> Result, &'static str> { + //let start_load = Instant::now(); + let original_img = if width == 0 && height == 0 { + // File format (JPEG/BMP/etc.) + image::load_from_memory(&input) + .map_err(|_| "Failed to load image")? + .to_rgb8() + } else { + // Raw BGR HWC u8 from Evision.Mat.to_binary() + let orig_raw = input.as_slice(); + let mut rgb_raw = vec![0u8; input.len()]; + for y in 0..height as usize { + for x in 0..width as usize { + let offset = (y * width as usize + x) * 3; + rgb_raw[offset] = orig_raw[offset + 2]; // R = BGR[2] + rgb_raw[offset + 1] = orig_raw[offset + 1]; // G = BGR[1] + rgb_raw[offset + 2] = orig_raw[offset]; // B = BGR[0] + } + } + ImageBuffer::from_raw(width, height, rgb_raw).ok_or("Invalid raw dimensions")? + }; + //println!("Load time: {:?}", start_load.elapsed()); + + //let start_resize = Instant::now(); + let img = { + let dynamic_img = DynamicImage::ImageRgb8(original_img); + custom_letterbox_resize(&dynamic_img, size, size, 114) // Custom fast resize + }; + // println!("Resize time: {:?}", start_resize.elapsed()); + + //let start_loop = Instant::now(); + let h = size as usize; + let w = h; + + let hw = h * w; + let total_bytes = 4 * 1 * 3 * hw; // f32 bytes, batch=1, CHW + let mut tensor: Vec = vec![0u8; total_bytes]; // Pre-allocate full len with 0s + + let rgb_img = img.to_rgb8(); // Bind temporary to extend lifetime + let raw_pixels = rgb_img.as_raw(); // Now safe borrow + let bytes_per_pixel = 3usize; + let row_stride = w * bytes_per_pixel; // Hoist row calculation + let norm_scale = f32x16::splat(1.0 / 255.0); // SIMD scale + + // SIMD CHW build: 3 passes (B, G, R for BGR) + for bgr_ch in 0..3 { + let rgb_idx = 2 - bgr_ch; // BGR mapping + for y in 0..h { + let row_offset = y * row_stride; + let mut x = 0; + while x + 16 <= w { + // Load 16 u8 for channel (strided) + let mut u8_arr = [0u8; 16]; + for i in 0..16 { + let pixel_offset = row_offset + (x + i) * bytes_per_pixel + rgb_idx; + u8_arr[i] = raw_pixels[pixel_offset]; + } + let u8_vals = u8x16::new(u8_arr); + + // Cast/normalize SIMD + let f32_arr: [f32; 16] = u8_vals.as_array().map(|u| u as f32); + let f32_vals = f32x16::new(f32_arr); + let norm_vec = f32_vals * norm_scale; + + // Store via ptr loop (unsafe wrapped) + let tensor_base = bgr_ch * hw + y * w + x; + let tensor_offset = tensor_base * 4usize; // f32 stride + unsafe { + let tensor_ptr = tensor.as_mut_ptr().add(tensor_offset).cast::(); + let norm_arr = norm_vec.as_array(); + for i in 0..16 { + let f32_ptr = tensor_ptr.add(i); + *f32_ptr = norm_arr[i]; + } + } + + x += 16; + } + + // Scalar tail + for tail in x..w { + let pixel_offset = row_offset + tail * bytes_per_pixel + rgb_idx; + let val_u8 = raw_pixels[pixel_offset]; + let norm_val = (val_u8 as f32) * norm_scale.as_array()[0]; + let tensor_offset = (bgr_ch * hw + y * w + tail) * 4usize; + unsafe { + let f32_ptr = tensor.as_mut_ptr().add(tensor_offset).cast::(); + *f32_ptr = norm_val; + } + } + } + } + + // println!("Loop time: {:?}", start_loop.elapsed()); + + Ok(tensor) +} diff --git a/native/ortex/src/lib.rs b/native/ortex/src/lib.rs index 0523105..53db827 100644 --- a/native/ortex/src/lib.rs +++ b/native/ortex/src/lib.rs @@ -1,124 +1,144 @@ -//! # Ortex -//! Rust bindings between [ONNX Runtime](https://github.com/microsoft/onnxruntime) and -//! Erlang/Elixir using [Ort](https://docs.rs/ort) and [Rustler](https://docs.rs/rustler). -//! These are only meant to be accessed via the NIF interface provided by Rustler and not -//! directly. - -mod constants; -mod model; -mod tensor; -mod utils; - -use model::OrtexModel; -use tensor::OrtexTensor; - -use rustler::resource::ResourceArc; -use rustler::types::Binary; -use rustler::{Atom, Env, NifResult, Term}; - -#[rustler::nif(schedule = "DirtyIo")] -fn init( - env: Env, - model_path: String, - eps: Vec, - opt: i32, -) -> NifResult> { - let eps = utils::map_eps(env, eps); - let model = model::init(model_path, eps, opt) - .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?; - Ok(ResourceArc::new(model)) -} - -#[rustler::nif] -fn show_session( - model: ResourceArc, -) -> NifResult<( - Vec<(String, String, Option>)>, - Vec<(String, String, Option>)>, -)> { - Ok(model::show(model)) -} - -#[rustler::nif(schedule = "DirtyIo")] -fn run( - model: ResourceArc, - inputs: Vec>, -) -> NifResult, Vec, Atom, usize)>> { - model::run(model, inputs).map_err(|e| rustler::Error::Term(Box::new(e.to_string()))) -} - -#[rustler::nif(schedule = "DirtyCpu")] -fn from_binary(bin: Binary, shape: Term, dtype: Term) -> NifResult> { - let shape: Vec = rustler::types::tuple::get_tuple(shape)? - .iter() - .map(|x| -> NifResult { Ok(x.decode::())? }) - .collect::>>()?; - let (dtype_t, dtype_bits): (Term, usize) = dtype.decode()?; - let dtype_str = dtype_t.atom_to_string()?; - - utils::from_binary(bin, shape, dtype_str, dtype_bits) - .map_err(|e| rustler::Error::Term(Box::new(e.to_string()))) -} - -#[rustler::nif(schedule = "DirtyCpu")] -fn to_binary<'a>( - env: Env<'a>, - reference: ResourceArc, - bits: usize, - limit: usize, -) -> NifResult> { - utils::to_binary(env, reference, bits, limit) -} - -#[rustler::nif] -pub fn slice<'a>( - tensor: ResourceArc, - start_indicies: Vec, - lengths: Vec, - strides: Vec, -) -> NifResult> { - Ok(ResourceArc::new(tensor.slice( - start_indicies, - lengths, - strides, - ))) -} - -#[rustler::nif] -pub fn reshape<'a>( - tensor: ResourceArc, - shape: Vec, -) -> NifResult> { - Ok(ResourceArc::new(tensor.reshape(shape)?)) -} - -#[rustler::nif] -pub fn concatenate<'a>( - tensors: Vec>, - dtype: Term, - axis: i32, -) -> NifResult> { - let (dtype_t, dtype_bits): (Term, usize) = dtype.decode()?; - let dtype_str = dtype_t.atom_to_string()?; - let concatted = tensor::concatenate(tensors, (&dtype_str, dtype_bits), axis as usize); - Ok(ResourceArc::new(concatted)) -} - -rustler::init!( - "Elixir.Ortex.Native", - [ - run, - init, - from_binary, - to_binary, - show_session, - slice, - reshape, - concatenate - ], - load = |env: Env, _| { - rustler::resource!(OrtexModel, env); - rustler::resource!(OrtexTensor, env); - true - } -); +//! # Ortex +//! Rust bindings between [ONNX Runtime](https://github.com/microsoft/onnxruntime) and +//! Erlang/Elixir using [Ort](https://docs.rs/ort) and [Rustler](https://docs.rs/rustler). +//! These are only meant to be accessed via the NIF interface provided by Rustler and not +//! directly. + +mod constants; +mod image; +mod model; +mod tensor; +mod utils; + +use model::OrtexModel; +use tensor::OrtexTensor; + +use rustler::types::Binary; +use rustler::ResourceArc; +use rustler::{Atom, Env, NifResult, Term}; + +#[rustler::nif(schedule = "DirtyIo")] +fn init( + env: Env, + model_path: String, + eps: Vec, + opt: i32, +) -> NifResult> { + let eps = utils::map_eps(env, eps); + let model = model::init(model_path, eps, opt) + .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?; + Ok(ResourceArc::new(model)) +} + +#[rustler::nif] +fn show_session( + model: ResourceArc, +) -> NifResult<( + Vec<(String, String, Option>)>, + Vec<(String, String, Option>)>, +)> { + Ok(model::show(model)) +} + +#[rustler::nif(schedule = "DirtyIo")] +fn run( + model: ResourceArc, + inputs: Vec>, +) -> NifResult, Vec, Atom, usize)>> { + model::run(model, inputs).map_err(|e| rustler::Error::Term(Box::new(e.to_string()))) +} + +#[rustler::nif(schedule = "DirtyCpu")] +fn from_binary(bin: Binary, shape: Term, dtype: Term) -> NifResult> { + let shape: Vec = rustler::types::tuple::get_tuple(shape)? + .iter() + .map(|x| -> NifResult { Ok(x.decode::())? }) + .collect::>>()?; + let (dtype_t, dtype_bits): (Term, usize) = dtype.decode()?; + let dtype_str = dtype_t.atom_to_string()?; + + utils::from_binary(bin, shape, dtype_str, dtype_bits) + .map_err(|e| rustler::Error::Term(Box::new(e.to_string()))) +} + +#[rustler::nif(schedule = "DirtyCpu")] +fn to_binary<'a>( + env: Env<'a>, + reference: ResourceArc, + bits: usize, + limit: usize, +) -> NifResult> { + utils::to_binary(env, reference, bits, limit) +} + +#[rustler::nif] +pub fn slice<'a>( + tensor: ResourceArc, + start_indicies: Vec, + lengths: Vec, + strides: Vec, +) -> NifResult> { + Ok(ResourceArc::new(tensor.slice( + start_indicies, + lengths, + strides, + ))) +} + +#[rustler::nif] +pub fn reshape<'a>( + tensor: ResourceArc, + shape: Vec, +) -> NifResult> { + Ok(ResourceArc::new(tensor.reshape(shape)?)) +} + +#[rustler::nif] +pub fn prepare_image<'a>( + env: Env<'a>, + bin: Binary, + width: u32, + height: u32, + size: u32, +) -> NifResult> { + image::prepare_image(env, bin, width, height, size) +} + +#[rustler::nif] +pub fn create_mask<'a>( + env: Env<'a>, + coefficients: Vec, + prototypes_bin: rustler::Binary, + proto_shape_term: Term<'a>, // Elixir tuple {batch, m, h, w} -> Vec + threshold: f32, +) -> Result, rustler::Error> { + model::create_mask( + env, + coefficients, + prototypes_bin, + proto_shape_term, + threshold, + ) +} + +#[rustler::nif] +pub fn concatenate<'a>( + tensors: Vec>, + dtype: Term, + axis: i32, +) -> NifResult> { + let (dtype_t, dtype_bits): (Term, usize) = dtype.decode()?; + let dtype_str = dtype_t.atom_to_string()?; + let concatted = tensor::concatenate(tensors, (&dtype_str, dtype_bits), axis as usize); + Ok(ResourceArc::new(concatted)) +} + +pub fn on_load(env: Env) -> bool { + tracing_subscriber::fmt::init(); + env.register::().is_ok() && env.register::().is_ok() +} + +rustler::init!( + "Elixir.Ortex.Native", + load = |env: Env, _term: Term| -> bool { on_load(env) } +); diff --git a/native/ortex/src/model.rs b/native/ortex/src/model.rs index f5e04b3..de6dcae 100644 --- a/native/ortex/src/model.rs +++ b/native/ortex/src/model.rs @@ -1,129 +1,214 @@ -//! Abstractions for creating an ONNX Runtime Session and Environment which can be safely -//! passed to and from the BEAM. -//! -//! # Examples -//! -//! ``` -//! let model = init("./models/resnet50.onnx", vec![])?; -//! let (inputs, outputs) = show(model)?; -//! ``` - -use crate::tensor::OrtexTensor; -use crate::utils::{is_bool_input, map_opt_level}; -use std::convert::TryInto; -use std::iter::zip; - -use ort::{Error, ExecutionProviderDispatch, Session}; -use rustler::resource::ResourceArc; -use rustler::Atom; - -/// Holds the model state which include onnxruntime session and environment. All -/// are threadsafe so this can be called concurrently from the beam. -pub struct OrtexModel { - pub session: ort::Session, -} - -// Since we're only using the session for inference and -// inference is threadsafe, this Sync is safe. Additionally, -// Environment is global and also threadsafe -// https://github.com/microsoft/onnxruntime/issues/114 -unsafe impl Sync for OrtexModel {} - -/// Creates a model given the path to the model and vector of execution providers. -/// The execution providers are Atoms from Erlang/Elixir. -pub fn init( - model_path: String, - eps: Vec, - opt: i32, -) -> Result { - // TODO: send tracing logs to erlang/elixir _somehow_ - // tracing_subscriber::fmt::init(); - - let session = Session::builder()? - .with_optimization_level(map_opt_level(opt))? - .with_execution_providers(eps)? - .commit_from_file(model_path)?; - - let state = OrtexModel { session }; - Ok(state) -} - -/// Returns input/output information about a model. The result is a Tuple of -/// `inputs` and `outputs` with elements of `(Name, Type, Dimension)` where -/// `Dimension` elements of -1 are dynamic. -pub fn show( - model: ResourceArc, -) -> ( - Vec<(String, String, Option>)>, - Vec<(String, String, Option>)>, -) { - let model: &OrtexModel = &*model; - - let mut inputs = Vec::new(); - for input in model.session.inputs.iter() { - let name = input.name.to_string(); - let repr = format!("{:#?}", input.input_type); - let dims = Option::<&Vec>::cloned(input.input_type.tensor_dimensions()); - inputs.push((name, repr, dims)); - } - - let mut outputs = Vec::new(); - for output in model.session.outputs.iter() { - let name = output.name.to_string(); - let repr = format!("{:#?}", output.output_type); - let dims = Option::<&Vec>::cloned(output.output_type.tensor_dimensions()); - outputs.push((name, repr, dims)); - } - - (inputs, outputs) -} - -/// Runs the model with the given inputs. Returns a vector of tensors. Use `model::show` -/// to see what the model expects for input and output shapes. -pub fn run( - model: ResourceArc, - inputs: Vec>, -) -> Result, Vec, Atom, usize)>, Error> { - // Grab the session and run a forward pass with it - let session: &ort::Session = &model.session; - - let mut ortified_inputs: Vec = Vec::new(); - - for (elixir_input, onnx_input) in zip(inputs, &session.inputs) { - let derefed_input: &OrtexTensor = &elixir_input; - if is_bool_input(&onnx_input.input_type) { - // this assumes that the boolean input isn't huge -- we're cloning it twice; - // once below, once in the try_into() - let boolified_input: &OrtexTensor = &derefed_input.clone().to_bool(); - let v: ort::SessionInputValue = boolified_input.try_into()?; - ortified_inputs.push(v); - } else { - let v: ort::SessionInputValue = derefed_input.try_into()?; - ortified_inputs.push(v); - } - } - - // Construct a Vec of ModelOutput enums based on the DynOrtTensor data type - let outputs = session.run(&ortified_inputs[..])?; - let mut collected_outputs = Vec::new(); - - for output_descriptor in &session.outputs { - let output_name: &str = &output_descriptor.name; - let val = outputs.get(output_name).expect( - &format!( - "Expected {} to be in the outputs, but didn't find it", - output_name - )[..], - ); - - // NOTE: try_into impl here will implicitly map bool outputs to u8 outputs - let ortextensor: OrtexTensor = val.try_into()?; - let shape = ortextensor.shape(); - let (dtype, bits) = ortextensor.dtype(); - - let collected_output = (ResourceArc::new(ortextensor), shape, dtype, bits); - collected_outputs.push(collected_output) - } - - Ok(collected_outputs) -} +//! Abstractions for creating an ONNX Runtime Session and Environment which can be safely +//! passed to and from the BEAM. +//! +//! # Examples +//! +//! ``` +//! let model = init("./models/resnet50.onnx", vec![])?; +//! let (inputs, outputs) = show(model)?; +//! ``` + +use crate::tensor::OrtexTensor; +use crate::utils::{is_bool_input, map_opt_level}; +use ndarray::{s, Array2, ArrayView3}; +use std::convert::TryInto; +use std::iter::zip; + +use ort::execution_providers::ExecutionProviderDispatch; +use ort::session::Session; +use ort::Error; +use rustler::Atom; +use rustler::Env; +use rustler::NewBinary; +use rustler::Resource; +use rustler::ResourceArc; +use rustler::Term; +use std::error::Error as StdError; +use std::sync::Mutex; + +/// Holds the model state which include onnxruntime session and environment. All +/// are threadsafe so this can be called concurrently from the beam. +pub struct OrtexModel { + pub session: Mutex, +} +impl Resource for OrtexModel {} + +// Since we're only using the session for inference and +// inference is threadsafe, this Sync is safe. Additionally, +// Environment is global and also threadsafe +// https://github.com/microsoft/onnxruntime/issues/114 +unsafe impl Sync for OrtexModel {} + +/// Creates a model given the path to the model and vector of execution providers. +/// The execution providers are Atoms from Erlang/Elixir. +pub fn init( + model_path: String, + eps: Vec, + opt: i32, +) -> Result { + // TODO: send tracing logs to erlang/elixir _somehow_ + //tracing_subscriber::fmt::init(); + + let session = Session::builder()? + .with_optimization_level(map_opt_level(opt))? + .with_execution_providers(eps)? + .commit_from_file(model_path)?; + + let state = OrtexModel { + session: session.into(), + }; + Ok(state) +} + +/// Returns input/output information about a model. The result is a Tuple of +/// `inputs` and `outputs` with elements of `(Name, Type, Dimension)` where +/// `Dimension` elements of -1 are dynamic. +pub fn show( + model: ResourceArc, +) -> ( + Vec<(String, String, Option>)>, + Vec<(String, String, Option>)>, +) { + let session: &mut ort::session::Session = &mut model.session.lock().unwrap(); + + let mut inputs = Vec::new(); + for input in session.inputs.iter() { + let name = input.name.to_string(); + let repr = format!("{:#?}", input.input_type); + let dims: Option> = input.input_type.tensor_shape().map(|s| s.to_vec()); + inputs.push((name, repr, dims)); + } + + let mut outputs = Vec::new(); + for output in session.outputs.iter() { + let name = output.name.to_string(); + let repr = format!("{:#?}", output.output_type); + let dims: Option> = output.output_type.tensor_shape().map(|s| s.to_vec()); + outputs.push((name, repr, dims)); + } + + (inputs, outputs) +} + +/// Runs the model with the given inputs. Returns a vector of tensors. Use `model::show` +/// to see what the model expects for input and output shapes. +pub fn run( + model: ResourceArc, + inputs: Vec>, +) -> Result, Vec, Atom, usize)>, Box> { + let session: &mut ort::session::Session = &mut model.session.lock().unwrap(); + + let mut ortified_inputs: Vec = Vec::new(); + + for (elixir_input, onnx_input) in zip(inputs, &session.inputs) { + let derefed_input: &OrtexTensor = &elixir_input; + if is_bool_input(&onnx_input.input_type) { + let boolified_input: &OrtexTensor = &derefed_input.clone().to_bool(); + let v: ort::session::SessionInputValue = boolified_input.try_into()?; + ortified_inputs.push(v); + } else { + let v: ort::session::SessionInputValue = derefed_input.try_into()?; + ortified_inputs.push(v); + } + } + + let outputs = session.run(&ortified_inputs[..])?; + let mut collected_outputs = Vec::new(); + + for output_name in outputs.keys() { + let val = outputs.get(output_name).expect( + &format!( + "Expected {} to be in the outputs, but didn't find it", + output_name + )[..], + ); + + let ortextensor: OrtexTensor = val.try_into()?; + let shape = ortextensor.shape(); + let (dtype, bits) = ortextensor.dtype(); + let collected_output = (ResourceArc::new(ortextensor), shape, dtype, bits); + collected_outputs.push(collected_output); + } + + Ok(collected_outputs) +} + +pub fn create_mask<'a>( + env: Env<'a>, + coefficients: Vec, + prototypes_bin: rustler::Binary, + proto_shape_term: Term<'a>, // Elixir tuple {batch, m, h, w} -> Vec + threshold: f32, +) -> Result, rustler::Error> { + // Decode as 4-element tuple directly + let (batch_size, m, height, width): (usize, usize, usize, usize) = + proto_shape_term.decode().map_err(|e| { + println!("Failed to decode tuple: {:?}", e); + rustler::Error::BadArg + })?; + + // Validate 4D + let expected_proto_size = batch_size * m * height * width; + let f32_size = std::mem::size_of::(); + + // Validate coefficients + if coefficients.len() != m { + println!( + "Invalid coefficients length: {}, expected: {}", + coefficients.len(), + m + ); + return Err(rustler::Error::BadArg); + } + + // Validate prototypes binary + let protos_bytes = prototypes_bin.as_slice(); + if protos_bytes.len() != expected_proto_size * f32_size { + println!( + "Invalid prototypes binary size: {}, expected: {}", + protos_bytes.len(), + expected_proto_size * f32_size + ); + return Err(rustler::Error::BadArg); + } + let protos_slice: &[f32] = unsafe { + std::slice::from_raw_parts(protos_bytes.as_ptr() as *const f32, expected_proto_size) + }; + + // Assume single batch + if batch_size != 1 { + println!("Batch size not 1: {}", batch_size); + return Err(rustler::Error::BadArg); + } + + // Reshape to 3D view + let proto_3d = + ArrayView3::::from_shape((m, height, width), protos_slice).map_err(|e| { + println!("ArrayView3 error: {:?}", e); + rustler::Error::BadArg + })?; + + // Weighted sum + let mut output = Array2::::zeros((height, width)); + for i in 0..m { + let proto_slice = proto_3d.slice(s![i, .., ..]); + let weighted = proto_slice.mapv(|x| x * coefficients[i]); + output += &weighted; + } + + // Sigmoid and threshold + let sigmoid = output.mapv(|x| 1.0 / (1.0 + (-x).exp())); + let binary = sigmoid.mapv(|x| if x >= threshold { 255u8 } else { 0u8 }); + let binary_vec = binary + .to_shape(height * width) + .map_err(|e| { + println!("Flatten error: {:?}", e); + rustler::Error::BadArg + })? + .to_vec(); + + // Return binary + let mut new_bin = NewBinary::new(env, binary_vec.len()); + new_bin.as_mut_slice().copy_from_slice(&binary_vec); + Ok(new_bin.into()) +} diff --git a/native/ortex/src/tensor.rs b/native/ortex/src/tensor.rs index d4aecf1..b7cba90 100644 --- a/native/ortex/src/tensor.rs +++ b/native/ortex/src/tensor.rs @@ -2,10 +2,12 @@ use core::convert::TryFrom; use ndarray::prelude::*; use ndarray::{ArrayBase, ArrayView, Data, IxDyn, IxDynImpl, ViewRepr}; -use ort::{DynValue, Error, Value}; -use rustler::resource::ResourceArc; +use ort::value::Value; +use ort::Error; use rustler::Atom; -use std::convert::TryInto; +use rustler::Resource; +use rustler::ResourceArc; +use std::error::Error as StdError; use crate::constants::ortex_atoms; @@ -203,6 +205,8 @@ impl OrtexTensor { } } +impl Resource for OrtexTensor {} + fn slice_array<'a, T, D>( array: &'a Array, slice_specs: &'a Vec<(isize, Option, isize)>, @@ -230,59 +234,156 @@ where impl TryFrom<&Value> for OrtexTensor { type Error = Error; fn try_from(e: &Value) -> Result { - let dtype: ort::ValueType = e.dtype(); + let dtype: ort::value::ValueType = e.dtype().clone(); let ty = match dtype { - ort::ValueType::Tensor { + ort::value::ValueType::Tensor { ty: t, - dimensions: _, + shape: _, + dimension_symbols: _, } => t, _ => panic!("can't decode non tensor, got {}", dtype), }; let tensor = match ty { - ort::TensorElementType::Bfloat16 => { - OrtexTensor::bf16(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Bfloat16 => { + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + let array = Array::from_shape_vec(shape, data.to_vec()) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::bf16(array) } - ort::TensorElementType::Float16 => { - OrtexTensor::f16(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Float16 => { + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + let array = Array::from_shape_vec(shape, data.to_vec()) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::f16(array) } - ort::TensorElementType::Float32 => { - OrtexTensor::f32(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Float32 => { + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + let array = Array::from_shape_vec(shape, data.to_vec()) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::f32(array) } - ort::TensorElementType::Float64 => { - OrtexTensor::f64(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Float64 => { + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + let array = Array::from_shape_vec(shape, data.to_vec()) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::f64(array) } - ort::TensorElementType::Uint8 => { - OrtexTensor::u8(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Uint8 => { + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + let array = Array::from_shape_vec(shape, data.to_vec()) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::Uint16 => { - OrtexTensor::u16(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Uint16 => { + //OrtexTensor::u8(<(&ort::tensor::Shape, &[u16])>::to_owned()) + + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + // Convert u16 data to u8 by truncating or clamping + let data_vec: Vec = data.iter().map(|&x| x.min(255) as u8).collect(); + let array = Array::from_shape_vec(shape, data_vec) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::Uint32 => { - OrtexTensor::u32(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Uint32 => { + //OrtexTensor::u8(<(&ort::tensor::Shape, &[u32])>::to_owned()) + + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + // Convert u16 data to u8 by truncating or clamping + let data_vec: Vec = data.iter().map(|&x| x.min(255) as u8).collect(); + let array = Array::from_shape_vec(shape, data_vec) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::Uint64 => { - OrtexTensor::u64(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Uint64 => { + //OrtexTensor::u8(<(&ort::tensor::Shape, &[u64])>::to_owned()) + + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + // Convert u16 data to u8 by truncating or clamping + let data_vec: Vec = data.iter().map(|&x| x.min(255) as u8).collect(); + let array = Array::from_shape_vec(shape, data_vec) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::Int8 => { - OrtexTensor::s8(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Int8 => { + //OrtexTensor::u8(<(&ort::tensor::Shape, &[i8])>::to_owned()) + + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + // Convert i8 data to u8 (e.g., shift range by adding 128) + let data_vec: Vec = data.iter().map(|&x| (x as i16 + 128) as u8).collect(); + let array = Array::from_shape_vec(shape, data_vec) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::Int16 => { - OrtexTensor::s16(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Int16 => { + //OrtexTensor::u8(<(&ort::tensor::Shape, &[u16])>::to_owned()) + + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + // Convert i8 data to u8 (e.g., shift range by adding 128) + let data_vec: Vec = data.iter().map(|&x| (x as i16 + 128) as u8).collect(); + let array = Array::from_shape_vec(shape, data_vec) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::Int32 => { - OrtexTensor::s32(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Int32 => { + //OrtexTensor::u8(<(&ort::tensor::Shape, &[i16])>::to_owned()) + + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + // Convert i8 data to u8 (e.g., shift range by adding 128) + let data_vec: Vec = data.iter().map(|&x| (x as i16 + 128) as u8).collect(); + let array = Array::from_shape_vec(shape, data_vec) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::Int64 => { - OrtexTensor::s64(e.try_extract_tensor::()?.into_owned()) + ort::tensor::TensorElementType::Int64 => { + //OrtexTensor::u8(<(&ort::tensor::Shape, &[i64])>::to_owned()) + + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + // Convert i8 data to u8 (e.g., shift range by adding 128) + let data_vec: Vec = data.iter().map(|&x| (x as i16 + 128) as u8).collect(); + let array = Array::from_shape_vec(shape, data_vec) + .map_err(|e| Error::from(Box::new(e) as Box))?; + OrtexTensor::u8(array) } - ort::TensorElementType::String => { + ort::tensor::TensorElementType::String => { todo!("Can't return string tensors") } // map the output into u8 space - ort::TensorElementType::Bool => { - let nd_array = e.try_extract_tensor::()?.into_owned(); - OrtexTensor::u8(nd_array.mapv(|x| x as u8)) + ort::tensor::TensorElementType::Bool => { + let (shape, data) = e.try_extract_tensor::()?; + let shape_vec: Vec = shape.iter().map(|&dim| dim as usize).collect(); + let shape = IxDyn(&shape_vec); + let bool_array = Array::from_shape_vec(shape, data.to_vec()) + .map_err(|e| Error::from(Box::new(e) as Box))?; + let u8_array = bool_array.mapv(|x| x as u8); + OrtexTensor::u8(u8_array) + } + _ => { + todo!("Complex types") } }; @@ -290,25 +391,25 @@ impl TryFrom<&Value> for OrtexTensor { } } -impl TryFrom<&OrtexTensor> for ort::SessionInputValue<'_> { +impl TryFrom<&OrtexTensor> for ort::session::SessionInputValue<'_> { type Error = Error; fn try_from(ort_tensor: &OrtexTensor) -> Result { - let r: DynValue = match ort_tensor { - OrtexTensor::s8(arr) => arr.to_owned().try_into()?, - OrtexTensor::s16(arr) => arr.clone().try_into()?, - OrtexTensor::s32(arr) => arr.clone().try_into()?, - OrtexTensor::s64(arr) => arr.clone().try_into()?, - OrtexTensor::f16(arr) => arr.clone().try_into()?, - OrtexTensor::f32(arr) => arr.clone().try_into()?, - OrtexTensor::f64(arr) => arr.clone().try_into()?, - OrtexTensor::bf16(arr) => arr.clone().try_into()?, - OrtexTensor::u8(arr) => arr.clone().try_into()?, - OrtexTensor::u16(arr) => arr.clone().try_into()?, - OrtexTensor::u32(arr) => arr.clone().try_into()?, - OrtexTensor::u64(arr) => arr.clone().try_into()?, - OrtexTensor::bool(arr) => arr.clone().try_into()?, + let value: Value = match ort_tensor { + OrtexTensor::s8(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::s16(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::s32(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::s64(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::f16(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::f32(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::f64(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::bf16(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::u8(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::u16(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::u32(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::u64(arr) => Value::from_array(arr.to_owned())?.into(), + OrtexTensor::bool(arr) => Value::from_array(arr.to_owned())?.into(), }; - Ok(r.into()) + Ok(ort::session::SessionInputValue::from(value)) } } @@ -343,7 +444,7 @@ macro_rules! concatenate { // `typ` is the actual datatype, `ort_tensor_kind` is the OrtexTensor variant ($tensors:expr, $axis:expr, $typ:ty, $ort_tensor_kind:ident) => {{ type ArrayType<'a> = ArrayBase, Dim>; - fn filter(tensor: &OrtexTensor) -> Option { + fn filter(tensor: &OrtexTensor) -> Option> { match tensor { OrtexTensor::$ort_tensor_kind(x) => Some(x.view()), _ => None, diff --git a/native/ortex/src/utils.rs b/native/ortex/src/utils.rs index 8d96117..c312b3e 100644 --- a/native/ortex/src/utils.rs +++ b/native/ortex/src/utils.rs @@ -1,127 +1,134 @@ -//! Serialization and deserialization to transfer between Ortex and BinaryBackend -//! [Nx](https://hexdocs.pm/nx) backend. - -use crate::constants::*; -use crate::tensor::OrtexTensor; -use ndarray::{ArrayViewMut, Ix, IxDyn}; - -use ndarray::ShapeError; - -use rustler::resource::ResourceArc; -use rustler::types::Binary; -use rustler::{Atom, Env, NifResult}; - -use ort::{ExecutionProviderDispatch, GraphOptimizationLevel}; - -/// A faster (unsafe) way of creating an Array from an Erlang binary -fn initialize_from_raw_ptr(ptr: *const T, shape: &[Ix]) -> ArrayViewMut { - let array = unsafe { ArrayViewMut::from_shape_ptr(shape, ptr as *mut T) }; - array -} - -/// Given a Binary term, shape, and dtype from the BEAM, constructs an OrtexTensor and -/// returns the reference to be used as an Nx.Backend representation. -/// -/// # Example -/// -/// ```elixir -/// bin = <<1, 0, 0, 0, 1, 0, 0, 0>> -/// ``` -/// -/// Create a shape `[2]` u32 OrtexTensor from a binary of 8 bytes -/// ```elixir -/// {:ok, reference} = from_binary(bin, {2}, {:u, 32}) -/// ``` -pub fn from_binary( - bin: Binary, - shape: Vec, - dtype_str: String, - dtype_bits: usize, -) -> Result, ShapeError> { - match (dtype_str.as_ref(), dtype_bits) { - ("bf", 16) => Ok(ResourceArc::new(OrtexTensor::bf16( - initialize_from_raw_ptr(bin.as_ptr() as *const half::bf16, &shape).to_owned(), - ))), - ("f", 16) => Ok(ResourceArc::new(OrtexTensor::f16( - initialize_from_raw_ptr(bin.as_ptr() as *const half::f16, &shape).to_owned(), - ))), - ("f", 32) => Ok(ResourceArc::new(OrtexTensor::f32( - initialize_from_raw_ptr(bin.as_ptr() as *const f32, &shape).to_owned(), - ))), - ("f", 64) => Ok(ResourceArc::new(OrtexTensor::f64( - initialize_from_raw_ptr(bin.as_ptr() as *const f64, &shape).to_owned(), - ))), - ("s", 8) => Ok(ResourceArc::new(OrtexTensor::s8( - initialize_from_raw_ptr(bin.as_ptr() as *const i8, &shape).to_owned(), - ))), - ("s", 16) => Ok(ResourceArc::new(OrtexTensor::s16( - initialize_from_raw_ptr(bin.as_ptr() as *const i16, &shape).to_owned(), - ))), - ("s", 32) => Ok(ResourceArc::new(OrtexTensor::s32( - initialize_from_raw_ptr(bin.as_ptr() as *const i32, &shape).to_owned(), - ))), - ("s", 64) => Ok(ResourceArc::new(OrtexTensor::s64( - initialize_from_raw_ptr(bin.as_ptr() as *const i64, &shape).to_owned(), - ))), - ("u", 8) => Ok(ResourceArc::new(OrtexTensor::u8( - initialize_from_raw_ptr(bin.as_ptr() as *const u8, &shape).to_owned(), - ))), - ("u", 16) => Ok(ResourceArc::new(OrtexTensor::u16( - initialize_from_raw_ptr(bin.as_ptr() as *const u16, &shape).to_owned(), - ))), - ("u", 32) => Ok(ResourceArc::new(OrtexTensor::u32( - initialize_from_raw_ptr(bin.as_ptr() as *const u32, &shape).to_owned(), - ))), - ("u", 64) => Ok(ResourceArc::new(OrtexTensor::u64( - initialize_from_raw_ptr(bin.as_ptr() as *const u64, &shape).to_owned(), - ))), - (&_, _) => unimplemented!(), - } -} - -/// Given a reference to an OrtexTensor return the binary representation to be used -/// by the BinaryBackend of Nx. -pub fn to_binary<'a>( - env: Env<'a>, - reference: ResourceArc, - _bits: usize, - _limit: usize, -) -> NifResult> { - Ok(reference.make_binary(env, |x| x.to_bytes())) -} - -/// Takes a vec of Atoms and transforms them into a vec of ExecutionProvider Enums -pub fn map_eps(env: rustler::env::Env, eps: Vec) -> Vec { - eps.iter() - .map(|e| match &e.to_term(env).atom_to_string().unwrap()[..] { - CPU => ort::CPUExecutionProvider::default().build(), - CUDA => ort::CUDAExecutionProvider::default().build(), - TENSORRT => ort::TensorRTExecutionProvider::default().build(), - ACL => ort::ACLExecutionProvider::default().build(), - ONEDNN => ort::OneDNNExecutionProvider::default().build(), - COREML => ort::CoreMLExecutionProvider::default().build(), - DIRECTML => ort::DirectMLExecutionProvider::default().build(), - ROCM => ort::ROCmExecutionProvider::default().build(), - _ => ort::CPUExecutionProvider::default().build(), - }) - .collect() -} - -/// Take an optimization level and returns the -pub fn map_opt_level(opt: i32) -> GraphOptimizationLevel { - match opt { - 1 => GraphOptimizationLevel::Level1, - 2 => GraphOptimizationLevel::Level2, - 3 => GraphOptimizationLevel::Level3, - _ => GraphOptimizationLevel::Disable, - } -} - -pub fn is_bool_input(inp: &ort::ValueType) -> bool { - match inp { - ort::ValueType::Tensor { ty, .. } => ty == &ort::TensorElementType::Bool, - ort::ValueType::Map { value, .. } => value == &ort::TensorElementType::Bool, - ort::ValueType::Sequence(boxed_input) => is_bool_input(boxed_input), - ort::ValueType::Optional(boxed_input) => is_bool_input(boxed_input), - } -} +//! Serialization and deserialization to transfer between Ortex and BinaryBackend +//! [Nx](https://hexdocs.pm/nx) backend. + +use crate::constants::*; +use crate::tensor::OrtexTensor; +use ndarray::{ArrayViewMut, Ix, IxDyn}; + +use ndarray::ShapeError; + +use rustler::types::Binary; +use rustler::ResourceArc; +use rustler::{Atom, Env, NifResult}; + +use ort::execution_providers::ExecutionProviderDispatch; +use ort::session::builder::GraphOptimizationLevel; + +/// A faster (unsafe) way of creating an Array from an Erlang binary +fn initialize_from_raw_ptr(ptr: *const T, shape: &[Ix]) -> ArrayViewMut<'_, T, IxDyn> { + let array = unsafe { ArrayViewMut::from_shape_ptr(shape, ptr as *mut T) }; + array +} + +/// Given a Binary term, shape, and dtype from the BEAM, constructs an OrtexTensor and +/// returns the reference to be used as an Nx.Backend representation. +/// +/// # Example +/// +/// ```elixir +/// bin = <<1, 0, 0, 0, 1, 0, 0, 0>> +/// ``` +/// +/// Create a shape `[2]` u32 OrtexTensor from a binary of 8 bytes +/// ```elixir +/// {:ok, reference} = from_binary(bin, {2}, {:u, 32}) +/// ``` +pub fn from_binary( + bin: Binary, + shape: Vec, + dtype_str: String, + dtype_bits: usize, +) -> Result, ShapeError> { + match (dtype_str.as_ref(), dtype_bits) { + ("bf", 16) => Ok(ResourceArc::new(OrtexTensor::bf16( + initialize_from_raw_ptr(bin.as_ptr() as *const half::bf16, &shape).to_owned(), + ))), + ("f", 16) => Ok(ResourceArc::new(OrtexTensor::f16( + initialize_from_raw_ptr(bin.as_ptr() as *const half::f16, &shape).to_owned(), + ))), + ("f", 32) => Ok(ResourceArc::new(OrtexTensor::f32( + initialize_from_raw_ptr(bin.as_ptr() as *const f32, &shape).to_owned(), + ))), + ("f", 64) => Ok(ResourceArc::new(OrtexTensor::f64( + initialize_from_raw_ptr(bin.as_ptr() as *const f64, &shape).to_owned(), + ))), + ("s", 8) => Ok(ResourceArc::new(OrtexTensor::s8( + initialize_from_raw_ptr(bin.as_ptr() as *const i8, &shape).to_owned(), + ))), + ("s", 16) => Ok(ResourceArc::new(OrtexTensor::s16( + initialize_from_raw_ptr(bin.as_ptr() as *const i16, &shape).to_owned(), + ))), + ("s", 32) => Ok(ResourceArc::new(OrtexTensor::s32( + initialize_from_raw_ptr(bin.as_ptr() as *const i32, &shape).to_owned(), + ))), + ("s", 64) => Ok(ResourceArc::new(OrtexTensor::s64( + initialize_from_raw_ptr(bin.as_ptr() as *const i64, &shape).to_owned(), + ))), + ("u", 8) => Ok(ResourceArc::new(OrtexTensor::u8( + initialize_from_raw_ptr(bin.as_ptr() as *const u8, &shape).to_owned(), + ))), + ("u", 16) => Ok(ResourceArc::new(OrtexTensor::u16( + initialize_from_raw_ptr(bin.as_ptr() as *const u16, &shape).to_owned(), + ))), + ("u", 32) => Ok(ResourceArc::new(OrtexTensor::u32( + initialize_from_raw_ptr(bin.as_ptr() as *const u32, &shape).to_owned(), + ))), + ("u", 64) => Ok(ResourceArc::new(OrtexTensor::u64( + initialize_from_raw_ptr(bin.as_ptr() as *const u64, &shape).to_owned(), + ))), + (&_, _) => unimplemented!(), + } +} + +/// Given a reference to an OrtexTensor return the binary representation to be used +/// by the BinaryBackend of Nx. +pub fn to_binary<'a>( + env: Env<'a>, + reference: ResourceArc, + _bits: usize, + _limit: usize, +) -> NifResult> { + Ok(reference.make_binary(env, |x| x.to_bytes())) +} + +/// Takes a vec of Atoms and transforms them into a vec of ExecutionProvider Enums +pub fn map_eps(env: rustler::env::Env, eps: Vec) -> Vec { + eps.iter() + .map(|e| match &e.to_term(env).atom_to_string().unwrap()[..] { + CPU => ort::execution_providers::cpu::CPUExecutionProvider::default().build(), + CUDA => ort::execution_providers::cuda::CUDAExecutionProvider::default() + .build() + .error_on_failure(), + TENSORRT => ort::execution_providers::tensorrt::TensorRTExecutionProvider::default() + .build() + .error_on_failure(), + ACL => ort::execution_providers::acl::ACLExecutionProvider::default().build(), + ONEDNN => ort::execution_providers::onednn::OneDNNExecutionProvider::default().build(), + COREML => ort::execution_providers::coreml::CoreMLExecutionProvider::default().build(), + DIRECTML => ort::execution_providers::directml::DirectMLExecutionProvider::default() + .build() + .error_on_failure(), + ROCM => ort::execution_providers::rocm::ROCmExecutionProvider::default().build(), + _ => ort::execution_providers::cpu::CPUExecutionProvider::default().build(), + }) + .collect() +} + +/// Take an optimization level and returns the +pub fn map_opt_level(opt: i32) -> GraphOptimizationLevel { + match opt { + 1 => GraphOptimizationLevel::Level1, + 2 => GraphOptimizationLevel::Level2, + 3 => GraphOptimizationLevel::Level3, + _ => GraphOptimizationLevel::Disable, + } +} + +pub fn is_bool_input(inp: &ort::value::ValueType) -> bool { + match inp { + ort::value::ValueType::Tensor { ty, .. } => ty == &ort::tensor::TensorElementType::Bool, + ort::value::ValueType::Map { value, .. } => value == &ort::tensor::TensorElementType::Bool, + ort::value::ValueType::Sequence(boxed_input) => is_bool_input(boxed_input), + ort::value::ValueType::Optional(boxed_input) => is_bool_input(boxed_input), + } +} diff --git a/test/test.exs b/test/test.exs new file mode 100644 index 0000000..c1c7658 --- /dev/null +++ b/test/test.exs @@ -0,0 +1,34 @@ +defmodule OrtexTest do + use ExUnit.Case + doctest Ortex + + test "resnet50" do + 0..500 + |> Enum.each(fn _ -> + run() + end) + end + + defp run() do + input = Nx.broadcast(0.0, {1, 3, 640, 640}) + # image = Evision.imread("C:/tmp/locator/Image01.jpg") + + # {:ok, scaled_image, scaler_config} = + # Ortex.Framework.YOLO.FrameScalers.fit( + # image, + # {640, 640}, + # Ortex.Framework.YOLO.FrameScalers.Evision + # ) + + # IO.inspect(Nx.shape(scaled_image)) + + model = + Ortex.load( + "C:/Development/Source/Maskon/Elixir/flux_app/project/models/vax_locator_11n_25_640.onnx" + ) + + _ = Ortex.run(model, input) + + Process.sleep(100) + end +end