v0.2.11-pre.007
This commit is contained in:
104
crates/ksp-offchain-transport-lib/src/market_price_registry.rs
Normal file
104
crates/ksp-offchain-transport-lib/src/market_price_registry.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
// file: crates/ksp-offchain-transport-lib/src/market_price_registry.rs
|
||||
// version: 1
|
||||
|
||||
//! Provider-neutral registry projection for configured market-price providers.
|
||||
|
||||
const MARKET_PRICE_PROVIDER_REGISTRY_MAX_ENTRIES: usize = 64;
|
||||
|
||||
/// Immutable provider descriptor plus its current generic runtime state.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
pub struct MarketPriceProviderRegistryEntry {
|
||||
descriptor: crate::MarketPriceProviderDescriptor,
|
||||
state: crate::MarketPriceProviderState,
|
||||
}
|
||||
|
||||
impl crate::MarketPriceProviderRegistryEntry {
|
||||
/// Returns the provider capability descriptor.
|
||||
#[must_use]
|
||||
pub const fn descriptor(&self) -> &crate::MarketPriceProviderDescriptor {
|
||||
return &self.descriptor;
|
||||
}
|
||||
|
||||
/// Returns the provider-neutral runtime state.
|
||||
#[must_use]
|
||||
pub const fn state(&self) -> &crate::MarketPriceProviderState {
|
||||
return &self.state;
|
||||
}
|
||||
|
||||
/// Creates one generic registry entry while keeping descriptor and state identity synchronized.
|
||||
#[must_use]
|
||||
pub fn new(descriptor: crate::MarketPriceProviderDescriptor, availability: crate::MarketPriceProviderAvailability) -> Self {
|
||||
let state = crate::MarketPriceProviderState::new(descriptor.id().clone(), availability);
|
||||
return Self { descriptor, state };
|
||||
}
|
||||
}
|
||||
|
||||
/// Deterministically ordered registry of configured market-price providers.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Serialize)]
|
||||
pub struct MarketPriceProviderRegistry {
|
||||
entries: std::vec::Vec<crate::MarketPriceProviderRegistryEntry>,
|
||||
}
|
||||
|
||||
impl crate::MarketPriceProviderRegistry {
|
||||
/// Returns a provider descriptor by opaque identifier.
|
||||
#[must_use]
|
||||
pub fn descriptor(&self, provider_id: &crate::MarketPriceProviderId) -> std::option::Option<&crate::MarketPriceProviderDescriptor> {
|
||||
return self.entry(provider_id).map(crate::MarketPriceProviderRegistryEntry::descriptor);
|
||||
}
|
||||
|
||||
/// Returns all configured provider entries in stable provider-id order.
|
||||
#[must_use]
|
||||
pub fn entries(&self) -> &[crate::MarketPriceProviderRegistryEntry] {
|
||||
return self.entries.as_slice();
|
||||
}
|
||||
|
||||
/// Returns one configured registry entry by opaque identifier.
|
||||
#[must_use]
|
||||
pub fn entry(&self, provider_id: &crate::MarketPriceProviderId) -> std::option::Option<&crate::MarketPriceProviderRegistryEntry> {
|
||||
let index = self.entries.binary_search_by(|entry| return entry.descriptor().id().cmp(provider_id));
|
||||
return match index {
|
||||
std::result::Result::Ok(value) => self.entries.get(value),
|
||||
std::result::Result::Err(_) => std::option::Option::None,
|
||||
};
|
||||
}
|
||||
|
||||
/// Reports whether no provider is currently registered.
|
||||
#[must_use]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
return self.entries.is_empty();
|
||||
}
|
||||
|
||||
/// Returns the configured provider count.
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
return self.entries.len();
|
||||
}
|
||||
|
||||
/// Returns one provider-neutral runtime state by opaque identifier.
|
||||
#[must_use]
|
||||
pub fn state(&self, provider_id: &crate::MarketPriceProviderId) -> std::option::Option<&crate::MarketPriceProviderState> {
|
||||
return self.entry(provider_id).map(crate::MarketPriceProviderRegistryEntry::state);
|
||||
}
|
||||
|
||||
/// Builds one bounded deterministic registry and rejects duplicate provider identifiers.
|
||||
pub fn new(mut entries: std::vec::Vec<crate::MarketPriceProviderRegistryEntry>) -> ksp_core_lib::Result<Self> {
|
||||
if entries.len() > MARKET_PRICE_PROVIDER_REGISTRY_MAX_ENTRIES {
|
||||
return std::result::Result::Err(registry_error("entry_count"));
|
||||
}
|
||||
entries.sort_by(|left, right| return left.descriptor().id().cmp(right.descriptor().id()));
|
||||
for index in 1..entries.len() {
|
||||
if entries[index - 1].descriptor().id() == entries[index].descriptor().id() {
|
||||
return std::result::Result::Err(registry_error("provider_id"));
|
||||
}
|
||||
}
|
||||
return std::result::Result::Ok(Self { entries });
|
||||
}
|
||||
}
|
||||
|
||||
fn registry_error(field: &'static str) -> ksp_core_lib::Error {
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_MARKET_PRICE_REGISTRY_INVALID, "Market-price provider registry is invalid").with_context("field", field);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "../unit_tests/market_price_registry.rs"]
|
||||
mod tests;
|
||||
Reference in New Issue
Block a user