mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-10 18:56:13 +00:00
Add stable hashed identity for speed dial actions
This commit is contained in:
36
src/slic3r/GUI/SpeedDialActionId.hpp
Normal file
36
src/slic3r/GUI/SpeedDialActionId.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
// Stable, opaque identity for a speed-dial action, used as the AppConfig key,
|
||||||
|
// the JS/registry handle, and the favourite_actions/stats key. FNV-1a 64-bit over
|
||||||
|
// the UTF-8 bytes of `plugin_key 0x1f capability`, lowercase 16-char hex.
|
||||||
|
//
|
||||||
|
// why: this is PERSISTED, so it must be deterministic across runs and platforms.
|
||||||
|
// std::hash<std::string> is explicitly NOT usable here (unspecified, per-process).
|
||||||
|
// note: 64-bit hash -> collision is astronomically unlikely at the tens-of-actions
|
||||||
|
// scale; upgrade path (128-bit / full-string key) only if that ever changes.
|
||||||
|
inline std::string speed_dial_action_id(const std::string& plugin_key, const std::string& capability)
|
||||||
|
{
|
||||||
|
constexpr std::uint64_t kOffset = 14695981039346656037ULL; // FNV offset basis (0xcbf29ce484222325)
|
||||||
|
constexpr std::uint64_t kPrime = 1099511628211ULL; // FNV prime
|
||||||
|
std::uint64_t h = kOffset;
|
||||||
|
// note: [&], not [&h] - MSVC rejects the constexpr kPrime read inside the lambda
|
||||||
|
// without a default capture mode (error C3493).
|
||||||
|
auto mix = [&](const std::string& s) {
|
||||||
|
for (unsigned char c : s) { h ^= c; h *= kPrime; }
|
||||||
|
};
|
||||||
|
mix(plugin_key);
|
||||||
|
h ^= 0x1f; h *= kPrime; // 0x1f (unit separator) between the two fields
|
||||||
|
mix(capability);
|
||||||
|
|
||||||
|
static const char* kHex = "0123456789abcdef";
|
||||||
|
std::string out(16, '0');
|
||||||
|
for (int i = 15; i >= 0; --i) { out[i] = kHex[h & 0xf]; h >>= 4; }
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
@@ -5,6 +5,7 @@ add_executable(${_TEST_NAME}_tests
|
|||||||
test_plugin_capability_identifier.cpp
|
test_plugin_capability_identifier.cpp
|
||||||
test_plugin_install.cpp
|
test_plugin_install.cpp
|
||||||
test_plugin_sort.cpp
|
test_plugin_sort.cpp
|
||||||
|
test_speed_dial_action_id.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
|||||||
28
tests/slic3rutils/test_speed_dial_action_id.cpp
Normal file
28
tests/slic3rutils/test_speed_dial_action_id.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
|
#include <slic3r/GUI/SpeedDialActionId.hpp>
|
||||||
|
|
||||||
|
using Slic3r::GUI::speed_dial_action_id;
|
||||||
|
|
||||||
|
TEST_CASE("speed_dial_action_id is deterministic and opaque", "[speeddial][id]") {
|
||||||
|
const std::string a = speed_dial_action_id("pack.py", "Do Thing");
|
||||||
|
const std::string b = speed_dial_action_id("pack.py", "Do Thing");
|
||||||
|
CHECK(a == b); // stable within a run
|
||||||
|
CHECK(a.size() == 16); // 64-bit -> 16 hex chars
|
||||||
|
CHECK(a.find_first_not_of("0123456789abcdef") == std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("speed_dial_action_id separates key and capability", "[speeddial][id]") {
|
||||||
|
// The 0x1f separator prevents (key+cap) run-together collisions:
|
||||||
|
// ("ab","c") must not equal ("a","bc").
|
||||||
|
CHECK(speed_dial_action_id("ab", "c") != speed_dial_action_id("a", "bc"));
|
||||||
|
CHECK(speed_dial_action_id("k", "one") != speed_dial_action_id("k", "two"));
|
||||||
|
CHECK(speed_dial_action_id("k1", "cap") != speed_dial_action_id("k2", "cap"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("speed_dial_action_id golden vector locks cross-run stability", "[speeddial][id]") {
|
||||||
|
// why: this value is PERSISTED as a config key; if the algorithm ever drifts,
|
||||||
|
// every saved favourite/stat silently orphans. Pin a known input->output.
|
||||||
|
// FNV-1a 64-bit of bytes: 'k','e','y',0x1f,'c','a','p'
|
||||||
|
CHECK(speed_dial_action_id("key", "cap") == "c54ad154fb2c9187");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user