diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6a52d4f3..a22ec8d9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -9,7 +9,7 @@ on:
jobs:
cloudproof_rust:
- uses: Cosmian/reusable_workflows/.github/workflows/cloudproof.yml@develop
+ uses: Cosmian/reusable_workflows/.github/workflows/cloudproof.yml@fix/cloudproof
with:
project-name: cloudproof_rust
toolchain: stable
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2ef70883..4c1b895b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -4,12 +4,6 @@ name: CI checks
on: push
jobs:
- cargo-nursery-base:
- uses: Cosmian/reusable_workflows/.github/workflows/cargo-nursery-base.yml@develop
- with:
- toolchain: stable
- exclusions: --exclude=cloudproof_findex
-
cargo-doc:
uses: Cosmian/reusable_workflows/.github/workflows/cargo-doc.yml@develop
with:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 09dc6877..3bdc6981 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -122,13 +122,9 @@ repos:
rev: v1.0.24
hooks:
# - id: dprint-toml-fix
+ # - id: cargo-upgrade
+ # - id: cargo-update
- id: stable-cargo-format
- - id: cargo-upgrade
- - id: cargo-update
- - id: cargo-audit-deny-warnings
- - id: cargo-outdated
- - id: cargo-udeps
- args: [--exclude=cloudproof_findex]
- id: cargo-machete
- id: docker-compose-up
- id: cargo-tests-all
diff --git a/crates/aesgcm/src/lib.rs b/crates/aesgcm/src/lib.rs
index f9bc5240..138013d8 100644
--- a/crates/aesgcm/src/lib.rs
+++ b/crates/aesgcm/src/lib.rs
@@ -1,6 +1,6 @@
-/// The `cloudproof_rust` subcrate `aesgcm` brings the standard AES256 GCM
-/// implementation which has been audited by the NCC Group, with no significant
-/// findings. Refer to
+//! The `cloudproof_rust` subcrate `aesgcm` brings the standard AES256 GCM
+//! implementation which has been audited by the NCC Group, with no significant
+//! findings. Refer to
#[cfg(feature = "ffi")]
pub mod ffi;
diff --git a/crates/aesgcm/src/wasm_bindgen/mod.rs b/crates/aesgcm/src/wasm_bindgen/mod.rs
index 8620af54..747f57bb 100644
--- a/crates/aesgcm/src/wasm_bindgen/mod.rs
+++ b/crates/aesgcm/src/wasm_bindgen/mod.rs
@@ -1,4 +1,5 @@
mod aesgcm;
+#[allow(dead_code)]
#[cfg(test)]
mod tests;
diff --git a/crates/anonymization/Cargo.toml b/crates/anonymization/Cargo.toml
index 45ceb0e7..fb8d7962 100644
--- a/crates/anonymization/Cargo.toml
+++ b/crates/anonymization/Cargo.toml
@@ -21,6 +21,9 @@ wasm = ["js-sys", "wasm-bindgen"]
[package.metadata.cargo-udeps.ignore]
normal = ["js-sys", "wasm-bindgen"]
+[package.metadata.cargo-machete]
+ignored = ["tiny-keccak"]
+
[dependencies]
argon2 = "0.5"
base64 = { workspace = true }
diff --git a/crates/anonymization/src/core/number.rs b/crates/anonymization/src/core/number.rs
index 6a01c60a..b57887e0 100644
--- a/crates/anonymization/src/core/number.rs
+++ b/crates/anonymization/src/core/number.rs
@@ -94,7 +94,7 @@ impl DateAggregator {
///
/// * `time_unit`: The unit of time to round the date to.
#[must_use]
- pub fn new(time_unit: TimeUnit) -> Self {
+ pub const fn new(time_unit: TimeUnit) -> Self {
Self { time_unit }
}
diff --git a/crates/anonymization/src/ffi/tests.rs b/crates/anonymization/src/ffi/tests.rs
index 1842130d..564dac16 100644
--- a/crates/anonymization/src/ffi/tests.rs
+++ b/crates/anonymization/src/ffi/tests.rs
@@ -1,2 +1,2 @@
#[test]
-fn ffi_anonymization() {}
+const fn ffi_anonymization() {}
diff --git a/crates/anonymization/src/pyo3/py_number.rs b/crates/anonymization/src/pyo3/py_number.rs
index 57f284fd..78aef83d 100644
--- a/crates/anonymization/src/pyo3/py_number.rs
+++ b/crates/anonymization/src/pyo3/py_number.rs
@@ -55,7 +55,7 @@ pub struct NumberScaler(NumberScalerRust);
#[pymethods]
impl NumberScaler {
#[new]
- pub fn new(mean: f64, std_dev: f64, scale: f64, translation: f64) -> Self {
+ pub const fn new(mean: f64, std_dev: f64, scale: f64, translation: f64) -> Self {
Self(NumberScalerRust::new(mean, std_dev, scale, translation))
}
diff --git a/crates/anonymization/src/wasm_bindgen/mod.rs b/crates/anonymization/src/wasm_bindgen/mod.rs
index 599c63f0..9cb3ba2b 100644
--- a/crates/anonymization/src/wasm_bindgen/mod.rs
+++ b/crates/anonymization/src/wasm_bindgen/mod.rs
@@ -7,6 +7,8 @@ macro_rules! wasm_unwrap {
mod hash;
mod noise;
mod number;
+mod word;
+
+#[allow(dead_code)]
#[cfg(test)]
mod tests;
-mod word;
diff --git a/crates/cloudproof/Cargo.toml b/crates/cloudproof/Cargo.toml
index 5a0a7ed9..d875c89a 100644
--- a/crates/cloudproof/Cargo.toml
+++ b/crates/cloudproof/Cargo.toml
@@ -22,6 +22,7 @@ doctest = false
[features]
findex-redis = ["cloudproof_findex/redis-interface"]
findex-sqlite = ["cloudproof_findex/sqlite-interface"]
+findex-rest = ["cloudproof_findex/rest-interface"]
default = [
"cloudproof_aesgcm/default",
"cloudproof_anonymization/default",
@@ -59,4 +60,3 @@ cloudproof_ecies = { version = "0.1.4", optional = true }
cloudproof_findex = { version = "6.0.2", optional = true }
cloudproof_fpe = { version = "0.2.2", optional = true }
######
-cosmian_crypto_core = { workspace = true, features = ["default"] }
diff --git a/crates/cover_crypt/src/ffi/hybrid_cc_aes.rs b/crates/cover_crypt/src/ffi/hybrid_cc_aes.rs
index 7bd55e76..2a45e3e5 100644
--- a/crates/cover_crypt/src/ffi/hybrid_cc_aes.rs
+++ b/crates/cover_crypt/src/ffi/hybrid_cc_aes.rs
@@ -483,7 +483,7 @@ pub unsafe extern "C" fn h_decrypt_header(
#[no_mangle]
///
/// # Safety
-pub unsafe extern "C" fn h_symmetric_encryption_overhead() -> i32 {
+pub const unsafe extern "C" fn h_symmetric_encryption_overhead() -> i32 {
(Aes256Gcm::NONCE_LENGTH + Aes256Gcm::MAC_LENGTH) as i32
}
diff --git a/crates/cover_crypt/src/pyo3/py_abe_policy.rs b/crates/cover_crypt/src/pyo3/py_abe_policy.rs
index 3425ef2d..61d371d6 100644
--- a/crates/cover_crypt/src/pyo3/py_abe_policy.rs
+++ b/crates/cover_crypt/src/pyo3/py_abe_policy.rs
@@ -148,7 +148,7 @@ impl PolicyAxis {
///
/// Returns:
/// bool
- pub fn is_hierarchical(&self) -> bool {
+ pub const fn is_hierarchical(&self) -> bool {
self.0.hierarchical
}
diff --git a/crates/cover_crypt/src/wasm_bindgen/mod.rs b/crates/cover_crypt/src/wasm_bindgen/mod.rs
index 22ecadeb..9f52eccc 100644
--- a/crates/cover_crypt/src/wasm_bindgen/mod.rs
+++ b/crates/cover_crypt/src/wasm_bindgen/mod.rs
@@ -8,5 +8,6 @@ mod abe_policy;
mod generate_cc_keys;
mod hybrid_cc_aes;
+#[allow(dead_code)]
#[cfg(test)]
mod tests;
diff --git a/crates/ecies/src/ffi/ecies.rs b/crates/ecies/src/ffi/ecies.rs
index 6b2c8090..491d2779 100644
--- a/crates/ecies/src/ffi/ecies.rs
+++ b/crates/ecies/src/ffi/ecies.rs
@@ -125,7 +125,7 @@ pub unsafe extern "C" fn h_ecies_salsa_seal_box_encrypt(
}
#[no_mangle]
-pub unsafe extern "C" fn h_ecies_salsa_seal_box_get_encryption_overhead() -> u32 {
+pub const unsafe extern "C" fn h_ecies_salsa_seal_box_get_encryption_overhead() -> u32 {
EciesSalsaSealBox::ENCRYPTION_OVERHEAD as u32
}
diff --git a/crates/ecies/src/wasm_bindgen/mod.rs b/crates/ecies/src/wasm_bindgen/mod.rs
index ec7fd7f5..cd22dd84 100644
--- a/crates/ecies/src/wasm_bindgen/mod.rs
+++ b/crates/ecies/src/wasm_bindgen/mod.rs
@@ -1,4 +1,5 @@
mod ecies;
+#[allow(dead_code)]
#[cfg(test)]
mod tests;
diff --git a/crates/findex/Cargo.toml b/crates/findex/Cargo.toml
index 99475fc9..7f0045f1 100644
--- a/crates/findex/Cargo.toml
+++ b/crates/findex/Cargo.toml
@@ -20,13 +20,14 @@ doctest = false
[features]
# Actual user features.
-default = []
+default = ["rest-interface"]
# Meta features implicitly activated.
serialization = []
ffi = [
"redis-interface",
+ "findex-cloud",
"rest-interface",
"cosmian_ffi_utils",
"lazy_static",
@@ -37,6 +38,7 @@ ffi = [
python = [
"redis-interface",
+ "findex-cloud",
"rest-interface",
"sqlite-interface",
"futures",
@@ -45,6 +47,7 @@ python = [
]
wasm = [
+ "findex-cloud",
"rest-interface",
"js-sys",
"log",
@@ -56,12 +59,8 @@ wasm = [
]
redis-interface = ["redis"]
-rest-interface = [
- "base64",
- "cosmian_crypto_core/ser",
- "reqwest",
- "serialization",
-]
+findex-cloud = ["base64", "cosmian_crypto_core/ser", "reqwest", "serialization"]
+rest-interface = ["base64", "cosmian_crypto_core/ser", "reqwest", "serialization"]
sqlite-interface = ["rusqlite"]
[dependencies]
@@ -71,7 +70,8 @@ async-trait = { workspace = true }
base64 = { workspace = true, optional = true }
cosmian_crypto_core = { workspace = true }
cosmian_ffi_utils = { workspace = true, optional = true }
-cosmian_findex = "6.0.0"
+cosmian_findex = { git = "https://www.github.com/Cosmian/findex", branch = "fix/missing_some_structs_serialization" }
+# cosmian_findex = { path = "../../../findex" }
futures = { version = "0.3.30", optional = true }
js-sys = { workspace = true, optional = true }
lazy_static = { version = "1.4.0", optional = true }
diff --git a/crates/findex/python/cloudproof_findex/__init__.pyi b/crates/findex/python/cloudproof_findex/__init__.pyi
index 09ac7f59..2e4461c3 100644
--- a/crates/findex/python/cloudproof_findex/__init__.pyi
+++ b/crates/findex/python/cloudproof_findex/__init__.pyi
@@ -189,7 +189,7 @@ class AuthorizationToken:
class Findex:
@staticmethod
def new_with_sqlite_interface(
- key: Key, label: str, entry_path: str, chain_path: Optional[str]=None
+ key: Key, label: str, entry_path: str, chain_path: Optional[str] = None
) -> Findex:
"""Instantiate a new Findex instance using an SQLite interface.
@@ -198,7 +198,7 @@ class Findex:
"""
@staticmethod
def new_with_redis_interface(
- key: Key, label: str, entry_url: str, chain_url: Optional[str]=None
+ key: Key, label: str, entry_url: str, chain_url: Optional[str] = None
) -> Findex:
"""Instantiate a new Findex instance using a Redis interface.
@@ -206,8 +206,18 @@ class Findex:
Findex
"""
@staticmethod
- def new_with_rest_interface(label: str, token: str, entry_url: str,
- chain_url: Optional[str]=None) -> Findex:
+ def new_with_findex_cloud_interface(
+ label: str, token: str, entry_url: str, chain_url: Optional[str] = None
+ ) -> Findex:
+ """Instantiate a new Findex instance using a REST interface.
+
+ Returns:
+ Findex
+ """
+ @staticmethod
+ def new_with_rest_interface(
+ key: Key, label: str, entry_url: str, chain_url: Optional[str] = None
+ ) -> Findex:
"""Instantiate a new Findex instance using a REST interface.
Returns:
@@ -218,7 +228,7 @@ class Findex:
key: Key,
label: str,
entry_callbacks: PythonCallbacks,
- chain_callbacks: Optional[PythonCallbacks]=None,
+ chain_callbacks: Optional[PythonCallbacks] = None,
) -> Findex:
"""Instantiate a new Findex instance using a custom interface.
diff --git a/crates/findex/python/tests/findex_test.py b/crates/findex/python/tests/findex_test.py
index a9eedb3f..8a829680 100644
--- a/crates/findex/python/tests/findex_test.py
+++ b/crates/findex/python/tests/findex_test.py
@@ -119,7 +119,9 @@ def upsert(old_values: dict, new_values: dict):
if old_value == current_value:
table[uid] = new_value
elif not current_value:
- raise ValueError('The current value needs to be defined as long as the old value is defined ')
+ raise ValueError(
+ 'The current value needs to be defined as long as the old value is defined '
+ )
else:
res[uid] = current_value
return res
@@ -187,7 +189,7 @@ class TestFindex(unittest.TestCase):
def setUp(self) -> None:
# Create structures needed by Findex
self.findex_key = Key.random()
- self.label = "My label."
+ self.label = 'My label.'
self.db = {
1: ['Martin', 'Sheperd'],
@@ -238,11 +240,17 @@ def setUp(self) -> None:
self.label,
redis_url,
),
- 'rest': Findex.new_with_rest_interface(self.label,
- str(token),
- rest_server_url),
+ 'findex-cloud': Findex.new_with_findex_cloud_interface(
+ self.label, str(token), rest_server_url
+ ),
+ 'rest': Findex.new_with_findex_cloud_interface(
+ self.label, str(token), rest_server_url
+ ),
'custom': Findex.new_with_custom_interface(
- self.findex_key, self.label, in_memory_db_interface, in_memory_db_interface
+ self.findex_key,
+ self.label,
+ in_memory_db_interface,
+ in_memory_db_interface,
),
}
@@ -343,9 +351,9 @@ def test_compact(self) -> None:
instance.add(indexed_values_and_keywords)
# removing 2nd db line
- new_label = "My renewed label"
+ new_label = 'My renewed label'
- filtered_locations = { Location.from_int(2) }
+ filtered_locations = {Location.from_int(2)}
def filter_obsolete_data(dataset: Set[Location]):
res = set()
diff --git a/crates/findex/src/db_interfaces/custom/mod.rs b/crates/findex/src/db_interfaces/custom/mod.rs
index 3b290a71..eceeced2 100644
--- a/crates/findex/src/db_interfaces/custom/mod.rs
+++ b/crates/findex/src/db_interfaces/custom/mod.rs
@@ -14,7 +14,7 @@ macro_rules! impl_custom_backend {
($backend_type:ident, $callback_type:ident, $value_length:ident) => {
impl $backend_type {
#[must_use]
- pub fn new(backend: $callback_type) -> Self {
+ pub const fn new(backend: $callback_type) -> Self {
Self(backend)
}
}
diff --git a/crates/findex/src/db_interfaces/error.rs b/crates/findex/src/db_interfaces/error.rs
index 0a35f965..5f9c9156 100644
--- a/crates/findex/src/db_interfaces/error.rs
+++ b/crates/findex/src/db_interfaces/error.rs
@@ -16,7 +16,12 @@ use wasm_bindgen::JsCast;
#[cfg(feature = "wasm")]
use wasm_bindgen::JsValue;
-#[cfg(any(feature = "rest-interface", feature = "wasm", feature = "ffi"))]
+#[cfg(any(
+ feature = "findex-cloud",
+ feature = "rest-interface",
+ feature = "wasm",
+ feature = "ffi"
+))]
use crate::ser_de::SerializationError;
#[derive(Debug)]
@@ -30,11 +35,11 @@ pub enum DbInterfaceError {
Ffi(String, ErrorCode),
#[cfg(feature = "python")]
Python(String),
- #[cfg(feature = "rest-interface")]
+ #[cfg(feature = "findex-cloud")]
MalformedToken(String),
#[cfg(feature = "wasm")]
Wasm(String),
- #[cfg(feature = "rest-interface")]
+ #[cfg(feature = "findex-cloud")]
MissingPermission(i32),
Findex(FindexCoreError),
CryptoCore(CryptoCoreError),
@@ -55,13 +60,13 @@ impl Display for DbInterfaceError {
Self::MissingCallback(err) => write!(f, "unknown callback: {err}"),
#[cfg(feature = "ffi")]
Self::Ffi(err, code) => write!(f, "{err}: {code}"),
- #[cfg(feature = "rest-interface")]
+ #[cfg(feature = "findex-cloud")]
Self::MalformedToken(err) => write!(f, "{err}"),
#[cfg(feature = "python")]
Self::Python(err) => write!(f, "{err}"),
#[cfg(feature = "wasm")]
Self::Wasm(err) => write!(f, "wasm callback error: {err}"),
- #[cfg(feature = "rest-interface")]
+ #[cfg(feature = "findex-cloud")]
Self::MissingPermission(err) => write!(f, "missing permission: {err}"),
Self::CryptoCore(err) => write!(f, "crypto_core: {err}"),
Self::Findex(err) => write!(f, "findex: {err}"),
@@ -92,7 +97,12 @@ impl From for DbInterfaceError {
}
}
-#[cfg(any(feature = "rest-interface", feature = "wasm", feature = "ffi"))]
+#[cfg(any(
+ feature = "findex-cloud",
+ feature = "rest-interface",
+ feature = "wasm",
+ feature = "ffi"
+))]
impl From for DbInterfaceError {
fn from(e: SerializationError) -> Self {
Self::Serialization(e.to_string())
@@ -105,7 +115,7 @@ impl From for DbInterfaceError {
}
}
-#[cfg(feature = "rest-interface")]
+#[cfg(any(feature = "findex-cloud", feature = "rest-interface"))]
impl From for DbInterfaceError {
fn from(e: TryFromSliceError) -> Self {
Self::SliceConversion(e)
diff --git a/crates/findex/src/db_interfaces/mod.rs b/crates/findex/src/db_interfaces/mod.rs
index 2d0d7abd..ba61e052 100644
--- a/crates/findex/src/db_interfaces/mod.rs
+++ b/crates/findex/src/db_interfaces/mod.rs
@@ -3,7 +3,7 @@
mod error;
-#[cfg(feature = "rest-interface")]
+#[cfg(any(feature = "findex-cloud", feature = "rest-interface"))]
pub mod rest;
#[cfg(any(feature = "wasm", feature = "python", feature = "ffi",))]
@@ -21,6 +21,7 @@ pub mod sqlite;
feature = "ffi",
feature = "python",
feature = "redis-interface",
+ feature = "findex-cloud",
feature = "rest-interface",
feature = "sqlite-interface",
feature = "wasm",
diff --git a/crates/findex/src/db_interfaces/redis.rs b/crates/findex/src/db_interfaces/redis.rs
index 8d99989c..4a786d0d 100644
--- a/crates/findex/src/db_interfaces/redis.rs
+++ b/crates/findex/src/db_interfaces/redis.rs
@@ -15,16 +15,38 @@ use crate::db_interfaces::DbInterfaceError;
/// The length of the prefix of the table name in bytes
/// 0x00ee for the entry table
/// 0x00ef for the chain table
-const TABLE_PREFIX_LENGTH: usize = 2;
+pub const TABLE_PREFIX_LENGTH: usize = 2;
-#[derive(Copy, Clone)]
-enum FindexTable {
+#[repr(u8)]
+#[derive(Copy, Clone, Debug)]
+pub enum FindexTable {
Entry = 0xee,
Chain = 0xef,
}
+impl From for u8 {
+ fn from(table: FindexTable) -> Self {
+ table as Self
+ }
+}
+
+impl TryFrom for FindexTable {
+ type Error = FindexCoreError;
+
+ fn try_from(value: u8) -> Result {
+ match value {
+ 0xee => Ok(Self::Entry),
+ 0xef => Ok(Self::Chain),
+ _ => Err(FindexCoreError::Conversion(format!(
+ "{value} is not a valid table"
+ ))),
+ }
+ }
+}
+
/// Generate a key for the entry table or chain table
-fn build_key(table: FindexTable, uid: &[u8]) -> Vec {
+#[must_use]
+pub fn build_key(table: FindexTable, uid: &[u8]) -> Vec {
[&[0x00, table as u8], uid].concat()
}
@@ -78,6 +100,7 @@ impl RedisEntryBackend {
///
/// # Warning
/// This is definitive
+ #[allow(dependency_on_unit_never_type_fallback)]
pub async fn clear_indexes(&self) -> Result<(), DbInterfaceError> {
redis::cmd("FLUSHDB")
.query_async(&mut self.manager.clone())
@@ -234,6 +257,7 @@ impl RedisChainBackend {
///
/// # Warning
/// This is definitive
+ #[allow(dependency_on_unit_never_type_fallback)]
pub async fn clear_indexes(&self) -> Result<(), DbInterfaceError> {
redis::cmd("FLUSHDB")
.query_async(&mut self.0.clone())
diff --git a/crates/findex/src/db_interfaces/rest/callback_prefix.rs b/crates/findex/src/db_interfaces/rest/callback_prefix.rs
index d70c777e..6e75a187 100644
--- a/crates/findex/src/db_interfaces/rest/callback_prefix.rs
+++ b/crates/findex/src/db_interfaces/rest/callback_prefix.rs
@@ -15,9 +15,9 @@ pub enum CallbackPrefix {
}
impl CallbackPrefix {
- #[cfg(feature = "rest-interface")]
+ #[cfg(any(feature = "findex-cloud", feature = "rest-interface"))]
#[must_use]
- pub fn get_uri(self) -> &'static str {
+ pub const fn get_uri(self) -> &'static str {
match self {
Self::FetchEntry => "fetch_entries",
Self::FetchChain => "fetch_chains",
diff --git a/crates/findex/src/db_interfaces/rest/findex_cloud_stores.rs b/crates/findex/src/db_interfaces/rest/findex_cloud_stores.rs
new file mode 100644
index 00000000..eb49f07c
--- /dev/null
+++ b/crates/findex/src/db_interfaces/rest/findex_cloud_stores.rs
@@ -0,0 +1,330 @@
+#[cfg(not(feature = "wasm"))]
+use std::time::SystemTime;
+use std::{ops::Deref, str::FromStr};
+
+use async_trait::async_trait;
+use cosmian_crypto_core::bytes_ser_de::Serializable;
+use cosmian_findex::{kmac, DbInterface, ENTRY_LENGTH, LINK_LENGTH};
+pub use cosmian_findex::{TokenToEncryptedValueMap, TokenWithEncryptedValueList, Tokens};
+#[cfg(feature = "wasm")]
+use js_sys::Date;
+use reqwest::Client;
+
+use super::{upsert_data::UpsertData, AuthorizationToken, CallbackPrefix};
+use crate::{
+ db_interfaces::DbInterfaceError,
+ ser_de::ffi_ser_de::{
+ deserialize_edx_lines, deserialize_token_set, serialize_edx_lines, serialize_token_set,
+ },
+};
+
+/// The number of seconds of validity of the requests to the `Findex Cloud`
+/// server. After this time, the request cannot be accepted by the backend. This
+/// is done to prevent replay attacks.
+pub const REQUEST_SIGNATURE_TIMEOUT_AS_SECS: u64 = 60;
+
+/// Callback signature length.
+pub const SIGNATURE_LENGTH: usize = 32;
+
+/// Parameters needed to instantiate a REST backend.
+#[derive(Debug, PartialEq, Eq)]
+pub struct FindexCloudParameters {
+ token: AuthorizationToken,
+ url: String,
+}
+
+impl FindexCloudParameters {
+ #[must_use]
+ pub const fn new(token: AuthorizationToken, url: String) -> Self {
+ Self { token, url }
+ }
+
+ pub fn from(token: &str, url: String) -> Result {
+ let token = AuthorizationToken::from_str(token)?;
+ Ok(Self { token, url })
+ }
+}
+
+#[derive(Debug)]
+pub struct FindexCloudChainBackend(FindexCloudParameters);
+
+impl Deref for FindexCloudChainBackend {
+ type Target = FindexCloudParameters;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl FindexCloudChainBackend {
+ #[must_use]
+ pub const fn new(parameters: FindexCloudParameters) -> Self {
+ Self(parameters)
+ }
+
+ /// Post the given `body` signed with the given `callback` key.
+ async fn post(
+ &self,
+ callback: CallbackPrefix,
+ bytes: &[u8],
+ ) -> Result, DbInterfaceError> {
+ let key = {
+ self.token
+ .get_key(&self.token.index_id, callback)
+ .ok_or_else(|| DbInterfaceError::MissingPermission(callback as i32))?
+ };
+
+ // SystemTime::now() panics in WASM
+ #[cfg(feature = "wasm")]
+ let current_timestamp = (Date::now() / 1000.0) as u64; // Date::now() returns milliseconds
+
+ #[cfg(not(feature = "wasm"))]
+ let current_timestamp = SystemTime::now()
+ .duration_since(SystemTime::UNIX_EPOCH)
+ .map_err(|_| DbInterfaceError::Other("SystemTime is before UNIX_EPOCH".to_string()))?
+ .as_secs();
+
+ let expiration_timestamp_bytes =
+ (current_timestamp + REQUEST_SIGNATURE_TIMEOUT_AS_SECS).to_be_bytes();
+
+ let signature = kmac!(SIGNATURE_LENGTH, &key, &expiration_timestamp_bytes, bytes);
+
+ let mut body =
+ Vec::with_capacity(signature.len() + expiration_timestamp_bytes.len() + bytes.len());
+ body.extend(&signature);
+ body.extend(&expiration_timestamp_bytes);
+ body.extend(bytes);
+
+ let url = {
+ format!(
+ "{}/indexes/{}/{}",
+ &self.url,
+ self.token.index_id,
+ callback.get_uri(),
+ )
+ };
+
+ let response = Client::new()
+ .post(url)
+ .body(body)
+ .send()
+ .await
+ .map_err(|err| {
+ DbInterfaceError::Other(format!(
+ "Unable to send the request to Findex Cloud: {err}"
+ ))
+ })?;
+
+ if !response.status().is_success() {
+ return Err(DbInterfaceError::Other(format!(
+ "request to Findex Cloud server failed, status code is {}, response is '{}'",
+ response.status(),
+ response
+ .text()
+ .await
+ .unwrap_or_else(|_| "cannot parse response".to_owned())
+ )));
+ }
+
+ response.bytes().await.map(|r| r.to_vec()).map_err(|err| {
+ DbInterfaceError::Other(format!(
+ "Unable to read the returned bytes from Findex Cloud server: {err}"
+ ))
+ })
+ }
+}
+
+#[async_trait(?Send)]
+impl DbInterface for FindexCloudChainBackend {
+ type Error = DbInterfaceError;
+
+ async fn dump_tokens(&self) -> Result {
+ let bytes = self.post(CallbackPrefix::DumpTokens, &[]).await?;
+ deserialize_token_set(&bytes)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn fetch(
+ &self,
+ tokens: Tokens,
+ ) -> Result, Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let res = self.post(CallbackPrefix::FetchChain, &bytes).await?;
+ deserialize_edx_lines(&res)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn upsert(
+ &self,
+ old_values: TokenToEncryptedValueMap,
+ new_values: TokenToEncryptedValueMap,
+ ) -> Result, Self::Error> {
+ let modifications = UpsertData::::new(old_values, new_values);
+ let bytes = modifications.serialize()?;
+
+ let res = self.post(CallbackPrefix::Upsert, &bytes).await?;
+
+ deserialize_edx_lines(&res)
+ .map(|v| v.into_iter().collect())
+ .map_err(Self::Error::from)
+ }
+
+ async fn insert(
+ &self,
+ values: TokenToEncryptedValueMap,
+ ) -> Result<(), Self::Error> {
+ let bytes = serialize_edx_lines(&values)?;
+ let _ = self.post(CallbackPrefix::Insert, &bytes).await?;
+ Ok(())
+ }
+
+ async fn delete(&self, tokens: Tokens) -> Result<(), Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let _ = self.post(CallbackPrefix::DeleteChain, &bytes).await?;
+ Ok(())
+ }
+}
+
+#[derive(Debug)]
+pub struct FindexCloudEntryBackend(FindexCloudParameters);
+
+impl Deref for FindexCloudEntryBackend {
+ type Target = FindexCloudParameters;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl FindexCloudEntryBackend {
+ #[must_use]
+ pub const fn new(parameters: FindexCloudParameters) -> Self {
+ Self(parameters)
+ }
+
+ /// Post the given `body` signed with the given `callback` key.
+ async fn post(
+ &self,
+ callback: CallbackPrefix,
+ bytes: &[u8],
+ ) -> Result, DbInterfaceError> {
+ let key = {
+ self.token
+ .get_key(&self.token.index_id, callback)
+ .ok_or_else(|| DbInterfaceError::MissingPermission(callback as i32))?
+ };
+
+ // SystemTime::now() panics in WASM
+ #[cfg(feature = "wasm")]
+ let current_timestamp = (Date::now() / 1000.0) as u64; // Date::now() returns milliseconds
+
+ #[cfg(not(feature = "wasm"))]
+ let current_timestamp = SystemTime::now()
+ .duration_since(SystemTime::UNIX_EPOCH)
+ .map_err(|_| DbInterfaceError::Other("SystemTime is before UNIX_EPOCH".to_string()))?
+ .as_secs();
+
+ let expiration_timestamp_bytes =
+ (current_timestamp + REQUEST_SIGNATURE_TIMEOUT_AS_SECS).to_be_bytes();
+
+ let signature = kmac!(SIGNATURE_LENGTH, &key, &expiration_timestamp_bytes, bytes);
+
+ let mut body =
+ Vec::with_capacity(signature.len() + expiration_timestamp_bytes.len() + bytes.len());
+ body.extend(&signature);
+ body.extend(&expiration_timestamp_bytes);
+ body.extend(bytes);
+
+ let url = {
+ format!(
+ "{}/indexes/{}/{}",
+ &self.url,
+ self.token.index_id,
+ callback.get_uri(),
+ )
+ };
+
+ let response = Client::new()
+ .post(url)
+ .body(body)
+ .send()
+ .await
+ .map_err(|err| {
+ DbInterfaceError::Other(format!(
+ "Unable to send the request to Findex Cloud: {err}"
+ ))
+ })?;
+
+ if !response.status().is_success() {
+ return Err(DbInterfaceError::Other(format!(
+ "request to Findex Cloud server failed, status code is {}, response is '{}'",
+ response.status(),
+ response
+ .text()
+ .await
+ .unwrap_or_else(|_| "cannot parse response".to_owned())
+ )));
+ }
+
+ response.bytes().await.map(|r| r.to_vec()).map_err(|err| {
+ DbInterfaceError::Other(format!(
+ "Unable to read the returned bytes from Findex Cloud server: {err}"
+ ))
+ })
+ }
+}
+
+#[async_trait(?Send)]
+impl DbInterface for FindexCloudEntryBackend {
+ type Error = DbInterfaceError;
+
+ async fn dump_tokens(&self) -> Result {
+ let bytes = self.post(CallbackPrefix::DumpTokens, &[]).await?;
+ deserialize_token_set(&bytes)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn fetch(
+ &self,
+ tokens: Tokens,
+ ) -> Result, Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let res = self.post(CallbackPrefix::FetchEntry, &bytes).await?;
+ deserialize_edx_lines(&res)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn upsert(
+ &self,
+ old_values: TokenToEncryptedValueMap,
+ new_values: TokenToEncryptedValueMap,
+ ) -> Result, Self::Error> {
+ let modifications = UpsertData::::new(old_values, new_values);
+ let bytes = modifications.serialize()?;
+
+ let res = self.post(CallbackPrefix::Upsert, &bytes).await?;
+
+ deserialize_edx_lines(&res)
+ .map(|v| v.into_iter().collect())
+ .map_err(Self::Error::from)
+ }
+
+ async fn insert(
+ &self,
+ values: TokenToEncryptedValueMap,
+ ) -> Result<(), Self::Error> {
+ let bytes = serialize_edx_lines(&values)?;
+ let _ = self.post(CallbackPrefix::Insert, &bytes).await?;
+ Ok(())
+ }
+
+ async fn delete(&self, tokens: Tokens) -> Result<(), Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let _ = self.post(CallbackPrefix::DeleteEntry, &bytes).await?;
+ Ok(())
+ }
+}
diff --git a/crates/findex/src/db_interfaces/rest/mod.rs b/crates/findex/src/db_interfaces/rest/mod.rs
index a4957265..cae32ee2 100644
--- a/crates/findex/src/db_interfaces/rest/mod.rs
+++ b/crates/findex/src/db_interfaces/rest/mod.rs
@@ -1,8 +1,19 @@
+#[cfg(feature = "rest-interface")]
mod callback_prefix;
-mod stores;
+#[cfg(feature = "findex-cloud")]
+mod findex_cloud_stores;
+mod rest_stores;
+#[cfg(feature = "findex-cloud")]
mod token;
mod upsert_data;
pub use callback_prefix::CallbackPrefix;
-pub use stores::{RestChainBackend, RestEntryBackend, RestParameters};
+#[cfg(feature = "findex-cloud")]
+pub use findex_cloud_stores::{
+ FindexCloudChainBackend, FindexCloudEntryBackend, FindexCloudParameters,
+};
+#[cfg(feature = "rest-interface")]
+pub use rest_stores::{RestChainBackend, RestEntryBackend};
+#[cfg(feature = "findex-cloud")]
pub use token::AuthorizationToken;
+pub use upsert_data::UpsertData;
diff --git a/crates/findex/src/db_interfaces/rest/rest_stores.rs b/crates/findex/src/db_interfaces/rest/rest_stores.rs
new file mode 100644
index 00000000..02960c02
--- /dev/null
+++ b/crates/findex/src/db_interfaces/rest/rest_stores.rs
@@ -0,0 +1,220 @@
+use async_trait::async_trait;
+use cosmian_crypto_core::bytes_ser_de::Serializable;
+use cosmian_findex::{DbInterface, ENTRY_LENGTH, LINK_LENGTH};
+pub use cosmian_findex::{TokenToEncryptedValueMap, TokenWithEncryptedValueList, Tokens};
+use reqwest::Client;
+
+use super::{upsert_data::UpsertData, CallbackPrefix};
+use crate::{
+ db_interfaces::DbInterfaceError,
+ ser_de::ffi_ser_de::{
+ deserialize_edx_lines, deserialize_token_set, serialize_edx_lines, serialize_token_set,
+ },
+};
+
+#[derive(Debug)]
+pub struct RestEntryBackend {
+ pub client: Client,
+ pub url: String,
+ pub index_id: String,
+}
+
+impl RestEntryBackend {
+ async fn post(
+ &self,
+ callback: CallbackPrefix,
+ body: &[u8],
+ ) -> Result, DbInterfaceError> {
+ let url = {
+ format!(
+ "{}/indexes/{}/{}",
+ &self.url,
+ self.index_id,
+ callback.get_uri(),
+ )
+ };
+ let response = self
+ .client
+ .post(url)
+ .body(body.to_vec())
+ .send()
+ .await
+ .map_err(|err| {
+ DbInterfaceError::Other(format!("Unable to send the request to Findex REST: {err}"))
+ })?;
+
+ if !response.status().is_success() {
+ return Err(DbInterfaceError::Other(format!(
+ "request to Findex REST server failed, status code is {}, response is '{}'",
+ response.status(),
+ response
+ .text()
+ .await
+ .unwrap_or_else(|_| "cannot parse response".to_owned())
+ )));
+ }
+
+ response.bytes().await.map(|r| r.to_vec()).map_err(|err| {
+ DbInterfaceError::Other(format!(
+ "Unable to read the returned bytes from Findex REST server: {err}"
+ ))
+ })
+ }
+}
+
+#[async_trait(?Send)]
+impl DbInterface for RestEntryBackend {
+ type Error = DbInterfaceError;
+
+ async fn dump_tokens(&self) -> Result {
+ let bytes = self.post(CallbackPrefix::DumpTokens, &[]).await?;
+ deserialize_token_set(&bytes)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn fetch(
+ &self,
+ tokens: Tokens,
+ ) -> Result, Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let res = self.post(CallbackPrefix::FetchEntry, &bytes).await?;
+ deserialize_edx_lines(&res)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn upsert(
+ &self,
+ old_values: TokenToEncryptedValueMap,
+ new_values: TokenToEncryptedValueMap,
+ ) -> Result, Self::Error> {
+ let modifications = UpsertData::::new(old_values, new_values);
+ let bytes = modifications.serialize()?;
+
+ let res = self.post(CallbackPrefix::Upsert, &bytes).await?;
+
+ deserialize_edx_lines(&res)
+ .map(|v| v.into_iter().collect())
+ .map_err(Self::Error::from)
+ }
+
+ async fn insert(
+ &self,
+ values: TokenToEncryptedValueMap,
+ ) -> Result<(), Self::Error> {
+ let bytes = serialize_edx_lines(&values)?;
+ let _ = self.post(CallbackPrefix::Insert, &bytes).await?;
+ Ok(())
+ }
+
+ async fn delete(&self, tokens: Tokens) -> Result<(), Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let _ = self.post(CallbackPrefix::DeleteEntry, &bytes).await?;
+ Ok(())
+ }
+}
+
+#[derive(Debug)]
+pub struct RestChainBackend {
+ pub client: Client,
+ pub url: String,
+ pub index_id: String,
+}
+
+impl RestChainBackend {
+ async fn post(
+ &self,
+ callback: CallbackPrefix,
+ body: &[u8],
+ ) -> Result, DbInterfaceError> {
+ let url = {
+ format!(
+ "{}/indexes/{}/{}",
+ &self.url,
+ self.index_id,
+ callback.get_uri(),
+ )
+ };
+
+ let response = self
+ .client
+ .post(url)
+ .body(body.to_vec())
+ .send()
+ .await
+ .map_err(|err| {
+ DbInterfaceError::Other(format!("Unable to send the request to Findex REST: {err}"))
+ })?;
+
+ if !response.status().is_success() {
+ return Err(DbInterfaceError::Other(format!(
+ "request to Findex REST server failed, status code is {}, response is '{}'",
+ response.status(),
+ response
+ .text()
+ .await
+ .unwrap_or_else(|_| "cannot parse response".to_owned())
+ )));
+ }
+
+ response.bytes().await.map(|r| r.to_vec()).map_err(|err| {
+ DbInterfaceError::Other(format!(
+ "Unable to read the returned bytes from Findex REST server: {err}"
+ ))
+ })
+ }
+}
+
+#[async_trait(?Send)]
+impl DbInterface for RestChainBackend {
+ type Error = DbInterfaceError;
+
+ async fn dump_tokens(&self) -> Result {
+ let bytes = self.post(CallbackPrefix::DumpTokens, &[]).await?;
+ deserialize_token_set(&bytes)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn fetch(
+ &self,
+ tokens: Tokens,
+ ) -> Result, Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let res = self.post(CallbackPrefix::FetchChain, &bytes).await?;
+ deserialize_edx_lines(&res)
+ .map_err(Self::Error::from)
+ .map(Into::into)
+ }
+
+ async fn upsert(
+ &self,
+ old_values: TokenToEncryptedValueMap,
+ new_values: TokenToEncryptedValueMap,
+ ) -> Result, Self::Error> {
+ let modifications = UpsertData::::new(old_values, new_values);
+ let bytes = modifications.serialize()?;
+
+ let res = self.post(CallbackPrefix::Upsert, &bytes).await?;
+
+ deserialize_edx_lines(&res)
+ .map(|v| v.into_iter().collect())
+ .map_err(Self::Error::from)
+ }
+
+ async fn insert(
+ &self,
+ values: TokenToEncryptedValueMap,
+ ) -> Result<(), Self::Error> {
+ let bytes = serialize_edx_lines(&values)?;
+ let _ = self.post(CallbackPrefix::Insert, &bytes).await?;
+ Ok(())
+ }
+
+ async fn delete(&self, tokens: Tokens) -> Result<(), Self::Error> {
+ let bytes = serialize_token_set(&tokens)?;
+ let _ = self.post(CallbackPrefix::DeleteChain, &bytes).await?;
+ Ok(())
+ }
+}
diff --git a/crates/findex/src/db_interfaces/rest/stores.rs b/crates/findex/src/db_interfaces/rest/stores.rs
deleted file mode 100644
index 24bafe31..00000000
--- a/crates/findex/src/db_interfaces/rest/stores.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-#[cfg(not(feature = "wasm"))]
-use std::time::SystemTime;
-use std::{ops::Deref, str::FromStr};
-
-use async_trait::async_trait;
-use cosmian_crypto_core::bytes_ser_de::Serializable;
-use cosmian_findex::{kmac, DbInterface, ENTRY_LENGTH, LINK_LENGTH};
-pub use cosmian_findex::{TokenToEncryptedValueMap, TokenWithEncryptedValueList, Tokens};
-#[cfg(feature = "wasm")]
-use js_sys::Date;
-use reqwest::Client;
-
-use super::{upsert_data::UpsertData, AuthorizationToken, CallbackPrefix};
-use crate::{
- db_interfaces::DbInterfaceError,
- ser_de::ffi_ser_de::{
- deserialize_edx_lines, deserialize_token_set, serialize_edx_lines, serialize_token_set,
- },
-};
-
-/// The number of seconds of validity of the requests to the `FindexREST`
-/// server. After this time, the request cannot be accepted by the backend. This
-/// is done to prevent replay attacks.
-pub const REQUEST_SIGNATURE_TIMEOUT_AS_SECS: u64 = 60;
-
-/// Callback signature length.
-pub const SIGNATURE_LENGTH: usize = 32;
-
-macro_rules! impl_rest_backend {
- ($type:ident, $value_length:ident, $name:literal, $table_bit:expr) => {
- impl Deref for $type {
- type Target = RestParameters;
-
- fn deref(&self) -> &Self::Target {
- &self.0
- }
- }
-
- impl $type {
- #[must_use]
- pub fn new(parameters: RestParameters) -> Self {
- Self(parameters)
- }
-
- /// Post the given `body` signed with the given `callback` key.
- async fn post(
- &self,
- callback: CallbackPrefix,
- bytes: &[u8],
- ) -> Result, DbInterfaceError> {
- let key = {
- self.token
- .get_key(&self.token.index_id, callback)
- .ok_or_else(|| DbInterfaceError::MissingPermission(callback as i32))?
- };
-
- // SystemTime::now() panics in WASM
- #[cfg(feature = "wasm")]
- let current_timestamp = (Date::now() / 1000.0) as u64; // Date::now() returns milliseconds
-
- #[cfg(not(feature = "wasm"))]
- let current_timestamp = SystemTime::now()
- .duration_since(SystemTime::UNIX_EPOCH)
- .map_err(|_| {
- DbInterfaceError::Other("SystemTime is before UNIX_EPOCH".to_string())
- })?
- .as_secs();
-
- let expiration_timestamp_bytes =
- (current_timestamp + REQUEST_SIGNATURE_TIMEOUT_AS_SECS).to_be_bytes();
-
- let signature = kmac!(SIGNATURE_LENGTH, &key, &expiration_timestamp_bytes, bytes);
-
- let mut body = Vec::with_capacity(
- signature.len() + expiration_timestamp_bytes.len() + bytes.len(),
- );
- body.extend(&signature);
- body.extend(&expiration_timestamp_bytes);
- body.extend(bytes);
-
- let url = {
- format!(
- "{}/indexes/{}/{}",
- &self.url,
- self.token.index_id,
- callback.get_uri(),
- )
- };
-
- let response = Client::new()
- .post(url)
- .body(body)
- .send()
- .await
- .map_err(|err| {
- DbInterfaceError::Other(format!(
- "Unable to send the request to FindexREST: {err}"
- ))
- })?;
-
- if !response.status().is_success() {
- return Err(DbInterfaceError::Other(format!(
- "request to FindexREST server failed, status code is {}, response is {}",
- response.status(),
- response
- .text()
- .await
- .unwrap_or_else(|_| "cannot parse response".to_owned())
- )));
- }
-
- response.bytes().await.map(|r| r.to_vec()).map_err(|err| {
- DbInterfaceError::Other(format!(
- "Impossible to read the returned bytes from FindexREST server: {err}"
- ))
- })
- }
- }
-
- #[async_trait(?Send)]
- impl DbInterface<$value_length> for $type {
- type Error = DbInterfaceError;
-
- async fn dump_tokens(&self) -> Result {
- let bytes = self.post(CallbackPrefix::DumpTokens, &[]).await?;
- deserialize_token_set(&bytes)
- .map_err(Self::Error::from)
- .map(Into::into)
- }
-
- async fn fetch(
- &self,
- tokens: $crate::db_interfaces::rest::stores::Tokens,
- ) -> Result<
- $crate::db_interfaces::rest::stores::TokenWithEncryptedValueList<$value_length>,
- Self::Error,
- > {
- let bytes = serialize_token_set(&tokens.into())?;
- let res = self
- .post(
- (CallbackPrefix::FetchEntry as u8 + $table_bit).try_into()?,
- &bytes,
- )
- .await?;
- deserialize_edx_lines(&res)
- .map_err(Self::Error::from)
- .map(Into::into)
- }
-
- async fn upsert(
- &self,
- old_values: $crate::db_interfaces::rest::stores::TokenToEncryptedValueMap<
- $value_length,
- >,
- new_values: $crate::db_interfaces::rest::stores::TokenToEncryptedValueMap<
- $value_length,
- >,
- ) -> Result<
- $crate::db_interfaces::rest::stores::TokenToEncryptedValueMap<$value_length>,
- Self::Error,
- > {
- let modifications = UpsertData::<$value_length>::new(old_values, new_values);
- let bytes = modifications.serialize()?;
-
- let res = self.post(CallbackPrefix::Upsert, &bytes).await?;
-
- deserialize_edx_lines(&res)
- .map(|v| v.into_iter().collect())
- .map_err(Self::Error::from)
- }
-
- async fn insert(
- &self,
- values: $crate::db_interfaces::rest::stores::TokenToEncryptedValueMap<
- $value_length,
- >,
- ) -> Result<(), Self::Error> {
- let bytes = serialize_edx_lines(&values.into())?;
- let _ = self.post(CallbackPrefix::Insert, &bytes).await?;
- Ok(())
- }
-
- async fn delete(
- &self,
- tokens: $crate::db_interfaces::rest::stores::Tokens,
- ) -> Result<(), Self::Error> {
- let bytes = serialize_token_set(&tokens.into())?;
- let _ = self
- .post(
- (CallbackPrefix::DeleteEntry as u8 + $table_bit).try_into()?,
- &bytes,
- )
- .await?;
- Ok(())
- }
- }
- };
-}
-
-/// Parameters needed to instantiate a REST backend.
-#[derive(Debug, PartialEq, Eq)]
-pub struct RestParameters {
- token: AuthorizationToken,
- url: String,
-}
-
-impl RestParameters {
- #[must_use]
- pub fn new(token: AuthorizationToken, url: String) -> Self {
- Self { token, url }
- }
-
- pub fn from(token: &str, url: String) -> Result {
- let token = AuthorizationToken::from_str(token)?;
- Ok(Self { token, url })
- }
-}
-
-#[derive(Debug)]
-pub struct RestEntryBackend(RestParameters);
-
-impl_rest_backend!(RestEntryBackend, ENTRY_LENGTH, "entry_table", 0);
-
-#[derive(Debug)]
-pub struct RestChainBackend(RestParameters);
-
-impl_rest_backend!(RestChainBackend, LINK_LENGTH, "entry_table", 1);
diff --git a/crates/findex/src/db_interfaces/sqlite.rs b/crates/findex/src/db_interfaces/sqlite.rs
index 03694bb6..f6b66a90 100644
--- a/crates/findex/src/db_interfaces/sqlite.rs
+++ b/crates/findex/src/db_interfaces/sqlite.rs
@@ -82,8 +82,8 @@ macro_rules! impl_sqlite_backend {
)?;
rows.map(|res| {
- // TODO: this fix is needed since error from conversion to encrypted value is not
- // easily convertible inside the `query_map`.
+ // TODO: this fix is needed since error from conversion to encrypted value is
+ // not easily convertible inside the `query_map`.
//
// Two paths to go forward:
// - find a way to convert the error inside `query_map`
diff --git a/crates/findex/src/db_interfaces/tests.rs b/crates/findex/src/db_interfaces/tests.rs
index fe48a6b8..bb573ef8 100644
--- a/crates/findex/src/db_interfaces/tests.rs
+++ b/crates/findex/src/db_interfaces/tests.rs
@@ -81,8 +81,8 @@ fn get_users() -> Result, DbInterfaceError> {
.map_err(|e| DbInterfaceError::Serialization(e.to_string()))
}
-/// Generate the key used in the tests. In case the test is a non-regression, the key from
-/// `dataset` is used. Otherwise a new random key is generated.
+/// Generate the key used in the tests. In case the test is a non-regression,
+/// the key from `dataset` is used. Otherwise a new random key is generated.
fn get_key(is_non_regression: bool) -> UserKey {
if is_non_regression {
let bytes = general_purpose::STANDARD
@@ -194,7 +194,8 @@ async fn find_users(findex: &InstantiatedFindex, key: &UserKey, label: &Label) {
/// 3. Asserts that compact operations can be run on the backend.
/// 4. Asserts that the correctness of the search as defined in step 2.
///
-/// The `.db` file produced by this test should be okay to use in the non-regression test.
+/// The `.db` file produced by this test should be okay to use in the
+/// non-regression test.
pub async fn test_backend(config: Configuration) {
let is_non_regression = false;
diff --git a/crates/findex/src/instantiation/db_config.rs b/crates/findex/src/instantiation/db_config.rs
index 7eb501a4..85fdeb6a 100644
--- a/crates/findex/src/instantiation/db_config.rs
+++ b/crates/findex/src/instantiation/db_config.rs
@@ -1,10 +1,12 @@
+use reqwest::Client;
+
#[cfg(feature = "ffi")]
use crate::db_interfaces::custom::ffi::FfiCallbacks;
#[cfg(feature = "python")]
use crate::db_interfaces::custom::python::PythonCallbacks;
#[cfg(feature = "wasm")]
use crate::db_interfaces::custom::wasm::WasmCallbacks;
-#[cfg(feature = "rest-interface")]
+#[cfg(feature = "findex-cloud")]
use crate::db_interfaces::rest::AuthorizationToken;
/// Contains all parameters needed to instantiate the corresponding interfaces.
@@ -13,23 +15,29 @@ use crate::db_interfaces::rest::AuthorizationToken;
/// Entry Table while the second ones are used to instantiate the Chain Table.
#[derive(Clone)]
pub enum Configuration {
- /// REST DB interface requires an authorization token and a server URL for the Entry and the
- /// Chain tables.
+ /// Findex Cloud DB interface requires an authorization token and a server
+ /// URL for the Entry and the Chain tables.
+ #[cfg(feature = "findex-cloud")]
+ FindexCloud(AuthorizationToken, String, String),
+
+ /// REST DB interface requires an authorization token and a server URL for
+ /// the Entry and the Chain tables and the index ID.
#[cfg(feature = "rest-interface")]
- Rest(AuthorizationToken, String, String),
+ Rest(Client, String, String, String),
- /// FFI DB interface requests FFI functions corresponding to the APIs used by the
- /// Entry/Chain tables.
+ /// FFI DB interface requests FFI functions corresponding to the APIs used
+ /// by the Entry/Chain tables.
#[cfg(feature = "ffi")]
Ffi(FfiCallbacks, FfiCallbacks),
- /// Python DB interface requests Python functions corresponding to the APIs used
- /// by the Entry/Chain tables.
+ /// Python DB interface requests Python functions corresponding to the APIs
+ /// used by the Entry/Chain tables.
#[cfg(feature = "python")]
Python(PythonCallbacks, PythonCallbacks),
- /// SQLite DB interface requests a valid [`Connection`](rusqlite::Connection)
- /// pointing to valid Entry/Chain tables.
+ /// `SQLite` DB interface requests a valid
+ /// [`Connection`](rusqlite::Connection) pointing to valid Entry/Chain
+ /// tables.
#[cfg(feature = "sqlite-interface")]
Sqlite(String, String),
@@ -37,8 +45,8 @@ pub enum Configuration {
#[cfg(feature = "redis-interface")]
Redis(String, String),
- /// WASM DB interface requests WASM functions corresponding to the APIs used by
- /// the Entry/Chain tables.
+ /// WASM DB interface requests WASM functions corresponding to the APIs used
+ /// by the Entry/Chain tables.
#[cfg(feature = "wasm")]
Wasm(WasmCallbacks, WasmCallbacks),
}
diff --git a/crates/findex/src/instantiation/findex.rs b/crates/findex/src/instantiation/findex.rs
index fbf1cec2..af69dfa2 100644
--- a/crates/findex/src/instantiation/findex.rs
+++ b/crates/findex/src/instantiation/findex.rs
@@ -17,8 +17,12 @@ use crate::db_interfaces::custom::python::{PythonChainBackend, PythonEntryBacken
use crate::db_interfaces::custom::wasm::{WasmChainBackend, WasmEntryBackend};
#[cfg(feature = "redis-interface")]
use crate::db_interfaces::redis::{RedisChainBackend, RedisEntryBackend};
+#[cfg(feature = "findex-cloud")]
+use crate::db_interfaces::rest::{
+ FindexCloudChainBackend, FindexCloudEntryBackend, FindexCloudParameters,
+};
#[cfg(feature = "rest-interface")]
-use crate::db_interfaces::rest::{RestChainBackend, RestEntryBackend, RestParameters};
+use crate::db_interfaces::rest::{RestChainBackend, RestEntryBackend};
#[cfg(feature = "sqlite-interface")]
use crate::db_interfaces::sqlite::{SqlChainBackend, SqlEntryBackend};
use crate::{db_interfaces::DbInterfaceError, Configuration};
@@ -70,6 +74,15 @@ pub enum InstantiatedFindex {
>,
),
+ #[cfg(feature = "findex-cloud")]
+ FindexCloud(
+ Findex<
+ DbInterfaceError,
+ EntryTable,
+ ChainTable,
+ >,
+ ),
+
#[cfg(feature = "rest-interface")]
Rest(
Findex<
@@ -96,13 +109,31 @@ impl InstantiatedFindex {
ChainTable::setup(RedisChainBackend::connect(&chain_params).await?),
)),
+ #[cfg(feature = "findex-cloud")]
+ Configuration::FindexCloud(token, entry_url, chain_url) => {
+ Self::FindexCloud(Findex::new(
+ EntryTable::setup(FindexCloudEntryBackend::new(FindexCloudParameters::new(
+ token.clone(),
+ entry_url,
+ ))),
+ ChainTable::setup(FindexCloudChainBackend::new(FindexCloudParameters::new(
+ token, chain_url,
+ ))),
+ ))
+ }
+
#[cfg(feature = "rest-interface")]
- Configuration::Rest(token, entry_url, chain_url) => Self::Rest(Findex::new(
- EntryTable::setup(RestEntryBackend::new(RestParameters::new(
- token.clone(),
- entry_url,
- ))),
- ChainTable::setup(RestChainBackend::new(RestParameters::new(token, chain_url))),
+ Configuration::Rest(client, entry_url, chain_url, index_id) => Self::Rest(Findex::new(
+ EntryTable::setup(RestEntryBackend {
+ client: client.clone(),
+ url: entry_url,
+ index_id: index_id.clone(),
+ }),
+ ChainTable::setup(RestChainBackend {
+ client,
+ url: chain_url,
+ index_id,
+ }),
)),
#[cfg(feature = "ffi")]
@@ -141,6 +172,8 @@ impl InstantiatedFindex {
Self::Python(findex) => findex.keygen(),
#[cfg(feature = "wasm")]
Self::Wasm(findex) => findex.keygen(),
+ #[cfg(feature = "findex-cloud")]
+ Self::FindexCloud(findex) => findex.keygen(),
#[cfg(feature = "rest-interface")]
Self::Rest(findex) => findex.keygen(),
}
@@ -158,6 +191,8 @@ impl InstantiatedFindex {
interrupt: &Interrupt,
) -> Result> {
match self {
+ #[cfg(feature = "findex-cloud")]
+ Self::FindexCloud(findex) => findex.search(key, label, keywords, interrupt).await,
#[cfg(feature = "rest-interface")]
Self::Rest(findex) => findex.search(key, label, keywords, interrupt).await,
#[cfg(feature = "ffi")]
@@ -191,6 +226,8 @@ impl InstantiatedFindex {
Self::Python(findex) => findex.add(key, label, additions).await,
#[cfg(feature = "wasm")]
Self::Wasm(findex) => findex.add(key, label, additions).await,
+ #[cfg(feature = "findex-cloud")]
+ Self::FindexCloud(findex) => findex.add(key, label, additions).await,
#[cfg(feature = "rest-interface")]
Self::Rest(findex) => findex.add(key, label, additions).await,
}
@@ -214,6 +251,8 @@ impl InstantiatedFindex {
Self::Python(findex) => findex.delete(key, label, deletions).await,
#[cfg(feature = "wasm")]
Self::Wasm(findex) => findex.delete(key, label, deletions).await,
+ #[cfg(feature = "findex-cloud")]
+ Self::FindexCloud(findex) => findex.delete(key, label, deletions).await,
#[cfg(feature = "rest-interface")]
Self::Rest(findex) => findex.delete(key, label, deletions).await,
}
@@ -298,6 +337,19 @@ impl InstantiatedFindex {
)
.await
}
+ #[cfg(feature = "findex-cloud")]
+ Self::FindexCloud(findex) => {
+ findex
+ .compact(
+ old_key,
+ new_key,
+ old_label,
+ new_label,
+ compacting_rate,
+ data_filter,
+ )
+ .await
+ }
#[cfg(feature = "rest-interface")]
Self::Rest(findex) => {
findex
diff --git a/crates/findex/src/interfaces/ffi/api.rs b/crates/findex/src/interfaces/ffi/api.rs
index a3bb6595..e42f9033 100644
--- a/crates/findex/src/interfaces/ffi/api.rs
+++ b/crates/findex/src/interfaces/ffi/api.rs
@@ -131,7 +131,7 @@ pub unsafe extern "C" fn h_instantiate_with_custom_interface(
ErrorCode::Success.into()
}
-/// Instantiate a Findex using a REST backend.
+/// Instantiate a Findex using a Findex Cloud backend.
///
/// # Parameters
///
@@ -144,7 +144,7 @@ pub unsafe extern "C" fn h_instantiate_with_custom_interface(
/// Cannot be safe since using FFI.
#[no_mangle]
#[tracing::instrument(ret, skip_all)]
-pub unsafe extern "C" fn h_instantiate_with_rest_interface(
+pub unsafe extern "C" fn h_instantiate_with_findex_cloud_interface(
findex_handle: *mut i32,
label_ptr: *const i8,
token_ptr: *const i8,
@@ -177,7 +177,7 @@ pub unsafe extern "C" fn h_instantiate_with_rest_interface(
} else {
ffi_read_string!("REST server Chain Table URL", chain_url_ptr)
};
- let config = Configuration::Rest(authorization_token.clone(), entry_url, chain_url);
+ let config = Configuration::FindexCloud(authorization_token.clone(), entry_url, chain_url);
let rt = ffi_unwrap!(
tokio::runtime::Runtime::new(),
@@ -205,6 +205,81 @@ pub unsafe extern "C" fn h_instantiate_with_rest_interface(
ErrorCode::Success.into()
}
+/// Instantiate a Findex using a REST backend.
+///
+/// # Parameters
+///
+/// - `label` : label used by Findex
+/// - `token` : token containing authentication keys
+/// - `url` : REST server URL
+///
+/// # Safety
+///
+/// Cannot be safe since using FFI.
+#[no_mangle]
+#[tracing::instrument(ret, skip_all)]
+pub unsafe extern "C" fn h_instantiate_with_rest_interface(
+ findex_handle: *mut i32,
+ key_ptr: *const u8,
+ key_len: i32,
+ label_ptr: *const i8,
+ entry_url_ptr: *const i8,
+ chain_url_ptr: *const i8,
+) -> i32 {
+ #[cfg(debug_assertions)]
+ log_init();
+
+ let key_bytes = ffi_read_bytes!("key", key_ptr, key_len);
+ let key = ffi_unwrap!(
+ SymmetricKey::try_from_slice(key_bytes),
+ "error deserializing findex key",
+ ErrorCode::Serialization
+ );
+ trace!("Key successfully parsed");
+
+ let label_bytes = ffi_read_string!("label", label_ptr);
+ let label = Label::from(label_bytes.as_str());
+ trace!("Label successfully parsed: label: {label}");
+
+ let entry_url = if entry_url_ptr.is_null() {
+ String::new()
+ } else {
+ ffi_read_string!("REST server Entry Table URL", entry_url_ptr)
+ };
+
+ let chain_url = if chain_url_ptr.is_null() {
+ String::new()
+ } else {
+ ffi_read_string!("REST server Chain Table URL", chain_url_ptr)
+ };
+ let config = Configuration::Rest(reqwest::Client::new(), entry_url, chain_url);
+
+ let rt = ffi_unwrap!(
+ tokio::runtime::Runtime::new(),
+ "error creating Tokio runtime",
+ ErrorCode::Tokio
+ );
+ let findex = ffi_unwrap!(
+ rt.block_on(InstantiatedFindex::new(config)),
+ "error instantiating Findex with REST backend",
+ ErrorCode::Backend
+ );
+
+ let mut cache = FINDEX_INSTANCES
+ .lock()
+ .expect("Findex instance cache lock poisoned.");
+ let handle = ffi_unwrap!(
+ ::try_from(cache.len()),
+ "findex instance cache capacity overflow",
+ ErrorCode::Findex
+ );
+ cache.insert(handle, (key, label, findex));
+
+ *findex_handle = handle;
+
+ ErrorCode::Success.into()
+}
+
/// Instantiate a Findex using a Redis backend.
///
/// # Parameters
@@ -592,7 +667,7 @@ pub unsafe extern "C" fn h_delete(
/// indexes every night this is the number of days to wait before
/// being sure that a big portion of the indexes were checked
/// (see the coupon problem to understand why it's not 100% sure)
-
+///
/// # Safety
///
/// Cannot be safe since using FFI.
diff --git a/crates/findex/src/interfaces/python/api.rs b/crates/findex/src/interfaces/python/api.rs
index eadbdaaa..f65ab76b 100644
--- a/crates/findex/src/interfaces/python/api.rs
+++ b/crates/findex/src/interfaces/python/api.rs
@@ -104,7 +104,7 @@ impl Findex {
);
let instance = pyo3_unwrap!(
runtime.block_on(InstantiatedFindex::new(configuration)),
- "error instantiating Findex with Redis backend"
+ "error instantiating Findex with custom backend"
);
Ok(Self {
key: UserKey::try_from_bytes(key.0.to_bytes())
@@ -117,7 +117,7 @@ impl Findex {
/// Instantiates Findex with a REST backend.
#[staticmethod]
- pub fn new_with_rest_interface(
+ pub fn new_with_findex_cloud_interface(
label: String,
token: String,
entry_url: String,
@@ -134,12 +134,12 @@ impl Findex {
let key = UserKey::try_from_slice(&token.findex_key)
.expect("the bytes passed represent a correct key");
let instance = pyo3_unwrap!(
- runtime.block_on(InstantiatedFindex::new(Configuration::Rest(
+ runtime.block_on(InstantiatedFindex::new(Configuration::FindexCloud(
token,
entry_url.clone(),
chain_url.unwrap_or(entry_url)
))),
- "error instantiating Findex with Redis backend"
+ "error instantiating Findex with Findex Cloud backend"
);
Ok(Self {
key,
@@ -149,6 +149,37 @@ impl Findex {
})
}
+ /// Instantiates Findex with a REST backend.
+ #[staticmethod]
+ pub fn new_with_rest_interface(
+ key: &KeyPy,
+ label: String,
+ index_id: String,
+ entry_url: String,
+ chain_url: Option,
+ ) -> PyResult {
+ let runtime = pyo3_unwrap!(
+ tokio::runtime::Runtime::new(),
+ "error creating Tokio runtime"
+ );
+ let instance = pyo3_unwrap!(
+ runtime.block_on(InstantiatedFindex::new(Configuration::Rest(
+ reqwest::Client::new(),
+ entry_url.clone(),
+ chain_url.unwrap_or(entry_url),
+ index_id,
+ ))),
+ "error instantiating Findex with REST backend"
+ );
+ Ok(Self {
+ key: UserKey::try_from_bytes(key.0.to_bytes())
+ .expect("the bytes passed represent a correct key"),
+ label: Label::from(label.as_str()),
+ runtime,
+ instance,
+ })
+ }
+
/// Adds the given associations to the index.
///
/// Any subsequent search for such a keyword will result in finding (at
diff --git a/crates/findex/src/interfaces/wasm/api.rs b/crates/findex/src/interfaces/wasm/api.rs
index e81dbf29..88bc919f 100644
--- a/crates/findex/src/interfaces/wasm/api.rs
+++ b/crates/findex/src/interfaces/wasm/api.rs
@@ -45,15 +45,31 @@ impl WasmFindex {
.map_err(JsError::from)
}
- /// Instantiates a Findex object using REST interfaces, using the given token
- /// and URLs.
- pub async fn new_with_rest_interface(
+ /// Instantiates a Findex object using REST interfaces, using the given
+ /// token and URLs.
+ pub async fn new_with_findex_cloud_interface(
token: String,
entry_url: String,
chain_url: String,
) -> Result {
let config =
- Configuration::Rest(AuthorizationToken::from_str(&token)?, entry_url, chain_url);
+ Configuration::FindexCloud(AuthorizationToken::from_str(&token)?, entry_url, chain_url);
+
+ InstantiatedFindex::new(config)
+ .await
+ .map(Self)
+ .map_err(WasmError::from)
+ .map_err(JsError::from)
+ }
+
+ /// Instantiates a Findex object using REST interfaces, using the given
+ /// token and URLs.
+ pub async fn new_with_rest_interface(
+ entry_url: String,
+ chain_url: String,
+ index_id: String,
+ ) -> Result {
+ let config = Configuration::Rest(reqwest::Client::new(), entry_url, chain_url, index_id);
InstantiatedFindex::new(config)
.await
@@ -94,7 +110,7 @@ impl WasmFindex {
let res = ::try_from(res).map_err(|e| {
format!(
"Findex search: failed converting input of user interrupt into Js object: \
- {e:?}"
+ {e:?}"
)
})?;
let res = interrupt
@@ -103,13 +119,15 @@ impl WasmFindex {
let interruption_flag =
JsFuture::from(Promise::resolve(&res)).await.map_err(|e| {
format!(
- "Findex search: failed getting the promised results from user interrupt: {e:?}"
- )
+ "Findex search: failed getting the promised results from user \
+ interrupt: {e:?}"
+ )
})?;
interruption_flag.as_bool().ok_or_else(|| {
format!(
- "Findex search: user interrupt does not return a boolean value: {interrupt:?}"
- )
+ "Findex search: user interrupt does not return a boolean value: \
+ {interrupt:?}"
+ )
})
} else {
Ok(false)
@@ -221,15 +239,16 @@ impl WasmFindex {
})?);
let filtered_data = JsFuture::from(promise).await.map_err(|e| {
format!(
- "Findex compact: failed getting the promised results from the obsolete data \
- filter: {e:?}"
- )
+ "Findex compact: failed getting the promised results from the obsolete \
+ data filter: {e:?}"
+ )
})?;
let filtered_data = >::try_from(IndexedData::from(filtered_data))
.map_err(|e| {
format!(
- "Findex compact: failed converting Js array back to filtered data: {e:?}"
- )
+ "Findex compact: failed converting Js array back to filtered data: \
+ {e:?}"
+ )
})?;
Ok(filtered_data)
} else {
diff --git a/crates/findex/src/lib.rs b/crates/findex/src/lib.rs
index 1ec52914..20e924d3 100644
--- a/crates/findex/src/lib.rs
+++ b/crates/findex/src/lib.rs
@@ -6,6 +6,7 @@ pub mod db_interfaces;
feature = "ffi",
feature = "python",
feature = "redis-interface",
+ feature = "findex-cloud",
feature = "rest-interface",
feature = "sqlite-interface",
feature = "wasm",
@@ -25,8 +26,14 @@ pub mod ser_de;
feature = "ffi",
feature = "python",
feature = "redis-interface",
+ feature = "findex-cloud",
feature = "rest-interface",
feature = "sqlite-interface",
feature = "wasm",
))]
pub use instantiation::{Configuration, InstantiatedFindex};
+
+pub mod reexport {
+ pub use cosmian_crypto_core;
+ pub use cosmian_findex;
+}
diff --git a/crates/findex/src/ser_de/ffi_ser_de.rs b/crates/findex/src/ser_de/ffi_ser_de.rs
index 5fee5d06..9eac6c25 100644
--- a/crates/findex/src/ser_de/ffi_ser_de.rs
+++ b/crates/findex/src/ser_de/ffi_ser_de.rs
@@ -29,15 +29,16 @@ pub const fn get_serialized_edx_lines_size_bound(
pub fn get_upsert_output_size(
modifications: &HashMap, Keywords>,
) -> usize {
- // Since `h_add` (resp. `h_delete`) returns the set of keywords that have been inserted (resp.
- // deleted), caller MUST know in advance how much memory is needed before calling `h_add`
- // (resp. `h_delete`).
+ // Since `h_add` (resp. `h_delete`) returns the set of keywords that have been
+ // inserted (resp. deleted), caller MUST know in advance how much memory is
+ // needed before calling `h_add` (resp. `h_delete`).
//
- // In order to centralize into Rust the computation of the allocation size, 2 calls to
- // `h_upsert` are required:
+ // In order to centralize into Rust the computation of the allocation size, 2
+ // calls to `h_upsert` are required:
//
- // - the first call is made with `results_len` with a 0 value. No indexation at all is done. It
- // simply returns an upper bound estimation of the allocation needed store the results.
+ // - the first call is made with `results_len` with a 0 value. No indexation at
+ // all is done. It simply returns an upper bound estimation of the allocation
+ // needed store the results.
// - the second call takes this returned value for `results_len`
modifications
.values()
@@ -136,8 +137,9 @@ pub fn deserialize_edx_lines(
let mut items = Vec::with_capacity(length);
for _ in 0..length {
let key = Token::from(de.read_array()?);
- // TODO: since constant generics cannot be used as constant values, there is no way to use
- // `de.read_array<{ EncryptedValue::::LENGTH }>()` for now.
+ // TODO: since constant generics cannot be used as constant values, there is no
+ // way to use `de.read_array<{ EncryptedValue::::LENGTH
+ // }>()` for now.
let value = EncryptedValue::::try_from(de.read_vec()?.as_slice())?;
items.push((key, value));
}
diff --git a/crates/findex/src/ser_de/mod.rs b/crates/findex/src/ser_de/mod.rs
index 28893337..d4622266 100644
--- a/crates/findex/src/ser_de/mod.rs
+++ b/crates/findex/src/ser_de/mod.rs
@@ -61,7 +61,7 @@ impl From for SerializationError {
}
}
-#[cfg(any(feature = "ffi", feature = "rest-interface"))]
+#[cfg(any(feature = "ffi", feature = "findex-cloud", feature = "rest-interface"))]
pub mod ffi_ser_de;
#[cfg(feature = "wasm")]
pub mod wasm_ser_de;
diff --git a/crates/findex/src/ser_de/wasm_ser_de.rs b/crates/findex/src/ser_de/wasm_ser_de.rs
index 31499729..7043c222 100644
--- a/crates/findex/src/ser_de/wasm_ser_de.rs
+++ b/crates/findex/src/ser_de/wasm_ser_de.rs
@@ -124,6 +124,7 @@ pub fn edx_lines_to_js_array(
Ok(res)
}
+#[allow(dead_code)]
#[cfg(test)]
mod tests {
diff --git a/crates/fpe/src/core/alphabet.rs b/crates/fpe/src/core/alphabet.rs
index b9045255..8cceae49 100644
--- a/crates/fpe/src/core/alphabet.rs
+++ b/crates/fpe/src/core/alphabet.rs
@@ -128,7 +128,7 @@ impl Alphabet {
/// secure. The minimum length is calculated based on the number of
/// characters in the alphabet and recommended security thresholds.
#[must_use]
- pub fn minimum_plaintext_length(&self) -> usize {
+ pub const fn minimum_plaintext_length(&self) -> usize {
self.min_text_length
}
diff --git a/crates/fpe/src/core/integer.rs b/crates/fpe/src/core/integer.rs
index 45a862a3..f29e004e 100644
--- a/crates/fpe/src/core/integer.rs
+++ b/crates/fpe/src/core/integer.rs
@@ -267,7 +267,7 @@ impl Integer {
/// The number of digits of the max value
/// that is the same as the `radix^digits - 1`
#[must_use]
- pub fn digits(&self) -> usize {
+ pub const fn digits(&self) -> usize {
self.digits
}
}
diff --git a/crates/fpe/src/wasm_bindgen/mod.rs b/crates/fpe/src/wasm_bindgen/mod.rs
index 0139d6c7..51e81ee4 100644
--- a/crates/fpe/src/wasm_bindgen/mod.rs
+++ b/crates/fpe/src/wasm_bindgen/mod.rs
@@ -2,5 +2,6 @@ mod alphabet;
mod float;
mod integer;
+#[allow(dead_code)]
#[cfg(test)]
mod tests;