Repository: unum-cloud/usearch (language: rust)

Issue:
Bug: Rust build failed on Windows PC
### Describe the bug

My PC with i5-10500 CPU, does not compile properly with rust bindings (using default features).

[This pull](https://github.com/unum-cloud/usearch/pull/472) may solve some problems.

[build.log](https://github.com/user-attachments/files/16781406/build.log)


### Steps to reproduce

Add package and build

### Expected behavior

Build success

### USearch version

2.15.0

### Operating System

Windows 10

### Hardware architecture

x86

### Which interface are you using?

Other bindings

### Contact Details

_No response_

### Are you open to being tagged as a contributor?

- [X] I am open to being mentioned in the project `.git` history as a contributor

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion / hints:

Fix patch:
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3b5d8520..56e46896 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -153,6 +153,7 @@
     "HNSW",
     "hnswlib",
     "ibin",
+    "ivdep",
     "jaccard",
     "Jemalloc",
     "Kullback",
@@ -175,6 +176,7 @@
     "Println",
     "pytest",
     "Quickstart",
+    "relock",
     "repr",
     "rtype",
     "SIMD",
diff --git a/build.rs b/build.rs
index 0a1c96f3..7007508e 100644
--- a/build.rs
+++ b/build.rs
@@ -80,7 +80,13 @@ fn main() {
             .flag_if_supported("/std:c++17")
             .flag_if_supported("/O2")
             .flag_if_supported("/fp:fast")
-            .flag_if_supported("/W1"); // Reduce warnings verbosity
+            .flag_if_supported("/W1") // Reduce warnings verbosity
+            .flag_if_supported("/EHsc")
+            .flag_if_supported("/MD")
+            .flag_if_supported("/permissive-")
+            .flag_if_supported("/sdl-")
+            .define("_ALLOW_RUNTIME_LIBRARY_MISMATCH", None)
+            .define("_ALLOW_POINTER_TO_CONST_MISMATCH", None);
     }
 
     let mut result = build.try_compile("usearch");
diff --git a/include/usearch/index_plugins.hpp b/include/usearch/index_plugins.hpp
index c7c75d95..c41afbce 100644
--- a/include/usearch/index_plugins.hpp
+++ b/include/usearch/index_plugins.hpp
@@ -139,6 +139,9 @@ enum class scalar_kind_t : std::uint8_t {
     i8_k = 23,
 };
 
+/**
+ *  @brief  Maps a scalar type to its corresponding scalar_kind_t enumeration value.
+ */
 template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
     if (std::is_same<scalar_at, b1x8_t>())
         return scalar_kind_t::b1x8_k;
@@ -175,22 +178,43 @@ template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
     return scalar_kind_t::unknown_k;
 }
 
+/**
+ *  @brief  Converts an angle from degrees to radians.
+ */
 template <typename at> at angle_to_radians(at angle) noexcept { return angle * at(3.14159265358979323846) / at(180); }
 
+/**
+ *  @brief  Readability helper to compute the square of a given value.
+ */
 template <typename at> at square(at value) noexcept { return value * value; }
 
+/**
+ *  @brief  Clamps a value between a lower and upper bound using a custom comparator. Similar to `std::clamp`.
+ *          https://en.cppreference.com/w/cpp/algorithm/clamp
+ */
 template <typename at, typename compare_at> inline at clamp(at v, at lo, at hi, compare_at comp) noexcept {
     return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
 }
+
+/**
+ *  @brief  Clamps a value between a lower and upper bound. Similar to `std::clamp`.
+ *          https://en.cppreference.com/w/cpp/algorithm/clamp
+ */
 template <typename at> inline at clamp(at v, at lo, at hi) noexcept {
     return usearch::clamp(v, lo, hi, std::less<at>{});
 }
 
-inline bool str_equals(char const* begin, std::size_t len, char const* other_begin) noexcept {
-    std::size_t other_len = std::strlen(other_begin);
-    return len == other_len && std::strncmp(begin, other_begin, len) == 0;
+/**
+ *  @brief  Compares two strings for equality, given a length for the first string.
+ */
+inline bool str_equals(char const* first_begin, std::size_t first_len, char const* second_begin) noexcept {
+    std::size_t second_len = std::strlen(second_begin);
+    return first_len == second_len && std::strncmp(first_begin, second_begin, first_len) == 0;
 }
 
+/**
+ *  @brief  Returns the number of bits required to represent a scalar type.
+ */
 inline std::size_t bits_per_scalar(scalar_kind_t scalar_kind) noexcept {
     switch (scalar_kind) {
     case scalar_kind_t::uuid_k: return 128;
@@ -213,6 +237,10 @@ inline std::size_t bits_per_scalar(scalar_kind_t scalar_kind) noexcept {
     }
 }
 
+/**
+ *  @brief  Returns the number of bits in a scalar word for a given scalar type.
+ *          Equivalent to `bits_per_scalar` for types that are not bit-packed.
+ */
 inline std::size_t bits_per_scalar_word(scalar_kind_t scalar_kind) noexcept {
     switch (scalar_kind) {
     case scalar_kind_t::uuid_k: return 128;
@@ -235,6 +263,9 @@ inline std::size_t bits_per_scalar_word(scalar_kind_t scalar_kind) noexcept {
     }
 }
 
+/**
+ *  @brief  Returns the string name of a given scalar type.
+ */
 inline char const* scalar_kind_name(scalar_kind_t scalar_kind) noexcept {
     switch (scalar_kind) {
     case scalar_kind_t::uuid_k: return "uuid";
@@ -257,6 +288,9 @@ inline char const* scalar_kind_name(scalar_kind_t scalar_kind) noexcept {
     }
 }
 
+/**
+ *  @brief  Returns the string name of a given distance metric.
+ */
 inline char const* metric_kind_name(metric_kind_t metric) noexcept {
     switch (metric) {
     case metric_kind_t::unknown_k: return "unknown";
@@ -273,6 +307,10 @@ inline char const* metric_kind_name(metric_kind_t metric) noexcept {
     default: return "";
     }
 }
+
+/**
+ *  @brief  Parses a string to identify the corresponding `scalar_kind_t` enumeration value.
+ */
 inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::size_t len) {
     expected_gt<scalar_kind_t> parsed;
     if (str_equals(name, len, "f32"))
@@ -292,10 +330,16 @@ inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::s
     return parsed;
 }
 
+/**
+ *  @brief  Parses a string to identify the corresponding `scalar_kind_t` enumeration value.
+ */
 inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name) {
     return scalar_kind_from_name(name, std::strlen(name));
 }
 
+/**
+ *  @brief  Parses a string to identify the corresponding `metric_kind_t` enumeration value.
+ */
 inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t len) {
     expected_gt<metric_kind_t> parsed;
     if (str_equals(name, len, "l2sq") || str_equals(name, len, "euclidean_sq")) {
@@ -321,6 +365,10 @@ inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t
                       "tanimoto, sorensen");
     return parsed;
 }
+
+/**
+ *  @brief  Parses a string to identify the corresponding `metric_kind_t` enumeration value.
+ */
 inline expected_gt<metric_kind_t> metric_from_name(char const* name) {
     return metric_from_name(name, std::strlen(name));
 }
@@ -417,7 +465,7 @@ class f16_bits_t {
     inline f16_bits_t(float v) noexcept : uint16_(f32_to_f16(v)) {}
     inline f16_bits_t(double v) noexcept : uint16_(f32_to_f16(static_cast<float>(v))) {}
 
-    inline bool operator<(const f16_bits_t& other) const noexcept { return float(*this) < float(other); }
+    inline bool operator<(f16_bits_t const& other) const noexcept { return float(*this) < float(other); }
 
     inline f16_bits_t operator+(f16_bits_t other) const noexcept { return {float(*this) + float(other)}; }
     inline f16_bits_t operator-(f16_bits_t other) const noexcept { return {float(*this) - float(other)}; }
@@ -1419,7 +1467,10 @@ template <typename scalar_at = float, typename result_at = float> struct metric_
     }
 };
 
-struct cos_i8_t {
+/**
+ *  @brief  Cosine (Angular) distance for signed 8-bit integers using 16-bit intermediates.
+ */
+struct metric_cos_i8_t {
     using scalar_t = i8_t;
     using result_t = f32_t;
 
@@ -1445,7 +1496,11 @@ struct cos_i8_t {
     }
 };
 
-struct l2sq_i8_t {
+/**
+ *  @brief  Squared Euclidean (L2) distance for signed 8-bit integers using 16-bit intermediates.
+ *          Square root is avoided at the end, as it won't affect the ordering.
+ */
+struct metric_l2sq_i8_t {
     using scalar_t = i8_t;
     using result_t = f32_t;
 
@@ -1775,7 +1830,7 @@ class metric_punned_t {
         case metric_kind_t::cos_k: {
             switch (scalar_kind_) {
             case scalar_kind_t::bf16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<bf16_t, f32_t>>; break;
-            case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<i8_t, f32_t>>; break;
+            case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_i8_t>; break;
             case scalar_kind_t::f16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f16_t, f32_t>>; break;
             case scalar_kind_t::f32_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f32_t>>; break;
             case scalar_kind_t::f64_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f64_t>>; break;
@@ -1786,7 +1841,7 @@ class metric_punned_t {
         case metric_kind_t::l2sq_k: {
             switch (scalar_kind_) {
             case scalar_kind_t::bf16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<bf16_t, f32_t>>; break;
-            case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<i8_t, f32_t>>; break;
+            case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_i8_t>; break;
             case scalar_kind_t::f16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f16_t, f32_t>>; break;
             case scalar_kind_t::f32_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f32_t>>; break;
             case scalar_kind_t::f64_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f64_t>>; break;
diff --git a/javascript/README.md b/javascript/README.md
index d02c3fd7..cb153a33 100644
--- a/javascript/README.md
+++ b/javascript/README.md
@@ -21,8 +21,9 @@ wasmer install unum/usearch
 Create an index, add vectors, and perform searches with ease:
 
 ```js
+const assert = require('node:assert');
 const usearch = require('usearch');
-const index = new usearch.Index({ metric: 'cos', connectivity: 16, dimensions: 3 });
+const index = new usearch.Index({ metric: 'l2sq', connectivity: 16, dimensions: 3 });
 index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
 const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
 
diff --git a/rust/lib.cpp b/rust/lib.cpp
index 87ee1d2c..9014decc 100644
--- a/rust/lib.cpp
+++ b/rust/lib.cpp
@@ -66,7 +66,7 @@ NativeIndex::NativeIndex(std::unique_ptr<index_t> index) : index_(std::move(inde
 auto make_predicate(uptr_t metric, uptr_t metric_state) {
     return [=](vector_key_t key) {
         auto func = reinterpret_cast<bool (*)(uptr_t, vector_key_t)>(metric);
-        auto state = reinterpret_cast<uptr_t>(metric_state);
+        auto state = static_cast<uptr_t>(metric_state);
         return func(key, state);
     };
 }
@@ -104,8 +104,8 @@ void NativeIndex::change_expansion_search(size_t n) const { index_->change_expan
 
 void NativeIndex::change_metric(uptr_t metric, uptr_t state) const {
     index_->change_metric(metric_punned_t::stateful( //
-        reinterpret_cast<std::uintptr_t>(metric),    //
-        reinterpret_cast<std::uintptr_t>(state),     //
+        static_cast<std::uintptr_t>(metric),         //
+        static_cast<std::uintptr_t>(state),          //
         index_->metric().metric_kind(),              //
         index_->scalar_kind()));
 }


Test patch:
diff --git a/javascript/usearch.test.js b/javascript/usearch.test.js
index d3673508..688a5847 100644
--- a/javascript/usearch.test.js
+++ b/javascript/usearch.test.js
@@ -47,13 +47,13 @@ test('Batch operations', () => {
 });
 
 test("Expected results", () => {
-    var index = new usearch.Index({
+    const index = new usearch.Index({
         metric: "l2sq",
         connectivity: 16,
         dimensions: 3,
     });
     index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
-    var results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
+    const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
 
     assert.equal(index.size(), 1);
     assert.deepEqual(results.keys, new BigUint64Array([42n]));