kvstore.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //! Key-Value Store Database traits and utilities
  2. //!
  3. //! This module provides shared KVStore functionality that can be used by both
  4. //! mint and wallet database implementations.
  5. use async_trait::async_trait;
  6. use super::{DbTransactionFinalizer, Error};
  7. /// Valid ASCII characters for namespace and key strings in KV store
  8. pub const KVSTORE_NAMESPACE_KEY_ALPHABET: &str =
  9. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
  10. /// Maximum length for namespace and key strings in KV store
  11. pub const KVSTORE_NAMESPACE_KEY_MAX_LEN: usize = 120;
  12. /// Validates that a string contains only valid KV store characters and is within length limits
  13. pub fn validate_kvstore_string(s: &str) -> Result<(), Error> {
  14. if s.len() > KVSTORE_NAMESPACE_KEY_MAX_LEN {
  15. return Err(Error::KVStoreInvalidKey(format!(
  16. "{KVSTORE_NAMESPACE_KEY_MAX_LEN} exceeds maximum length of key characters"
  17. )));
  18. }
  19. if !s
  20. .chars()
  21. .all(|c| KVSTORE_NAMESPACE_KEY_ALPHABET.contains(c))
  22. {
  23. return Err(Error::KVStoreInvalidKey("key contains invalid characters. Only ASCII letters, numbers, underscore, and hyphen are allowed".to_string()));
  24. }
  25. Ok(())
  26. }
  27. /// Validates namespace and key parameters for KV store operations
  28. pub fn validate_kvstore_params(
  29. primary_namespace: &str,
  30. secondary_namespace: &str,
  31. key: &str,
  32. ) -> Result<(), Error> {
  33. // Validate primary namespace
  34. validate_kvstore_string(primary_namespace)?;
  35. // Validate secondary namespace
  36. validate_kvstore_string(secondary_namespace)?;
  37. // Validate key
  38. validate_kvstore_string(key)?;
  39. // Check empty namespace rules
  40. if primary_namespace.is_empty() && !secondary_namespace.is_empty() {
  41. return Err(Error::KVStoreInvalidKey(
  42. "If primary_namespace is empty, secondary_namespace must also be empty".to_string(),
  43. ));
  44. }
  45. // Check for potential collisions between keys and namespaces in the same namespace
  46. let namespace_key = format!("{primary_namespace}/{secondary_namespace}");
  47. if key == primary_namespace || key == secondary_namespace || key == namespace_key {
  48. return Err(Error::KVStoreInvalidKey(format!(
  49. "Key '{key}' conflicts with namespace names"
  50. )));
  51. }
  52. Ok(())
  53. }
  54. /// Key-Value Store Transaction trait
  55. #[async_trait]
  56. pub trait KVStoreTransaction<'a, Error>: DbTransactionFinalizer<Err = Error> {
  57. /// Read value from key-value store
  58. async fn kv_read(
  59. &mut self,
  60. primary_namespace: &str,
  61. secondary_namespace: &str,
  62. key: &str,
  63. ) -> Result<Option<Vec<u8>>, Error>;
  64. /// Write value to key-value store
  65. async fn kv_write(
  66. &mut self,
  67. primary_namespace: &str,
  68. secondary_namespace: &str,
  69. key: &str,
  70. value: &[u8],
  71. ) -> Result<(), Error>;
  72. /// Remove value from key-value store
  73. async fn kv_remove(
  74. &mut self,
  75. primary_namespace: &str,
  76. secondary_namespace: &str,
  77. key: &str,
  78. ) -> Result<(), Error>;
  79. /// List keys in a namespace
  80. async fn kv_list(
  81. &mut self,
  82. primary_namespace: &str,
  83. secondary_namespace: &str,
  84. ) -> Result<Vec<String>, Error>;
  85. }
  86. /// Key-Value Store Database trait
  87. #[async_trait]
  88. pub trait KVStoreDatabase {
  89. /// KV Store Database Error
  90. type Err: Into<Error> + From<Error>;
  91. /// Read value from key-value store
  92. async fn kv_read(
  93. &self,
  94. primary_namespace: &str,
  95. secondary_namespace: &str,
  96. key: &str,
  97. ) -> Result<Option<Vec<u8>>, Self::Err>;
  98. /// List keys in a namespace
  99. async fn kv_list(
  100. &self,
  101. primary_namespace: &str,
  102. secondary_namespace: &str,
  103. ) -> Result<Vec<String>, Self::Err>;
  104. }
  105. /// Key-Value Store trait combining read operations with transaction support
  106. #[async_trait]
  107. pub trait KVStore: KVStoreDatabase {
  108. /// Begins a KV transaction
  109. async fn begin_transaction<'a>(
  110. &'a self,
  111. ) -> Result<Box<dyn KVStoreTransaction<'a, Self::Err> + Send + Sync + 'a>, Error>;
  112. }