Unverified Commit 94fad479 authored by Ryan Olson's avatar Ryan Olson Committed by GitHub
Browse files

feat: kvbm-logical (#6033)


Signed-off-by: default avatarRyan Olson <rolson@nvidia.com>
parent 0e55e821
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Attachment system for storing arbitrary typed data on registration handles.
use super::handle::BlockRegistrationHandle;
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::marker::PhantomData;
/// Error types for attachment operations
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AttachmentError {
/// Attempted to attach a type as unique when it's already registered as multiple
TypeAlreadyRegisteredAsMultiple(TypeId),
/// Attempted to attach a type as multiple when it's already registered as unique
TypeAlreadyRegisteredAsUnique(TypeId),
}
impl std::fmt::Display for AttachmentError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AttachmentError::TypeAlreadyRegisteredAsMultiple(type_id) => {
write!(
f,
"Type {:?} is already registered as multiple attachment",
type_id
)
}
AttachmentError::TypeAlreadyRegisteredAsUnique(type_id) => {
write!(
f,
"Type {:?} is already registered as unique attachment",
type_id
)
}
}
}
}
impl std::error::Error for AttachmentError {}
/// Tracks how a type is registered in the attachment system
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum AttachmentMode {
Unique,
Multiple,
}
/// Storage for attachments on a BlockRegistrationHandle
#[derive(Debug)]
pub(crate) struct AttachmentStore {
/// Unique attachments - only one value per TypeId
pub(super) unique_attachments: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
/// Multiple attachments - multiple values per TypeId
pub(super) multiple_attachments: HashMap<TypeId, Vec<Box<dyn Any + Send + Sync>>>,
/// Track which types are registered and how
pub(super) type_registry: HashMap<TypeId, AttachmentMode>,
/// Storage for weak block references - separate from generic attachments, keyed by TypeId
pub(crate) weak_blocks: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
/// Explicit presence tracking for Block<T, Registered> lifecycle
/// Key is TypeId::of::<T>() - indicates a Block<T, Registered> exists somewhere
pub(super) presence_markers: HashMap<TypeId, ()>,
}
impl AttachmentStore {
pub(super) fn new() -> Self {
Self {
unique_attachments: HashMap::new(),
multiple_attachments: HashMap::new(),
type_registry: HashMap::new(),
weak_blocks: HashMap::new(),
presence_markers: HashMap::new(),
}
}
}
/// Typed accessor for attachments of a specific type
pub struct TypedAttachments<'a, T> {
pub(super) handle: &'a BlockRegistrationHandle,
pub(super) _phantom: PhantomData<T>,
}
impl<'a, T: Any + Send + Sync> TypedAttachments<'a, T> {
/// Execute a closure with immutable access to the unique attachment of type T.
pub fn with_unique<R>(&self, f: impl FnOnce(&T) -> R) -> Option<R> {
let type_id = TypeId::of::<T>();
let attachments = self.handle.inner.attachments.lock();
attachments
.unique_attachments
.get(&type_id)?
.downcast_ref::<T>()
.map(f)
}
/// Execute a closure with mutable access to the unique attachment of type T.
pub fn with_unique_mut<R>(&self, f: impl FnOnce(&mut T) -> R) -> Option<R> {
let type_id = TypeId::of::<T>();
let mut attachments = self.handle.inner.attachments.lock();
attachments
.unique_attachments
.get_mut(&type_id)?
.downcast_mut::<T>()
.map(f)
}
/// Execute a closure with immutable access to multiple attachments of type T.
pub fn with_multiple<R>(&self, f: impl FnOnce(&[&T]) -> R) -> R {
let type_id = TypeId::of::<T>();
let attachments = self.handle.inner.attachments.lock();
let multiple_refs: Vec<&T> = attachments
.multiple_attachments
.get(&type_id)
.map(|vec| vec.iter().filter_map(|v| v.downcast_ref::<T>()).collect())
.unwrap_or_default();
f(&multiple_refs)
}
/// Execute a closure with mutable access to multiple attachments of type T.
pub fn with_multiple_mut<R>(&self, f: impl FnOnce(&mut [&mut T]) -> R) -> R {
let type_id = TypeId::of::<T>();
let mut attachments = self.handle.inner.attachments.lock();
let mut multiple_refs: Vec<&mut T> = attachments
.multiple_attachments
.get_mut(&type_id)
.map(|vec| {
vec.iter_mut()
.filter_map(|v| v.downcast_mut::<T>())
.collect()
})
.unwrap_or_default();
f(&mut multiple_refs)
}
/// Execute a closure with immutable access to both unique and multiple attachments of type T.
pub fn with_all<R>(&self, f: impl FnOnce(Option<&T>, &[&T]) -> R) -> R {
let type_id = TypeId::of::<T>();
let attachments = self.handle.inner.attachments.lock();
let unique = attachments
.unique_attachments
.get(&type_id)
.and_then(|v| v.downcast_ref::<T>());
let multiple_refs: Vec<&T> = attachments
.multiple_attachments
.get(&type_id)
.map(|vec| vec.iter().filter_map(|v| v.downcast_ref::<T>()).collect())
.unwrap_or_default();
f(unique, &multiple_refs)
}
/// Execute a closure with mutable access to both unique and multiple attachments of type T.
pub fn with_all_mut<R>(&self, f: impl FnOnce(Option<&mut T>, &mut [&mut T]) -> R) -> R {
let type_id = TypeId::of::<T>();
let mut attachments = self.handle.inner.attachments.lock();
match attachments.type_registry.get(&type_id) {
Some(AttachmentMode::Unique) => {
let unique = attachments
.unique_attachments
.get_mut(&type_id)
.and_then(|v| v.downcast_mut::<T>());
let mut empty_vec: Vec<&mut T> = Vec::new();
f(unique, &mut empty_vec)
}
Some(AttachmentMode::Multiple) => {
let mut multiple_refs: Vec<&mut T> = attachments
.multiple_attachments
.get_mut(&type_id)
.map(|vec| {
vec.iter_mut()
.filter_map(|v| v.downcast_mut::<T>())
.collect()
})
.unwrap_or_default();
f(None, &mut multiple_refs)
}
None => {
let mut empty_vec: Vec<&mut T> = Vec::new();
f(None, &mut empty_vec)
}
}
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Block registration handle and its inner implementation.
use super::attachments::{AttachmentError, AttachmentStore, TypedAttachments};
use super::{BlockRegistry, PositionalRadixTree};
use crate::blocks::{BlockMetadata, SequenceHash};
use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::sync::{Arc, Weak};
use parking_lot::Mutex;
/// Handle that represents a block registration in the global registry.
/// This handle is cloneable and can be shared across pools.
#[derive(Clone, Debug)]
pub struct BlockRegistrationHandle {
pub(crate) inner: Arc<BlockRegistrationHandleInner>,
}
/// Type alias for touch callback functions.
type TouchCallback = Arc<dyn Fn(SequenceHash) + Send + Sync>;
pub(crate) struct BlockRegistrationHandleInner {
/// Sequence hash of the block
seq_hash: SequenceHash,
/// Attachments for the block
pub(crate) attachments: Mutex<AttachmentStore>,
/// Callbacks invoked when this handle is touched
touch_callbacks: Mutex<Vec<TouchCallback>>,
/// Weak reference to the registry - allows us to remove the block from the registry on drop
registry: Weak<PositionalRadixTree<Weak<BlockRegistrationHandleInner>>>,
}
impl std::fmt::Debug for BlockRegistrationHandleInner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BlockRegistrationHandleInner")
.field("seq_hash", &self.seq_hash)
.field("attachments", &self.attachments)
.field(
"touch_callbacks",
&format!("[{} callbacks]", self.touch_callbacks.lock().len()),
)
.finish()
}
}
impl BlockRegistrationHandleInner {
pub(super) fn new(
seq_hash: SequenceHash,
registry: Weak<PositionalRadixTree<Weak<BlockRegistrationHandleInner>>>,
) -> Self {
Self {
seq_hash,
attachments: Mutex::new(AttachmentStore::new()),
touch_callbacks: Mutex::new(Vec::new()),
registry,
}
}
}
impl Drop for BlockRegistrationHandleInner {
#[inline]
fn drop(&mut self) {
if let Some(registry) = self.registry.upgrade()
&& registry
.prefix(&self.seq_hash)
.remove(&self.seq_hash)
.is_none()
{
tracing::warn!("Failed to remove block from registry: {:?}", self.seq_hash);
}
}
}
impl BlockRegistrationHandle {
pub(crate) fn from_inner(inner: Arc<BlockRegistrationHandleInner>) -> Self {
Self { inner }
}
pub fn seq_hash(&self) -> SequenceHash {
self.inner.seq_hash
}
pub fn is_from_registry(&self, registry: &BlockRegistry) -> bool {
self.inner
.registry
.upgrade()
.map(|reg| Arc::ptr_eq(&reg, &registry.prt))
.unwrap_or(false)
}
/// Mark that a Block<T, Registered> exists for this sequence hash.
/// Called when transitioning from Complete to Registered state.
pub(crate) fn mark_present<T: BlockMetadata>(&self) {
let type_id = TypeId::of::<T>();
let mut attachments = self.inner.attachments.lock();
attachments.presence_markers.insert(type_id, ());
}
/// Mark that Block<T, Registered> no longer exists for this sequence hash.
/// Called when transitioning from Registered to Reset state.
pub(crate) fn mark_absent<T: BlockMetadata>(&self) {
let type_id = TypeId::of::<T>();
let mut attachments = self.inner.attachments.lock();
attachments.presence_markers.remove(&type_id);
}
/// Check if a Block<T, Registered> currently exists for this sequence hash.
/// Returns true if block exists in active or inactive pool, false otherwise.
pub fn has_block<T: BlockMetadata>(&self) -> bool {
let type_id = TypeId::of::<T>();
let attachments = self.inner.attachments.lock();
attachments.presence_markers.contains_key(&type_id)
}
/// Check if a Block exists for any of the specified metadata types.
/// Returns true if a block exists for at least one of the types.
/// Acquires the lock only once for efficiency.
pub fn has_any_block(&self, type_ids: &[TypeId]) -> bool {
let attachments = self.inner.attachments.lock();
type_ids
.iter()
.any(|type_id| attachments.presence_markers.contains_key(type_id))
}
/// Register a callback to be invoked when this handle is touched.
pub fn on_touch(&self, callback: Arc<dyn Fn(SequenceHash) + Send + Sync>) {
self.inner.touch_callbacks.lock().push(callback);
}
/// Fire all registered touch callbacks with this handle's sequence hash.
pub fn touch(&self) {
let callbacks: Vec<_> = self.inner.touch_callbacks.lock().clone();
let seq_hash = self.inner.seq_hash;
for cb in &callbacks {
cb(seq_hash);
}
}
/// Get a typed accessor for attachments of type T
pub fn get<T: Any + Send + Sync>(&self) -> TypedAttachments<'_, T> {
TypedAttachments {
handle: self,
_phantom: PhantomData,
}
}
/// Attach a unique value of type T to this handle.
/// Only one value per type is allowed - subsequent calls will replace the previous value.
/// Returns an error if type T is already registered as multiple attachment.
pub fn attach_unique<T: Any + Send + Sync>(&self, value: T) -> Result<(), AttachmentError> {
let type_id = TypeId::of::<T>();
let mut attachments = self.inner.attachments.lock();
if let Some(super::attachments::AttachmentMode::Multiple) =
attachments.type_registry.get(&type_id)
{
return Err(AttachmentError::TypeAlreadyRegisteredAsMultiple(type_id));
}
attachments
.unique_attachments
.insert(type_id, Box::new(value));
attachments
.type_registry
.insert(type_id, super::attachments::AttachmentMode::Unique);
Ok(())
}
/// Attach a value of type T to this handle.
/// Multiple values per type are allowed - this will append to existing values.
/// Returns an error if type T is already registered as unique attachment.
pub fn attach<T: Any + Send + Sync>(&self, value: T) -> Result<(), AttachmentError> {
let type_id = TypeId::of::<T>();
let mut attachments = self.inner.attachments.lock();
if let Some(super::attachments::AttachmentMode::Unique) =
attachments.type_registry.get(&type_id)
{
return Err(AttachmentError::TypeAlreadyRegisteredAsUnique(type_id));
}
attachments
.multiple_attachments
.entry(type_id)
.or_default()
.push(Box::new(value));
attachments
.type_registry
.insert(type_id, super::attachments::AttachmentMode::Multiple);
Ok(())
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Global registry for block deduplication via weak references and sequence hash matching.
//!
//! The [`BlockRegistry`] is the central coordination point for block deduplication in the
//! KVBM system. It maps sequence hashes to registration handles using a
//! [`dynamo_tokens::PositionalRadixTree`], enabling efficient prefix-based lookups.
//!
//! # Architecture
//!
//! ```text
//! BlockRegistry
//! └── PositionalRadixTree<Weak<BlockRegistrationHandleInner>>
//! ├── seq_hash_1 → Handle → AttachmentStore (presence markers, weak refs, typed data)
//! ├── seq_hash_2 → Handle → AttachmentStore
//! └── ...
//! ```
//!
//! - **Handle**: One per sequence hash. Ties blocks across all pool tiers (active, inactive).
//! - **Attachments**: Arbitrary typed data stored on handles (unique or multiple per type).
//! - **Presence markers**: Track which `Block<T, Registered>` exist for a given handle.
//! - **Weak references**: Enable block resurrection during pool transitions.
//!
//! # Future directions
//!
//! - Delegate pattern to decouple EventsManager from BlockRegistry
//! - Cross-pool touch tracking
//! - RAII attachment guards
mod attachments;
mod handle;
mod registration;
#[cfg(test)]
pub(crate) mod tests;
// Re-export public types
pub use attachments::{AttachmentError, TypedAttachments};
pub use handle::BlockRegistrationHandle;
use crate::{events::EventsManager, tinylfu::FrequencyTracker};
use crate::blocks::SequenceHash;
use std::sync::{Arc, Weak};
use handle::BlockRegistrationHandleInner;
pub(crate) use crate::blocks::RegisteredReturnFn;
pub(crate) type PositionalRadixTree<V> = dynamo_tokens::PositionalRadixTree<V, SequenceHash>;
/// Builder for [`BlockRegistry`].
///
/// # Example
///
/// ```ignore
/// // Simple registry with no tracking
/// let registry = BlockRegistry::builder().build();
///
/// // With frequency tracking
/// let registry = BlockRegistry::builder()
/// .frequency_tracker(tracker)
/// .build();
///
/// // With both frequency tracking and event management
/// let registry = BlockRegistry::builder()
/// .frequency_tracker(tracker)
/// .event_manager(events_manager)
/// .build();
/// ```
#[derive(Default)]
pub struct BlockRegistryBuilder {
frequency_tracker: Option<Arc<dyn FrequencyTracker<u128>>>,
event_manager: Option<Arc<EventsManager>>,
}
impl BlockRegistryBuilder {
/// Creates a new builder with default settings.
pub fn new() -> Self {
Self::default()
}
/// Sets the frequency tracker for block access tracking.
pub fn frequency_tracker(mut self, tracker: Arc<dyn FrequencyTracker<u128>>) -> Self {
self.frequency_tracker = Some(tracker);
self
}
/// Sets the events manager for distributed coordination.
// TODO(delegate): Replace direct EventsManager coupling with a delegate/observer pattern.
pub fn event_manager(mut self, manager: Arc<EventsManager>) -> Self {
self.event_manager = Some(manager);
self
}
/// Builds the BlockRegistry.
pub fn build(self) -> BlockRegistry {
BlockRegistry {
frequency_tracker: self.frequency_tracker,
event_manager: self.event_manager,
prt: Arc::new(PositionalRadixTree::new()),
}
}
}
/// Global registry for managing block registrations.
/// Tracks canonical blocks and provides registration handles.
#[derive(Clone)]
pub struct BlockRegistry {
pub(crate) prt: Arc<PositionalRadixTree<Weak<BlockRegistrationHandleInner>>>,
frequency_tracker: Option<Arc<dyn FrequencyTracker<u128>>>,
// TODO(delegate): Replace direct EventsManager field with a delegate/observer trait.
event_manager: Option<Arc<EventsManager>>,
}
impl BlockRegistry {
/// Creates a new builder for BlockRegistry.
pub fn builder() -> BlockRegistryBuilder {
BlockRegistryBuilder::new()
}
/// Creates a new BlockRegistry with no tracking.
pub fn new() -> Self {
Self::builder().build()
}
pub fn has_frequency_tracking(&self) -> bool {
self.frequency_tracker.is_some()
}
pub fn touch(&self, seq_hash: SequenceHash) {
if let Some(tracker) = &self.frequency_tracker {
tracker.touch(seq_hash.as_u128());
}
}
pub fn count(&self, seq_hash: SequenceHash) -> u32 {
if let Some(tracker) = &self.frequency_tracker {
tracker.count(seq_hash.as_u128())
} else {
0
}
}
/// Check presence of sequence hashes for blocks with specific metadata type T.
/// Returns Vec<(SequenceHash, bool)> where bool indicates if a Block<T, Registered> exists.
///
/// This checks for existence in either active or inactive pools without acquiring ownership.
/// Does NOT trigger frequency tracking.
pub fn check_presence<T: crate::blocks::BlockMetadata>(
&self,
seq_hashes: &[SequenceHash],
) -> Vec<(SequenceHash, bool)> {
seq_hashes
.iter()
.map(|&seq_hash| {
let handle_result = self.match_sequence_hash(seq_hash, false);
let present = handle_result
.as_ref()
.map(|handle| handle.has_block::<T>())
.unwrap_or(false);
tracing::debug!(
?seq_hash,
type_name = std::any::type_name::<T>(),
handle_found = handle_result.is_some(),
present,
"check_presence result"
);
(seq_hash, present)
})
.collect()
}
/// Check presence of sequence hashes for blocks with any of the specified metadata types.
/// Returns Vec<(SequenceHash, bool)> where bool is true if the block exists in ANY of the specified pools.
///
/// Does NOT trigger frequency tracking.
pub fn check_presence_any(
&self,
seq_hashes: &[SequenceHash],
type_ids: &[std::any::TypeId],
) -> Vec<(SequenceHash, bool)> {
seq_hashes
.iter()
.map(|&seq_hash| {
let present = self
.match_sequence_hash(seq_hash, false)
.map(|handle| handle.has_any_block(type_ids))
.unwrap_or(false);
(seq_hash, present)
})
.collect()
}
/// Register a sequence hash and get a registration handle.
/// If the sequence is already registered, returns the existing handle.
/// Otherwise, creates a new canonical registration.
/// This method triggers frequency tracking.
// TODO(delegate): This is where `on_block_registered` is called. Future delegate
// pattern should replace the direct EventsManager call here.
#[inline]
pub fn register_sequence_hash(&self, seq_hash: SequenceHash) -> BlockRegistrationHandle {
let map = self.prt.prefix(&seq_hash);
let mut weak = map.entry(seq_hash).or_default();
if let Some(inner) = weak.upgrade() {
return BlockRegistrationHandle::from_inner(inner);
}
let inner = self.create_registration(seq_hash);
*weak = Arc::downgrade(&inner);
let handle = BlockRegistrationHandle::from_inner(inner);
if let Some(event_manager) = &self.event_manager
&& let Err(e) = event_manager.on_block_registered(&handle)
{
tracing::warn!("Failed to register block with event manager: {}", e);
}
self.touch(seq_hash);
handle
}
/// Internal method for transferring block registration without triggering frequency tracking.
/// Used when copying blocks between pools where we don't want to count the transfer as a new access.
#[allow(dead_code)]
pub(crate) fn transfer_registration(&self, seq_hash: SequenceHash) -> BlockRegistrationHandle {
let map = self.prt.prefix(&seq_hash);
let mut weak = map.entry(seq_hash).or_default();
match weak.upgrade() {
Some(inner) => BlockRegistrationHandle::from_inner(inner),
None => {
let inner = self.create_registration(seq_hash);
*weak = Arc::downgrade(&inner);
BlockRegistrationHandle::from_inner(inner)
}
}
}
fn create_registration(&self, seq_hash: SequenceHash) -> Arc<BlockRegistrationHandleInner> {
Arc::new(BlockRegistrationHandleInner::new(
seq_hash,
Arc::downgrade(&self.prt),
))
}
/// Match a sequence hash and return a registration handle.
/// This method triggers frequency tracking.
#[inline]
pub fn match_sequence_hash(
&self,
seq_hash: SequenceHash,
touch: bool,
) -> Option<BlockRegistrationHandle> {
let result = self
.prt
.prefix(&seq_hash)
.get(&seq_hash)
.and_then(|weak| weak.upgrade())
.map(BlockRegistrationHandle::from_inner);
if result.is_some() && touch {
self.touch(seq_hash);
}
result
}
/// Check if a sequence is currently registered (has a canonical handle).
#[inline]
pub fn is_registered(&self, seq_hash: SequenceHash) -> bool {
self.prt
.prefix(&seq_hash)
.get(&seq_hash)
.map(|weak| weak.strong_count() > 0)
.unwrap_or(false)
}
/// Get the current number of registered blocks.
pub fn registered_count(&self) -> usize {
self.prt.len()
}
/// Get the frequency tracker if frequency tracking is enabled.
pub fn frequency_tracker(&self) -> Option<Arc<dyn FrequencyTracker<u128>>> {
self.frequency_tracker.clone()
}
}
impl Default for BlockRegistry {
fn default() -> Self {
Self::new()
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Block registration logic: register_block, try_find_existing_block, try_get_block.
use super::RegisteredReturnFn;
use super::attachments::AttachmentStore;
use super::handle::BlockRegistrationHandle;
use crate::blocks::{
Block, BlockDuplicationPolicy, BlockMetadata, CompleteBlock, DuplicateBlock, PrimaryBlock,
RegisteredBlock, WeakBlockEntry,
state::{Registered, Reset, Staged},
};
use crate::metrics::BlockPoolMetrics;
use crate::pools::InactivePool;
use std::any::TypeId;
use std::sync::{Arc, Weak};
impl BlockRegistrationHandle {
pub(crate) fn register_block<T: BlockMetadata + Sync>(
&self,
mut block: CompleteBlock<T>,
duplication_policy: BlockDuplicationPolicy,
inactive_pool: &InactivePool<T>,
metrics: Option<&BlockPoolMetrics>,
) -> Arc<dyn RegisteredBlock<T>> {
assert_eq!(
block.sequence_hash(),
self.seq_hash(),
"Attempted to register block with different sequence hash"
);
let block_id = block.block_id();
let inner_block = block.block.take().unwrap();
let reset_return_fn = block.return_fn.clone();
register_block_inner(
self,
inner_block,
block_id,
reset_return_fn,
duplication_policy,
inactive_pool,
metrics,
)
}
#[inline]
pub(crate) fn try_get_block<T: BlockMetadata + Sync>(
&self,
pool_return_fn: RegisteredReturnFn<T>,
) -> Option<Arc<dyn RegisteredBlock<T>>> {
let type_id = TypeId::of::<Weak<Block<T, Registered>>>();
let attachments = self.inner.attachments.lock();
let weak_block = attachments
.weak_blocks
.get(&type_id)
.and_then(|weak_any| weak_any.downcast_ref::<WeakBlockEntry<T>>())?;
if let Some(primary_arc) = weak_block.primary_block.upgrade() {
drop(attachments);
return Some(primary_arc as Arc<dyn RegisteredBlock<T>>);
}
if let Some(raw_arc) = weak_block.raw_block.upgrade() {
drop(attachments);
let primary_arc = PrimaryBlock::new_attached(raw_arc, pool_return_fn);
return Some(primary_arc as Arc<dyn RegisteredBlock<T>>);
}
None
}
}
/// Core registration logic for register_block.
fn register_block_inner<T: BlockMetadata + Sync>(
handle: &BlockRegistrationHandle,
block: Block<T, Staged>,
block_id: crate::BlockId,
reset_return_fn: Arc<dyn Fn(Block<T, Reset>) + Send + Sync>,
duplication_policy: BlockDuplicationPolicy,
inactive_pool: &InactivePool<T>,
metrics: Option<&BlockPoolMetrics>,
) -> Arc<dyn RegisteredBlock<T>> {
let pool_return_fn = inactive_pool.return_fn();
// CRITICAL: Check for existing blocks BEFORE registering.
// register()/register_with_handle() calls mark_present::<T>() which would make
// has_block::<T>() always return true.
let attachments = handle.inner.attachments.lock();
// Check for existing block (handles race condition with retry loop)
if let Some(existing_primary) = try_find_existing_block(handle, inactive_pool, &attachments) {
// Check if same block_id (shouldn't happen)
if existing_primary.block_id() == block_id {
panic!("Attempted to register block with same block_id as existing");
}
// Handle duplicate based on policy
match duplication_policy {
BlockDuplicationPolicy::Allow => {
if let Some(m) = metrics {
m.inc_duplicate_blocks();
}
drop(attachments);
PrimaryBlock::store_weak_refs(&existing_primary);
let registered_block = block.register_with_handle(handle.clone());
let duplicate =
DuplicateBlock::new(registered_block, existing_primary, reset_return_fn);
return Arc::new(duplicate);
}
BlockDuplicationPolicy::Reject => {
if let Some(m) = metrics {
m.inc_registration_dedup();
}
drop(attachments);
PrimaryBlock::store_weak_refs(&existing_primary);
reset_return_fn(block.reset());
return existing_primary as Arc<dyn RegisteredBlock<T>>;
}
}
}
// No existing block - register and create new primary
drop(attachments);
let registered_block = block.register_with_handle(handle.clone());
let primary_arc = PrimaryBlock::new_attached(Arc::new(registered_block), pool_return_fn);
primary_arc as Arc<dyn RegisteredBlock<T>>
}
/// Try to find an existing block with the same sequence hash.
/// Handles race conditions where block may be transitioning between pools.
fn try_find_existing_block<T: BlockMetadata + Sync>(
handle: &BlockRegistrationHandle,
inactive_pool: &InactivePool<T>,
attachments: &AttachmentStore,
) -> Option<Arc<PrimaryBlock<T>>> {
let type_id = TypeId::of::<Weak<Block<T, Registered>>>();
const MAX_RETRIES: usize = 100;
let mut retry_count = 0;
loop {
// Check presence first
if !attachments
.presence_markers
.contains_key(&TypeId::of::<T>())
{
tracing::debug!(
seq_hash = %handle.seq_hash(),
"try_find_existing_block: no presence marker, returning None"
);
return None;
}
// Try active pool (weak reference)
if let Some(weak_any) = attachments.weak_blocks.get(&type_id)
&& let Some(weak_block) = weak_any.downcast_ref::<WeakBlockEntry<T>>()
&& let Some(existing_primary) = weak_block.primary_block.upgrade()
{
tracing::debug!(
seq_hash = %handle.seq_hash(),
block_id = existing_primary.block_id(),
"try_find_existing_block: found in active pool"
);
return Some(existing_primary);
}
// Try inactive pool - this acquires the inactive pool lock.
// find_block_as_primary uses new_unattached because we hold the attachments lock.
// The caller (register_block_inner) calls store_weak_refs after dropping the lock.
if let Some(promoted) = inactive_pool.find_block_as_primary(handle.seq_hash(), false) {
tracing::debug!(
seq_hash = %handle.seq_hash(),
block_id = promoted.block_id(),
"try_find_existing_block: found in inactive pool, promoted"
);
return Some(promoted);
}
// Block is present but not found in either pool - it's transitioning.
retry_count += 1;
if retry_count >= MAX_RETRIES {
tracing::warn!(
seq_hash = %handle.seq_hash(),
retries = retry_count,
"try_find_existing_block: max retries exceeded, presence marker set but block not found in either pool"
);
return None;
}
// Brief yield to allow other thread to complete transition
std::hint::spin_loop();
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use crate::{BlockId, KvbmSequenceHashProvider, tinylfu::TinyLFUTracker};
use super::attachments::AttachmentError;
use super::*;
use crate::blocks::{
Block, BlockMetadata, CompleteBlock, PrimaryBlock, RegisteredBlock,
state::{Registered, Staged},
};
use crate::pools::InactivePool;
use crate::testing::{
self, MetadataA, MetadataB, MetadataC, TestMeta, TestPoolSetupBuilder, create_staged_block,
};
use std::any::TypeId;
use std::sync::Arc;
// Type aliases for backward compatibility with existing tests
type TestMetadata = TestMeta;
/// Wrapper for create_staged_block with original (tokens, block_id) arg order for fifo.rs
/// The original create_completed_block had args (tokens, block_id) but create_staged_block
/// uses (block_id, tokens), so we provide a wrapper function.
pub fn create_completed_block<T: BlockMetadata + std::fmt::Debug>(
tokens: &[u32],
block_id: BlockId,
) -> Block<T, Staged> {
create_staged_block::<T>(block_id, tokens)
}
/// Helper to create a token block for testing (local wrapper with auto block_size)
fn create_test_token_block(tokens: &[u32]) -> dynamo_tokens::TokenBlock {
testing::create_test_token_block(tokens, tokens.len() as u32)
}
/// Helper to create and register a block with specific metadata type
fn register_test_block<T: BlockMetadata + std::fmt::Debug>(
registry: &BlockRegistry,
block_id: BlockId,
tokens: &[u32],
) -> Block<T, Registered> {
let staged = create_staged_block::<T>(block_id, tokens);
let handle = registry.register_sequence_hash(staged.sequence_hash());
staged.register_with_handle(handle)
}
#[test]
fn test_type_tracking_enforcement() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
// Test: attach unique first, then try multiple (should fail)
handle
.attach_unique("unique_publisher".to_string())
.unwrap();
let result = handle.attach("listener1".to_string());
assert_eq!(
result,
Err(AttachmentError::TypeAlreadyRegisteredAsUnique(
TypeId::of::<String>()
))
);
// Test with different types: attach multiple first, then try unique (should fail)
handle.attach(42i32).unwrap();
handle.attach(43i32).unwrap();
let result = handle.attach_unique(44i32);
assert_eq!(
result,
Err(AttachmentError::TypeAlreadyRegisteredAsMultiple(
TypeId::of::<i32>()
))
);
}
#[test]
fn test_different_types_usage() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
// Define some test types for better demonstration
#[derive(Debug, Clone, PartialEq)]
struct EventPublisher(String);
#[derive(Debug, Clone, PartialEq)]
struct EventListener(String);
// Attach unique EventPublisher
handle
.attach_unique(EventPublisher("main_publisher".to_string()))
.unwrap();
// Attach multiple EventListeners
handle
.attach(EventListener("listener1".to_string()))
.unwrap();
handle
.attach(EventListener("listener2".to_string()))
.unwrap();
// Retrieve by type using new API
let publisher = handle.get::<EventPublisher>().with_unique(|p| p.clone());
assert_eq!(
publisher,
Some(EventPublisher("main_publisher".to_string()))
);
let listeners = handle
.get::<EventListener>()
.with_multiple(|listeners| listeners.iter().map(|l| (*l).clone()).collect::<Vec<_>>());
assert_eq!(listeners.len(), 2);
assert!(listeners.contains(&EventListener("listener1".to_string())));
assert!(listeners.contains(&EventListener("listener2".to_string())));
// Test with_all for EventListener (should have no unique, only multiple)
handle.get::<EventListener>().with_all(|unique, multiple| {
assert_eq!(unique, None);
assert_eq!(multiple.len(), 2);
});
// Attempting to register EventPublisher as multiple should fail
let result = handle.attach(EventPublisher("another_publisher".to_string()));
assert_eq!(
result,
Err(AttachmentError::TypeAlreadyRegisteredAsUnique(
TypeId::of::<EventPublisher>()
))
);
// Attempting to register EventListener as unique should fail
let result = handle.attach_unique(EventListener("unique_listener".to_string()));
assert_eq!(
result,
Err(AttachmentError::TypeAlreadyRegisteredAsMultiple(
TypeId::of::<EventListener>()
))
);
}
#[test]
fn test_frequency_tracking() {
let tracker = Arc::new(TinyLFUTracker::new(100));
let registry = BlockRegistry::builder()
.frequency_tracker(tracker.clone())
.build();
let block_1 = create_test_token_block(&[1, 2, 3, 4]);
let seq_hash_1 = block_1.kvbm_sequence_hash();
assert!(registry.has_frequency_tracking());
assert_eq!(registry.count(seq_hash_1), 0);
registry.touch(seq_hash_1);
assert_eq!(registry.count(seq_hash_1), 1);
registry.touch(seq_hash_1);
registry.touch(seq_hash_1);
assert_eq!(registry.count(seq_hash_1), 3);
let block_2 = create_test_token_block(&[5, 6, 7, 8]);
let seq_hash_2 = block_2.kvbm_sequence_hash();
let _handle1 = registry.register_sequence_hash(seq_hash_2);
assert_eq!(registry.count(seq_hash_2), 1);
let _handle2 = registry.match_sequence_hash(seq_hash_2, true);
assert_eq!(registry.count(seq_hash_2), 2);
let _handle3 = registry.match_sequence_hash(seq_hash_2, false);
assert_eq!(registry.count(seq_hash_2), 2);
}
#[test]
fn test_transfer_registration_no_tracking() {
let tracker = Arc::new(TinyLFUTracker::new(100));
let registry = BlockRegistry::builder()
.frequency_tracker(tracker.clone())
.build();
let seq_hash_1 = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let seq_hash_2 = create_test_token_block(&[5, 6, 7, 8]).kvbm_sequence_hash();
let _handle1 = registry.transfer_registration(seq_hash_1);
assert_eq!(registry.count(seq_hash_1), 0);
let _handle2 = registry.register_sequence_hash(seq_hash_2);
assert_eq!(registry.count(seq_hash_2), 1);
}
#[test]
fn test_presence_tracking_lifecycle() {
let registry = BlockRegistry::new();
let complete_block = create_completed_block::<TestMetadata>(&[1, 2, 3, 4], 42);
let handle = registry.register_sequence_hash(complete_block.sequence_hash());
// Initially, no block is present
assert!(!handle.has_block::<TestMetadata>());
// Register a block - this should mark it as present
let registered_block = complete_block.register_with_handle(handle.clone());
// Now the block should be present
assert!(handle.has_block::<TestMetadata>());
// Reset the block - this should mark it as absent
let _reset_block = registered_block.reset();
// Now the block should not be present
assert!(!handle.has_block::<TestMetadata>());
}
#[test]
fn test_presence_tracking_different_types() {
let registry = BlockRegistry::new();
let complete_block = create_completed_block::<TestMetadata>(&[100, 101, 102, 103], 42);
let handle = registry.register_sequence_hash(complete_block.sequence_hash());
// Register a block with MetadataA
let _registered_a = register_test_block::<MetadataA>(&registry, 42, &[100, 101, 102, 103]);
// MetadataA should be present, but not MetadataB
assert!(handle.has_block::<MetadataA>());
assert!(!handle.has_block::<MetadataB>());
// Now register a block with MetadataB (same seq_hash, different type)
let _registered_b = register_test_block::<MetadataB>(&registry, 42, &[100, 101, 102, 103]);
// Both should be present now
assert!(handle.has_block::<MetadataA>());
assert!(handle.has_block::<MetadataB>());
}
#[test]
fn test_check_presence_api() {
let registry = BlockRegistry::new();
// Register blocks for hashes 100 and 300, but not 200
let block_100 = register_test_block::<TestMetadata>(&registry, 100, &[0, 1, 2, 3]);
let block_200 = create_completed_block::<TestMetadata>(&[10, 11, 12, 13], 200);
let block_300 = register_test_block::<TestMetadata>(&registry, 300, &[20, 21, 22, 23]);
let hashes = vec![
block_100.sequence_hash(),
block_200.sequence_hash(),
block_300.sequence_hash(),
];
// Check presence using the API
let presence = registry.check_presence::<TestMetadata>(&hashes);
assert_eq!(presence.len(), 3);
assert_eq!(presence[0], (block_100.sequence_hash(), true));
assert_eq!(presence[1], (block_200.sequence_hash(), false));
assert_eq!(presence[2], (block_300.sequence_hash(), true));
}
#[test]
fn test_has_any_block() {
let registry = BlockRegistry::new();
let complete_block = create_completed_block::<MetadataB>(&[1, 2, 3, 4], 42);
let handle = registry.register_sequence_hash(complete_block.sequence_hash());
// No blocks initially
let type_ids = [TypeId::of::<MetadataA>(), TypeId::of::<MetadataB>()];
assert!(!handle.has_any_block(&type_ids));
// Register a block with MetadataB
let _registered = complete_block.register_with_handle(handle.clone());
// Now should return true because MetadataB is present
assert!(handle.has_any_block(&type_ids));
// Check with different types (neither A nor C is present)
let other_type_ids = [TypeId::of::<MetadataA>(), TypeId::of::<MetadataC>()];
assert!(!handle.has_any_block(&other_type_ids));
// Check with just MetadataB
let b_only = [TypeId::of::<MetadataB>()];
assert!(handle.has_any_block(&b_only));
}
#[test]
fn test_check_presence_any() {
let registry = BlockRegistry::new();
// Create three blocks:
// hash 100: has MetadataA
// hash 200: has MetadataB
// hash 300: has neither
let block_a = register_test_block::<MetadataA>(&registry, 100, &[10, 11, 12, 13]);
let block_b = create_completed_block::<MetadataA>(&[1, 2, 3, 4], 200);
let block_c = register_test_block::<MetadataB>(&registry, 300, &[20, 21, 22, 23]);
let hashes = vec![
block_a.sequence_hash(),
block_b.sequence_hash(),
block_c.sequence_hash(),
];
// Check presence with both types
let type_ids = [TypeId::of::<MetadataA>(), TypeId::of::<MetadataB>()];
let presence = registry.check_presence_any(&hashes, &type_ids);
assert_eq!(presence.len(), 3);
assert_eq!(presence[0], (block_a.sequence_hash(), true));
assert_eq!(presence[1], (block_b.sequence_hash(), false));
assert_eq!(presence[2], (block_c.sequence_hash(), true));
// Check with only MetadataA
let a_only = [TypeId::of::<MetadataA>()];
let a_presence = registry.check_presence_any(&hashes, &a_only);
assert_eq!(a_presence[0], (block_a.sequence_hash(), true));
assert_eq!(a_presence[1], (block_b.sequence_hash(), false));
assert_eq!(a_presence[2], (block_c.sequence_hash(), false));
}
#[test]
fn test_handle_drop_removes_registration() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
{
let _handle = registry.register_sequence_hash(seq_hash);
assert!(registry.is_registered(seq_hash));
assert_eq!(registry.registered_count(), 1);
}
// Handle should be dropped and registration removed
assert!(!registry.is_registered(seq_hash));
assert_eq!(registry.registered_count(), 0);
}
#[test]
fn test_multiple_handles_same_sequence() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let handle1 = registry.register_sequence_hash(seq_hash);
let handle2 = handle1.clone();
drop(handle1);
// Sequence should still be registered because handle2 exists
assert!(registry.is_registered(seq_hash));
assert_eq!(registry.registered_count(), 1);
drop(handle2);
// Now sequence should be unregistered
assert!(!registry.is_registered(seq_hash));
assert_eq!(registry.registered_count(), 0);
}
#[test]
fn test_mutable_access() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
#[derive(Debug, Clone, PartialEq)]
struct UniqueCounter(i32);
#[derive(Debug, Clone, PartialEq)]
struct MultipleCounter(i32);
impl UniqueCounter {
fn increment(&mut self) {
self.0 += 1;
}
}
impl MultipleCounter {
fn increment(&mut self) {
self.0 += 1;
}
}
// Test unique mutable access
handle.attach_unique(UniqueCounter(0)).unwrap();
handle.get::<UniqueCounter>().with_unique_mut(|counter| {
counter.increment();
counter.increment();
});
// Verify the change
let value = handle
.get::<UniqueCounter>()
.with_unique(|counter| counter.0);
assert_eq!(value, Some(2));
// Test mutable access to multiple (different type)
handle.attach(MultipleCounter(10)).unwrap();
handle.attach(MultipleCounter(20)).unwrap();
handle
.get::<MultipleCounter>()
.with_multiple_mut(|counters| {
for counter in counters {
counter.increment();
}
});
// Verify multiple were modified
let total = handle
.get::<MultipleCounter>()
.with_multiple(|counters| counters.iter().map(|c| c.0).sum::<i32>());
assert_eq!(total, 32); // 11 + 21
}
#[test]
fn test_with_all_mut_unique() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
#[derive(Debug, Clone, PartialEq)]
struct UniqueValue(i32);
impl UniqueValue {
fn increment(&mut self) {
self.0 += 1;
}
}
// Attach unique value
handle.attach_unique(UniqueValue(10)).unwrap();
// Test with_all_mut for unique type
handle
.get::<UniqueValue>()
.with_all_mut(|unique, multiple| {
assert!(unique.is_some());
assert_eq!(multiple.len(), 0);
if let Some(val) = unique {
val.increment();
}
});
// Verify the change
let value = handle.get::<UniqueValue>().with_unique(|v| v.0);
assert_eq!(value, Some(11));
}
#[test]
fn test_with_all_mut_multiple() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
#[derive(Debug, Clone, PartialEq)]
struct MultipleValue(i32);
impl MultipleValue {
fn increment(&mut self) {
self.0 += 1;
}
}
// Attach multiple values
handle.attach(MultipleValue(1)).unwrap();
handle.attach(MultipleValue(2)).unwrap();
// Test with_all_mut for multiple type
handle
.get::<MultipleValue>()
.with_all_mut(|unique, multiple| {
assert!(unique.is_none());
assert_eq!(multiple.len(), 2);
for val in multiple {
val.increment();
}
});
// Verify the changes
let total = handle
.get::<MultipleValue>()
.with_multiple(|values| values.iter().map(|v| v.0).sum::<i32>());
assert_eq!(total, 5); // 2 + 3
}
#[test]
fn test_concurrent_try_get_block_and_drop() {
use crate::pools::backends::{FifoReusePolicy, HashMapBackend};
use crate::pools::*;
use std::sync::Barrier;
use std::thread;
let registry = BlockRegistry::new();
let tokens = vec![1u32, 2, 3, 4];
let token_block = create_test_token_block(&tokens);
let seq_hash = token_block.kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
let reset_blocks: Vec<_> = (0..10).map(|i| Block::new(i, 4)).collect();
let reset_pool = ResetPool::new(reset_blocks, 4, None);
let reuse_policy = Box::new(FifoReusePolicy::new());
let backend = Box::new(HashMapBackend::new(reuse_policy));
let registered_pool = InactivePool::new(backend, &reset_pool, None);
// Create barriers for synchronization
let barrier1 = Arc::new(Barrier::new(2));
let barrier2 = Arc::new(Barrier::new(2));
let barrier1_clone = barrier1.clone();
let barrier2_clone = barrier2.clone();
// Create custom return function that holds the Arc at barriers
let registered_pool_clone = registered_pool.clone();
let pool_return_fn = Arc::new(move |block: Arc<Block<TestMetadata, Registered>>| {
barrier1_clone.wait();
barrier2_clone.wait();
(registered_pool_clone.return_fn())(block);
}) as Arc<dyn Fn(Arc<Block<TestMetadata, Registered>>) + Send + Sync>;
let complete_block = Block::<TestMetadata, _>::new(0, 4).stage(seq_hash);
let registered_block = complete_block.register_with_handle(handle.clone());
let primary_arc = PrimaryBlock::new_attached(Arc::new(registered_block), pool_return_fn);
let immutable_block = primary_arc as Arc<dyn RegisteredBlock<TestMetadata>>;
let handle_clone = handle.clone();
let real_return_fn = registered_pool.return_fn();
let registered_pool_clone2 = registered_pool.clone();
let upgrade_thread = thread::spawn(move || {
barrier1.wait();
let result = handle_clone.try_get_block::<TestMetadata>(real_return_fn);
barrier2.wait();
result
});
let drop_thread = thread::spawn(move || {
drop(immutable_block);
});
let upgraded_block = upgrade_thread.join().unwrap();
drop_thread.join().unwrap();
assert!(
upgraded_block.is_some(),
"Should successfully upgrade the weak reference to Arc<Block<T, Registered>>"
);
let _held_block = upgraded_block;
assert_eq!(
registered_pool_clone2.len(),
0,
"Block should not be in inactive pool because Arc refcount was >= 2"
);
}
/// Test helper to create an inactive pool with test infrastructure
fn create_test_inactive_pool() -> (
crate::pools::ResetPool<TestMetadata>,
InactivePool<TestMetadata>,
) {
let setup = TestPoolSetupBuilder::default().build().unwrap();
let (inactive_pool, reset_pool) = setup.build_pools::<TestMetadata>();
(reset_pool, inactive_pool)
}
#[test]
fn test_attach_block_ref_called_on_inactive_promotion_allow_policy() {
use crate::pools::*;
let registry = BlockRegistry::new();
let (reset_pool, inactive_pool) = create_test_inactive_pool();
let tokens = vec![1u32, 2, 3, 4];
let token_block = create_test_token_block(&tokens);
let seq_hash = token_block.kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
let complete_block1 = Block::<TestMetadata, _>::new(100, 4)
.complete(&token_block)
.expect("Block size should match");
let complete_block1 = CompleteBlock::new(complete_block1, reset_pool.return_fn());
let registered1 = handle.register_block(
complete_block1,
BlockDuplicationPolicy::Allow,
&inactive_pool,
None,
);
drop(registered1);
assert!(
inactive_pool.has_block(seq_hash),
"Block should be in inactive pool after drop"
);
let before_result = handle.try_get_block::<TestMetadata>(inactive_pool.return_fn());
assert!(
before_result.is_none(),
"try_get_block should return None before re-promotion (weak ref expired)"
);
let complete_block2 = Block::<TestMetadata, _>::new(200, 4)
.complete(&token_block)
.expect("Block size should match");
let complete_block2 = CompleteBlock::new(complete_block2, reset_pool.return_fn());
let registered2 = handle.register_block(
complete_block2,
BlockDuplicationPolicy::Allow,
&inactive_pool,
None,
);
let after_result = handle.try_get_block::<TestMetadata>(inactive_pool.return_fn());
assert!(
after_result.is_some(),
"try_get_block should succeed after promotion - attach_block_ref must have been called"
);
drop(registered2);
drop(after_result);
}
#[test]
fn test_attach_block_ref_called_on_inactive_promotion_reject_policy() {
use crate::pools::*;
let registry = BlockRegistry::new();
let (reset_pool, inactive_pool) = create_test_inactive_pool();
let tokens = vec![5u32, 6, 7, 8];
let token_block = create_test_token_block(&tokens);
let seq_hash = token_block.kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
let complete_block1 = Block::<TestMetadata, _>::new(100, 4)
.complete(&token_block)
.expect("Block size should match");
let complete_block1 = CompleteBlock::new(complete_block1, reset_pool.return_fn());
let registered1 = handle.register_block(
complete_block1,
BlockDuplicationPolicy::Reject,
&inactive_pool,
None,
);
drop(registered1);
assert!(inactive_pool.has_block(seq_hash));
let before_result = handle.try_get_block::<TestMetadata>(inactive_pool.return_fn());
assert!(before_result.is_none());
let complete_block2 = Block::<TestMetadata, _>::new(200, 4)
.complete(&token_block)
.expect("Block size should match");
let complete_block2 = CompleteBlock::new(complete_block2, reset_pool.return_fn());
let registered2 = handle.register_block(
complete_block2,
BlockDuplicationPolicy::Reject,
&inactive_pool,
None,
);
let after_result = handle.try_get_block::<TestMetadata>(inactive_pool.return_fn());
assert!(
after_result.is_some(),
"try_get_block should succeed after Reject policy promotion"
);
drop(registered2);
drop(after_result);
}
#[test]
fn test_touch_callback_fires() {
use std::sync::atomic::{AtomicU32, Ordering};
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[1, 2, 3, 4]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
let counter = Arc::new(AtomicU32::new(0));
let counter_clone = counter.clone();
handle.on_touch(Arc::new(move |hash| {
assert_eq!(hash, seq_hash);
counter_clone.fetch_add(1, Ordering::Relaxed);
}));
handle.touch();
assert_eq!(counter.load(Ordering::Relaxed), 1);
handle.touch();
handle.touch();
assert_eq!(counter.load(Ordering::Relaxed), 3);
}
#[test]
fn test_touch_multiple_callbacks() {
use std::sync::atomic::{AtomicU32, Ordering};
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[5, 6, 7, 8]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
let counter_a = Arc::new(AtomicU32::new(0));
let counter_b = Arc::new(AtomicU32::new(0));
let ca = counter_a.clone();
let cb = counter_b.clone();
handle.on_touch(Arc::new(move |_| {
ca.fetch_add(1, Ordering::Relaxed);
}));
handle.on_touch(Arc::new(move |_| {
cb.fetch_add(10, Ordering::Relaxed);
}));
handle.touch();
assert_eq!(counter_a.load(Ordering::Relaxed), 1);
assert_eq!(counter_b.load(Ordering::Relaxed), 10);
}
#[test]
fn test_touch_no_callbacks_is_noop() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[9, 10, 11, 12]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
// Should not panic or fail
handle.touch();
}
#[test]
fn test_touch_callback_receives_correct_hash() {
use parking_lot::Mutex;
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[13, 14, 15, 16]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
let received_hash = Arc::new(Mutex::new(None));
let rh = received_hash.clone();
handle.on_touch(Arc::new(move |hash| {
*rh.lock() = Some(hash);
}));
handle.touch();
assert_eq!(*received_hash.lock(), Some(seq_hash));
}
#[test]
fn test_with_all_mut_no_attachments() {
let registry = BlockRegistry::new();
let seq_hash = create_test_token_block(&[50, 51, 52, 53]).kvbm_sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
#[derive(Debug, Clone)]
#[allow(dead_code)]
struct UnusedType(i32);
// Call with_all_mut without attaching anything — exercises the None arm
let result = handle.get::<UnusedType>().with_all_mut(|unique, multiple| {
assert!(unique.is_none());
assert_eq!(multiple.len(), 0);
42
});
assert_eq!(result, 42);
}
#[test]
fn test_attachment_error_display() {
let err_multiple = AttachmentError::TypeAlreadyRegisteredAsMultiple(TypeId::of::<String>());
let display = format!("{}", err_multiple);
assert!(
display.contains("already registered as multiple"),
"Display should describe multiple registration: {}",
display
);
let err_unique = AttachmentError::TypeAlreadyRegisteredAsUnique(TypeId::of::<i32>());
let display = format!("{}", err_unique);
assert!(
display.contains("already registered as unique"),
"Display should describe unique registration: {}",
display
);
}
#[test]
fn test_is_from_registry() {
let registry1 = BlockRegistry::new();
let registry2 = BlockRegistry::new();
let seq_hash = create_test_token_block(&[60, 61, 62, 63]).kvbm_sequence_hash();
let handle = registry1.register_sequence_hash(seq_hash);
assert!(
handle.is_from_registry(&registry1),
"Handle should be from registry1"
);
assert!(
!handle.is_from_registry(&registry2),
"Handle should NOT be from registry2"
);
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Block lifecycle helpers and TestBlockBuilder for tests.
use super::config::DEFAULT_TEST_BLOCK_SIZE;
use crate::BlockId;
use crate::blocks::{
Block, BlockMetadata,
state::{Registered, Reset, Staged},
};
use crate::pools::SequenceHash;
use crate::registry::BlockRegistry;
use super::token_blocks::create_test_token_block;
// ============================================================================
// Block lifecycle helpers
// ============================================================================
/// Create a staged (completed but not registered) block.
pub(crate) fn create_staged_block<T: BlockMetadata + std::fmt::Debug>(
id: BlockId,
tokens: &[u32],
) -> Block<T, Staged> {
let token_block = create_test_token_block(tokens, tokens.len() as u32);
let block: Block<T, Reset> = Block::new(id, tokens.len());
block.complete(&token_block).expect("Should complete")
}
/// Create a registered block with a new ephemeral registry.
///
/// Returns both the registered block and its sequence hash.
pub(crate) fn create_registered_block<T: BlockMetadata + std::fmt::Debug>(
id: BlockId,
tokens: &[u32],
) -> (Block<T, Registered>, SequenceHash) {
let staged = create_staged_block::<T>(id, tokens);
let seq_hash = staged.sequence_hash();
let registry = BlockRegistry::new();
let handle = registry.register_sequence_hash(seq_hash);
(staged.register_with_handle(handle), seq_hash)
}
/// Create a reset block with the given ID and block size.
pub(crate) fn create_reset_block<T: BlockMetadata>(
id: BlockId,
block_size: usize,
) -> Block<T, Reset> {
Block::new(id, block_size)
}
/// Create multiple reset blocks with sequential IDs starting from 0.
pub(crate) fn create_reset_blocks<T: BlockMetadata>(
count: usize,
block_size: usize,
) -> Vec<Block<T, Reset>> {
(0..count as BlockId)
.map(|id| Block::new(id, block_size))
.collect()
}
// ============================================================================
// Generic TestBlockBuilder<T>
// ============================================================================
/// Enhanced test block builder for consistent block creation.
///
/// Provides a fluent API for creating test blocks with explicit configuration
/// of all parameters, reducing the likelihood of block size mismatches in tests.
pub(crate) struct TestBlockBuilder<T: BlockMetadata> {
id: BlockId,
block_size: usize,
tokens: Option<Vec<u32>>,
_phantom: std::marker::PhantomData<T>,
}
impl<T: BlockMetadata> TestBlockBuilder<T> {
/// Create a new test block builder with the given ID.
///
/// Uses the default test block size (4) but allows override.
pub(crate) fn new(id: BlockId) -> Self {
Self {
id,
block_size: DEFAULT_TEST_BLOCK_SIZE,
tokens: None,
_phantom: std::marker::PhantomData,
}
}
/// Set the block size for this test block.
///
/// The block size must be a power of 2 between 1 and 1024.
pub(crate) fn with_block_size(mut self, size: usize) -> Self {
use super::config::validate_test_block_size;
assert!(
validate_test_block_size(size),
"Invalid test block size: {}. Must be power of 2 between 1 and 1024",
size
);
self.block_size = size;
self
}
/// Set specific tokens for this test block.
///
/// If not specified, tokens will be auto-generated to match the block size.
/// The length of the tokens vector should match the configured block size.
pub(crate) fn with_tokens(mut self, tokens: Vec<u32>) -> Self {
self.tokens = Some(tokens);
self
}
/// Fill with sequential tokens starting from the given value.
///
/// Generates tokens [start, start+1, start+2, ...] up to block_size.
/// This is mutually exclusive with `with_tokens()` - the last one called wins.
pub(crate) fn fill_iota(mut self, start: u32) -> Self {
let tokens: Vec<u32> = (start..start + self.block_size as u32).collect();
self.tokens = Some(tokens);
self
}
/// Build a Staged (Complete) state block.
///
/// This will auto-generate tokens if none were provided, ensuring they
/// match the configured block size.
pub(crate) fn build_staged(self) -> Block<T, Staged>
where
T: std::fmt::Debug,
{
use super::config::generate_test_tokens;
// Auto-generate tokens if not provided
let tokens = self
.tokens
.unwrap_or_else(|| generate_test_tokens(self.id as u32 * 100, self.block_size));
// Validate token count matches block size
assert_eq!(
tokens.len(),
self.block_size,
"Token count {} doesn't match block size {}",
tokens.len(),
self.block_size
);
let token_block = create_test_token_block(&tokens, self.block_size as u32);
Block::new(self.id, self.block_size)
.complete(&token_block)
.expect("Block size should match token block size")
}
/// Build a Registered state block with a specific registry.
///
/// Creates a staged block and registers it with the provided registry.
pub(crate) fn build_registered_with_registry(
self,
registry: &BlockRegistry,
) -> (Block<T, Registered>, SequenceHash)
where
T: std::fmt::Debug,
{
let staged = self.build_staged();
let seq_hash = staged.sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
(staged.register_with_handle(handle), seq_hash)
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Centralized test configuration for v2 block manager.
//!
//! This module provides constants and utilities for consistent testing across
//! all v2 block manager components.
/// Default block size for testing (4 tokens)
///
/// Most tests use 4-token sequences like [100, 101, 102, 103].
/// This size is small enough for easy test data generation while being
/// a valid power-of-2 block size.
pub const DEFAULT_TEST_BLOCK_SIZE: usize = 4;
/// Default number of blocks for testing pools and managers
pub const DEFAULT_TEST_BLOCK_COUNT: usize = 10;
/// Common test block sizes for parameterized testing
///
/// These cover the full range of valid block sizes from 1 to 1024,
/// all being powers of 2 as required by the validation.
pub const TEST_BLOCK_SIZES: &[usize] = &[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024];
/// Small set of block sizes for focused testing
pub const COMMON_TEST_BLOCK_SIZES: &[usize] = &[1, 4, 16, 64];
/// Test configuration constants
pub mod constants {
/// Very small block size for edge case testing
pub const TINY: usize = 1;
/// Small block size (our standard)
pub const SMALL: usize = 4;
/// Medium block size
pub const MEDIUM: usize = 16;
/// Large block size
pub const LARGE: usize = 64;
/// Maximum block size
pub const MAX: usize = 1024;
}
/// Validate that a block size is suitable for testing
///
/// # Arguments
/// * `size` - The block size to validate
///
/// # Returns
/// `true` if the size is a power of 2 between 1 and 1024 (inclusive)
pub fn validate_test_block_size(size: usize) -> bool {
size.is_power_of_two() && (1..=1024).contains(&size)
}
/// Generate a sequence of tokens for testing with the given block size
///
/// # Arguments
/// * `base` - Starting token value
/// * `block_size` - Number of tokens to generate
///
/// # Returns
/// Vector of tokens: [base, base+1, base+2, ..., base+block_size-1]
///
/// # Example
/// ```
/// use dynamo_kvbm_logical::testing::config::generate_test_tokens;
///
/// let tokens = generate_test_tokens(100, 4);
/// assert_eq!(tokens, vec![100, 101, 102, 103]);
/// ```
pub fn generate_test_tokens(base: u32, block_size: usize) -> Vec<u32> {
(base..base + block_size as u32).collect()
}
/// Generate unique token sequences for multiple blocks
///
/// # Arguments
/// * `count` - Number of token sequences to generate
/// * `block_size` - Size of each token sequence
///
/// # Returns
/// Vector of token vectors, each with unique values
///
/// # Example
/// ```
/// use dynamo_kvbm_logical::testing::config::generate_unique_token_sequences;
///
/// let sequences = generate_unique_token_sequences(2, 4);
/// assert_eq!(sequences.len(), 2);
/// assert_eq!(sequences[0], vec![0, 1, 2, 3]);
/// assert_eq!(sequences[1], vec![1000, 1001, 1002, 1003]);
/// ```
pub fn generate_unique_token_sequences(count: usize, block_size: usize) -> Vec<Vec<u32>> {
(0..count)
.map(|i| generate_test_tokens(i as u32 * 1000, block_size))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_test_block_size() {
// Valid sizes
assert!(validate_test_block_size(1));
assert!(validate_test_block_size(4));
assert!(validate_test_block_size(16));
assert!(validate_test_block_size(1024));
// Invalid sizes
assert!(!validate_test_block_size(0));
assert!(!validate_test_block_size(3)); // Not power of 2
assert!(!validate_test_block_size(5)); // Not power of 2
assert!(!validate_test_block_size(2048)); // Too large
}
#[test]
fn test_generate_test_tokens() {
let tokens = generate_test_tokens(100, 4);
assert_eq!(tokens, vec![100, 101, 102, 103]);
let tokens = generate_test_tokens(0, 1);
assert_eq!(tokens, vec![0]);
}
#[test]
fn test_generate_unique_token_sequences() {
let sequences = generate_unique_token_sequences(3, 2);
assert_eq!(sequences.len(), 3);
assert_eq!(sequences[0], vec![0, 1]);
assert_eq!(sequences[1], vec![1000, 1001]);
assert_eq!(sequences[2], vec![2000, 2001]);
// Ensure all sequences are unique
for i in 0..sequences.len() {
for j in (i + 1)..sequences.len() {
assert_ne!(sequences[i], sequences[j]);
}
}
}
#[test]
fn test_constants_are_valid() {
assert!(validate_test_block_size(constants::TINY));
assert!(validate_test_block_size(constants::SMALL));
assert!(validate_test_block_size(constants::MEDIUM));
assert!(validate_test_block_size(constants::LARGE));
assert!(validate_test_block_size(constants::MAX));
}
#[test]
fn test_block_sizes_arrays_are_valid() {
for &size in TEST_BLOCK_SIZES {
assert!(
validate_test_block_size(size),
"Invalid test block size: {}",
size
);
}
for &size in COMMON_TEST_BLOCK_SIZES {
assert!(
validate_test_block_size(size),
"Invalid common test block size: {}",
size
);
}
}
#[test]
fn test_default_constants() {
assert_eq!(DEFAULT_TEST_BLOCK_SIZE, 4);
assert_eq!(DEFAULT_TEST_BLOCK_COUNT, 10);
assert!(validate_test_block_size(DEFAULT_TEST_BLOCK_SIZE));
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Test manager creation helpers.
use crate::blocks::BlockMetadata;
use crate::manager::{BlockManager, FrequencyTrackingCapacity};
use crate::registry::BlockRegistry;
/// Create a basic test manager with LRU backend.
pub fn create_test_manager<T: BlockMetadata>(block_count: usize) -> BlockManager<T> {
let registry = BlockRegistry::builder()
.frequency_tracker(FrequencyTrackingCapacity::default().create_tracker())
.build();
BlockManager::<T>::builder()
.block_count(block_count)
.block_size(4) // Most tests use 4-token blocks
.registry(registry)
.with_lru_backend()
.build()
.expect("Should build manager")
}
/// Create a test manager with custom block size.
pub fn create_test_manager_with_block_size<T: BlockMetadata>(
block_count: usize,
block_size: usize,
) -> BlockManager<T> {
let registry = BlockRegistry::builder()
.frequency_tracker(FrequencyTrackingCapacity::default().create_tracker())
.build();
BlockManager::<T>::builder()
.block_count(block_count)
.block_size(block_size)
.registry(registry)
.with_lru_backend()
.build()
.expect("Should build manager")
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Shared test fixtures for `v2/logical/` module tests.
//!
//! This module consolidates duplicated test helpers across registry, pools, and manager tests.
//! It uses internal types like `Block<T, Staged>` so it must be behind `#[cfg(test)]`.
//!
//! Note: `v2/testing/` uses only the public API and remains separate.
pub mod config;
#[allow(dead_code)]
mod blocks;
mod managers;
#[allow(dead_code)]
mod pools;
#[allow(dead_code)]
mod sequences;
mod token_blocks;
// ============================================================================
// Canonical test metadata types
// ============================================================================
/// Primary test metadata type used across all v2 tests.
/// Replaces: `TestMetadata` (registry), `TestData` (pools), `TestBlockData` (manager)
#[derive(Debug, Clone, PartialEq)]
pub struct TestMeta {
pub value: u64,
}
/// Multi-type registry test metadata A
#[derive(Debug, Clone, PartialEq)]
pub struct MetadataA(pub u32);
/// Multi-type registry test metadata B
#[derive(Debug, Clone, PartialEq)]
pub struct MetadataB(pub String);
/// Multi-type registry test metadata C (unit struct)
#[derive(Debug, Clone, PartialEq)]
pub struct MetadataC;
// ============================================================================
// Constants
// ============================================================================
/// Standard salt value for test token blocks.
/// Standardizes mixed salt values (42 in pools/manager, 1337 in registry).
pub const TEST_SALT: u64 = 42;
// ============================================================================
// Re-exports from submodules
// ============================================================================
// pub items — usable by downstream crates via the testing feature
pub use managers::{create_test_manager, create_test_manager_with_block_size};
pub use sequences::BlockSequenceBuilder;
pub use token_blocks::{
create_iota_token_block, create_test_token_block, sequential_tokens, tokens_for_id,
};
// pub(crate) items — internal helpers using internal types
#[cfg(test)]
pub(crate) use blocks::{
TestBlockBuilder, create_registered_block, create_reset_block, create_reset_blocks,
create_staged_block,
};
#[cfg(test)]
pub(crate) use pools::TestPoolSetupBuilder;
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Test pool setup builder.
use derive_builder::Builder;
use crate::blocks::BlockMetadata;
use crate::pools::{
InactivePool, ResetPool,
backends::{FifoReusePolicy, HashMapBackend},
};
use super::blocks::create_reset_blocks;
/// Configuration for setting up test pools.
#[derive(Builder)]
#[builder(pattern = "owned")]
pub(crate) struct TestPoolSetup {
#[builder(default = "10")]
pub(crate) block_count: usize,
#[builder(default = "4")]
pub(crate) block_size: usize,
}
impl TestPoolSetup {
/// Build a reset pool with the configured settings.
pub(crate) fn build_reset_pool<T: BlockMetadata>(&self) -> ResetPool<T> {
let blocks = create_reset_blocks::<T>(self.block_count, self.block_size);
ResetPool::new(blocks, self.block_size, None)
}
/// Build both inactive and reset pools with the configured settings.
pub(crate) fn build_pools<T: BlockMetadata>(&self) -> (InactivePool<T>, ResetPool<T>) {
let reset_pool = self.build_reset_pool::<T>();
let reuse_policy = Box::new(FifoReusePolicy::new());
let backend = Box::new(HashMapBackend::new(reuse_policy));
let inactive_pool = InactivePool::new(backend, &reset_pool, None);
(inactive_pool, reset_pool)
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! BlockSequenceBuilder for creating sequences of test blocks.
use std::sync::Arc;
use dynamo_tokens::TokenBlockSequence;
use super::config::DEFAULT_TEST_BLOCK_SIZE;
use crate::BlockId;
use crate::blocks::{
Block, BlockMetadata,
state::{Registered, Staged},
};
use crate::pools::SequenceHash;
use crate::registry::BlockRegistry;
use super::blocks::TestBlockBuilder;
/// Builder for creating sequences of blocks with relationships.
///
/// Supports two modes:
/// - Individual: Build blocks with custom configuration
/// - TokenSequence: Build from a realistic token sequence using TokenBlockSequence
pub struct BlockSequenceBuilder<T: BlockMetadata> {
mode: BuilderMode<T>,
block_size: usize,
}
enum BuilderMode<T: BlockMetadata> {
/// Build individual blocks with custom configuration
Individual { blocks: Vec<TestBlockBuilder<T>> },
/// Build from a token sequence (more realistic)
TokenSequence { tokens: Vec<u32>, salt: Option<u64> },
}
impl<T: BlockMetadata + std::fmt::Debug> BlockSequenceBuilder<T> {
/// Start a new sequence in individual mode.
pub(crate) fn new() -> Self {
Self {
mode: BuilderMode::Individual { blocks: Vec::new() },
block_size: DEFAULT_TEST_BLOCK_SIZE,
}
}
/// Create from a token sequence (switches to TokenSequence mode).
pub(crate) fn from_tokens(tokens: Vec<u32>) -> Self {
Self {
mode: BuilderMode::TokenSequence { tokens, salt: None },
block_size: DEFAULT_TEST_BLOCK_SIZE,
}
}
/// Set block size (must be called before building).
pub(crate) fn with_block_size(mut self, size: usize) -> Self {
use super::config::validate_test_block_size;
assert!(
validate_test_block_size(size),
"Invalid block size: {}. Must be power of 2 between 1 and 1024",
size
);
self.block_size = size;
self
}
/// Set salt for token sequence mode.
pub(crate) fn with_salt(mut self, salt: u64) -> Self {
if let BuilderMode::TokenSequence { tokens, .. } = self.mode {
self.mode = BuilderMode::TokenSequence {
tokens,
salt: Some(salt),
};
} else {
panic!("with_salt() only valid in TokenSequence mode");
}
self
}
/// Add a block to the sequence (Individual mode only).
pub(crate) fn add_block(mut self, id: BlockId) -> Self {
if let BuilderMode::Individual { mut blocks } = self.mode {
blocks.push(TestBlockBuilder::<T>::new(id).with_block_size(self.block_size));
self.mode = BuilderMode::Individual { blocks };
} else {
panic!("add_block() only valid in Individual mode");
}
self
}
/// Add a block with specific configuration (Individual mode only).
pub(crate) fn add_block_with<F>(mut self, id: BlockId, f: F) -> Self
where
F: FnOnce(TestBlockBuilder<T>) -> TestBlockBuilder<T>,
{
if let BuilderMode::Individual { mut blocks } = self.mode {
let builder = f(TestBlockBuilder::<T>::new(id).with_block_size(self.block_size));
blocks.push(builder);
self.mode = BuilderMode::Individual { blocks };
} else {
panic!("add_block_with() only valid in Individual mode");
}
self
}
/// Build the sequence, returning registered blocks.
pub(crate) fn build(self) -> Vec<(Block<T, Registered>, SequenceHash)> {
let registry = Arc::new(BlockRegistry::new());
let block_size = self.block_size;
match self.mode {
BuilderMode::Individual { blocks } => Self::build_individual_static(blocks, registry),
BuilderMode::TokenSequence { tokens, salt } => {
Self::build_from_token_sequence_static(tokens, salt, registry, block_size)
}
}
}
fn build_from_token_sequence_static(
tokens: Vec<u32>,
salt: Option<u64>,
registry: Arc<BlockRegistry>,
block_size: usize,
) -> Vec<(Block<T, Registered>, SequenceHash)> {
// Validate token count is divisible by block size
assert_eq!(
tokens.len() % block_size,
0,
"Token count {} must be divisible by block size {}",
tokens.len(),
block_size
);
// Create TokenBlockSequence
let token_seq = TokenBlockSequence::from_slice(&tokens, block_size as u32, salt);
// Convert each TokenBlock to a registered test block
let mut results = Vec::new();
let token_blocks = token_seq.blocks();
for (idx, token_block) in token_blocks.iter().enumerate() {
let block_id = idx as BlockId;
let staged: Block<T, Staged> = Block::new(block_id, block_size)
.complete(token_block)
.expect("Block size should match");
let seq_hash = staged.sequence_hash();
let handle = registry.register_sequence_hash(seq_hash);
let registered = staged.register_with_handle(handle);
results.push((registered, seq_hash));
}
results
}
fn build_individual_static(
blocks: Vec<TestBlockBuilder<T>>,
registry: Arc<BlockRegistry>,
) -> Vec<(Block<T, Registered>, SequenceHash)> {
let mut results = Vec::new();
for builder in blocks {
let block = builder.build_registered_with_registry(&registry);
results.push(block);
}
results
}
}
impl<T: BlockMetadata + std::fmt::Debug> Default for BlockSequenceBuilder<T> {
fn default() -> Self {
Self::new()
}
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Token block creation helpers for tests.
use dynamo_tokens::{TokenBlock, TokenBlockSequence};
use super::TEST_SALT;
/// Create a token block from a slice of tokens with standard test salt.
///
/// If the token count matches block_size, returns a complete block.
/// Otherwise attempts to commit a partial block.
pub fn create_test_token_block(tokens: &[u32], block_size: u32) -> TokenBlock {
let sequence = TokenBlockSequence::from_slice(tokens, block_size, Some(TEST_SALT));
if let Some(block) = sequence.blocks().first() {
block.clone()
} else {
let mut partial = sequence.into_parts().1;
partial.commit().expect("Should be able to commit")
}
}
/// Create a token block with sequential tokens starting from `start`.
///
/// Generates tokens [start, start+1, ..., start+block_size-1].
pub fn create_iota_token_block(start: u32, block_size: u32) -> TokenBlock {
let tokens: Vec<u32> = (start..start + block_size).collect();
create_test_token_block(&tokens, block_size)
}
/// Generate a vector of sequential tokens.
pub fn sequential_tokens(start: u32, count: usize) -> Vec<u32> {
(start..start + count as u32).collect()
}
/// Generate tokens for a given block ID (for unique but deterministic test data).
pub fn tokens_for_id(id: u64) -> Vec<u32> {
vec![id as u32, (id + 1) as u32, (id + 2) as u32, (id + 3) as u32]
}
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! Frequency tracking for block reuse policies using Count-Min Sketch.
use derive_builder::Builder;
use parking_lot::Mutex;
use xxhash_rust::const_xxh3::const_custom_default_secret;
use xxhash_rust::xxh3::xxh3_64_with_secret;
const SECRET_0: &[u8; 192] = &const_custom_default_secret(0);
const SECRET_1: &[u8; 192] = &const_custom_default_secret(1);
const SECRET_2: &[u8; 192] = &const_custom_default_secret(2);
const SECRET_3: &[u8; 192] = &const_custom_default_secret(3);
/// Trait for types that can be used as keys in the TinyLFU sketch.
pub trait SketchKey: Copy + Send + Sync + 'static {
/// Convert the key to bytes for hashing.
fn hash_with_secret(&self, secret: &[u8; 192]) -> u64;
}
impl SketchKey for u64 {
fn hash_with_secret(&self, secret: &[u8; 192]) -> u64 {
let bytes = self.to_le_bytes();
xxh3_64_with_secret(&bytes, secret)
}
}
impl SketchKey for u128 {
fn hash_with_secret(&self, secret: &[u8; 192]) -> u64 {
let bytes = self.to_le_bytes();
xxh3_64_with_secret(&bytes, secret)
}
}
/// Policy that determines when the TinyLFU sketch should decay its counters.
pub trait DecayPolicy: Send + Sync {
/// Returns `true` if the sketch should reset/decay given the number of
/// increments since the last reset.
fn should_decay(&self, increments_since_last_reset: u32) -> bool;
}
/// Fixed-threshold decay policy: decays after a fixed number of increments.
///
/// This is the default policy, matching the original `capacity * 10` behavior.
pub struct FixedDecayPolicy {
sample_size: u32,
}
impl FixedDecayPolicy {
/// Create a policy with a specific sample size threshold.
pub fn new(sample_size: u32) -> Self {
Self { sample_size }
}
/// Create a policy derived from capacity, using `capacity * 10` as the threshold.
pub fn from_capacity(capacity: usize) -> Self {
let sample_size = capacity.saturating_mul(10).min(u32::MAX as usize) as u32;
Self { sample_size }
}
}
impl DecayPolicy for FixedDecayPolicy {
fn should_decay(&self, increments_since_last_reset: u32) -> bool {
increments_since_last_reset >= self.sample_size
}
}
/// Settings for constructing a [`TinyLFUSketch`] or [`TinyLFUTracker`].
///
/// # Example
///
/// ```ignore
/// // Simple with defaults (FixedDecayPolicy from capacity)
/// let sketch = TinyLFUSettings::builder()
/// .capacity(100)
/// .build()?
/// .into_sketch::<u64>();
///
/// // With custom decay policy
/// let sketch = TinyLFUSettings::builder()
/// .capacity(100)
/// .decay_policy(FixedDecayPolicy::new(500))
/// .build()?
/// .into_sketch::<u64>();
/// ```
#[derive(Builder)]
#[builder(setter(into), build_fn(error = "anyhow::Error"), pattern = "owned")]
pub struct TinyLFUSettings {
capacity: usize,
#[builder(default, setter(custom))]
decay_policy: Option<Box<dyn DecayPolicy>>,
}
impl TinyLFUSettingsBuilder {
pub fn decay_policy(mut self, policy: impl DecayPolicy + 'static) -> Self {
self.decay_policy = Some(Some(Box::new(policy)));
self
}
}
impl TinyLFUSettings {
/// Creates a new builder for TinyLFUSettings.
pub fn builder() -> TinyLFUSettingsBuilder {
TinyLFUSettingsBuilder::default()
}
/// Converts settings into a [`TinyLFUSketch`].
pub fn into_sketch<K: SketchKey>(self) -> TinyLFUSketch<K> {
let decay_policy = self
.decay_policy
.unwrap_or_else(|| Box::new(FixedDecayPolicy::from_capacity(self.capacity)));
TinyLFUSketch::with_decay_policy(self.capacity, decay_policy)
}
/// Converts settings into a [`TinyLFUTracker`].
pub fn into_tracker<K: SketchKey>(self) -> TinyLFUTracker<K> {
TinyLFUTracker {
sketch: Mutex::new(self.into_sketch()),
}
}
}
pub struct TinyLFUSketch<K: SketchKey> {
table: Vec<u64>,
size: u32,
decay_policy: Box<dyn DecayPolicy>,
_phantom: std::marker::PhantomData<K>,
}
impl<K: SketchKey> TinyLFUSketch<K> {
const RESET_MASK: u64 = 0x7777_7777_7777_7777;
const ONE_MASK: u64 = 0x1111_1111_1111_1111;
pub fn new(capacity: usize) -> Self {
let decay_policy = Box::new(FixedDecayPolicy::from_capacity(capacity));
Self::with_decay_policy(capacity, decay_policy)
}
fn with_decay_policy(capacity: usize, decay_policy: Box<dyn DecayPolicy>) -> Self {
let table_size = std::cmp::max(1, capacity / 4);
Self {
table: vec![0; table_size],
size: 0,
decay_policy,
_phantom: std::marker::PhantomData,
}
}
fn hash(key: &K, seed: u32) -> u64 {
let secret = match seed {
0 => SECRET_0,
1 => SECRET_1,
2 => SECRET_2,
3 => SECRET_3,
_ => SECRET_0,
};
key.hash_with_secret(secret)
}
pub fn increment(&mut self, key: K) {
if self.table.is_empty() {
return;
}
let mut added = false;
for i in 0..4 {
let hash = Self::hash(&key, i);
let table_index = (hash as usize) % self.table.len();
let counter_index = (hash & 15) as u8;
if self.increment_at(table_index, counter_index) {
added = true;
}
}
if added {
self.size += 1;
if self.decay_policy.should_decay(self.size) {
self.reset();
}
}
}
fn increment_at(&mut self, table_index: usize, counter_index: u8) -> bool {
let offset = (counter_index as usize) * 4;
let mask = 0xF_u64 << offset;
if self.table[table_index] & mask != mask {
self.table[table_index] += 1u64 << offset;
true
} else {
false
}
}
pub fn estimate(&self, key: K) -> u32 {
if self.table.is_empty() {
return 0;
}
let mut min_count = u32::MAX;
for i in 0..4 {
let hash = Self::hash(&key, i);
let table_index = (hash as usize) % self.table.len();
let counter_index = (hash & 15) as u8;
let count = self.count_at(table_index, counter_index);
min_count = min_count.min(count as u32);
}
min_count
}
fn count_at(&self, table_index: usize, counter_index: u8) -> u8 {
let offset = (counter_index as usize) * 4;
let mask = 0xF_u64 << offset;
((self.table[table_index] & mask) >> offset) as u8
}
fn reset(&mut self) {
let mut count = 0u32;
for entry in self.table.iter_mut() {
count += (*entry & Self::ONE_MASK).count_ones();
*entry = (*entry >> 1) & Self::RESET_MASK;
}
let half = self.size >> 1;
let dec = count >> 2;
self.size = half.saturating_sub(dec);
}
}
pub trait FrequencyTracker<K: SketchKey>: Send + Sync {
fn touch(&self, key: K);
fn count(&self, key: K) -> u32;
}
pub struct TinyLFUTracker<K: SketchKey> {
sketch: Mutex<TinyLFUSketch<K>>,
}
impl<K: SketchKey> TinyLFUTracker<K> {
pub fn new(capacity: usize) -> Self {
Self {
sketch: Mutex::new(TinyLFUSketch::new(capacity)),
}
}
}
impl<K: SketchKey> FrequencyTracker<K> for TinyLFUTracker<K> {
fn touch(&self, key: K) {
self.sketch.lock().increment(key);
}
fn count(&self, key: K) -> u32 {
self.sketch.lock().estimate(key)
}
}
pub struct NoOpTracker<K: SketchKey> {
_phantom: std::marker::PhantomData<K>,
}
impl<K: SketchKey> NoOpTracker<K> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<K: SketchKey> Default for NoOpTracker<K> {
fn default() -> Self {
Self::new()
}
}
impl<K: SketchKey> FrequencyTracker<K> for NoOpTracker<K> {
fn touch(&self, _key: K) {}
fn count(&self, _key: K) -> u32 {
0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tinylfu_increment_and_estimate() {
let mut sketch = TinyLFUSketch::<u64>::new(100);
sketch.increment(42);
assert_eq!(sketch.estimate(42), 1);
sketch.increment(42);
sketch.increment(42);
assert_eq!(sketch.estimate(42), 3);
assert_eq!(sketch.estimate(99), 0);
}
#[test]
fn test_tinylfu_saturation() {
let mut sketch = TinyLFUSketch::<u64>::new(100);
for _ in 0..20 {
sketch.increment(42);
}
assert!(sketch.estimate(42) <= 15);
}
#[test]
fn test_tinylfu_reset() {
let mut sketch = TinyLFUSketch::<u64>::new(10);
for i in 0..100 {
sketch.increment(i);
}
let estimate_before = sketch.estimate(5);
assert!(estimate_before > 0);
}
#[test]
fn test_frequency_tracker_trait() {
let tracker = TinyLFUTracker::<u64>::new(100);
tracker.touch(42);
assert_eq!(tracker.count(42), 1);
tracker.touch(42);
tracker.touch(42);
assert_eq!(tracker.count(42), 3);
}
#[test]
fn test_noop_tracker() {
let tracker = NoOpTracker::<u64>::new();
tracker.touch(42);
assert_eq!(tracker.count(42), 0);
tracker.touch(42);
assert_eq!(tracker.count(42), 0);
}
#[test]
fn test_u128_keys() {
let mut sketch = TinyLFUSketch::<u128>::new(100);
let key: u128 = 0x0123_4567_89AB_CDEF_0123_4567_89AB_CDEF;
sketch.increment(key);
assert_eq!(sketch.estimate(key), 1);
sketch.increment(key);
sketch.increment(key);
assert_eq!(sketch.estimate(key), 3);
assert_eq!(sketch.estimate(0), 0);
}
#[test]
fn test_u128_tracker() {
let tracker = TinyLFUTracker::<u128>::new(100);
let key: u128 = 0x0123_4567_89AB_CDEF_0123_4567_89AB_CDEF;
tracker.touch(key);
assert_eq!(tracker.count(key), 1);
tracker.touch(key);
tracker.touch(key);
assert_eq!(tracker.count(key), 3);
}
#[test]
fn test_settings_builder_default_policy() {
let sketch = TinyLFUSettings::builder()
.capacity(100usize)
.build()
.unwrap()
.into_sketch::<u64>();
assert_eq!(sketch.estimate(42), 0);
}
#[test]
fn test_settings_builder_custom_policy() {
let mut sketch = TinyLFUSettings::builder()
.capacity(100usize)
.decay_policy(FixedDecayPolicy::new(500))
.build()
.unwrap()
.into_sketch::<u64>();
// With sample_size=500 (instead of default 1000), decay triggers sooner
// Increment the same key many times and verify it tracks
for _ in 0..10 {
sketch.increment(42);
}
assert!(sketch.estimate(42) >= 5);
}
#[test]
fn test_settings_builder_into_tracker() {
let tracker = TinyLFUSettings::builder()
.capacity(100usize)
.build()
.unwrap()
.into_tracker::<u64>();
tracker.touch(42);
assert_eq!(tracker.count(42), 1);
}
#[test]
fn test_fixed_decay_policy() {
let policy = FixedDecayPolicy::new(100);
assert!(!policy.should_decay(99));
assert!(policy.should_decay(100));
assert!(policy.should_decay(101));
}
#[test]
fn test_fixed_decay_policy_from_capacity() {
let policy = FixedDecayPolicy::from_capacity(10);
assert!(!policy.should_decay(99));
assert!(policy.should_decay(100)); // 10 * 10 = 100
}
#[test]
fn test_manual_decay_via_atomic_policy() {
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
struct ManualDecayPolicy {
trigger: Arc<AtomicBool>,
}
impl DecayPolicy for ManualDecayPolicy {
fn should_decay(&self, _increments_since_last_reset: u32) -> bool {
self.trigger.swap(false, Ordering::Relaxed)
}
}
let trigger = Arc::new(AtomicBool::new(false));
let mut sketch = TinyLFUSettings::builder()
.capacity(100usize)
.decay_policy(ManualDecayPolicy {
trigger: Arc::clone(&trigger),
})
.build()
.unwrap()
.into_sketch::<u64>();
// Increment key 42 four times — no decay armed
for _ in 0..4 {
sketch.increment(42);
}
assert_eq!(sketch.estimate(42), 4);
// Arm decay, then increment a *different* key to trigger it.
// The next added increment will see should_decay → true and reset.
trigger.store(true, Ordering::Relaxed);
sketch.increment(99);
// After reset, counters are halved: 4 → 2, and key 99's single
// count also halves (1 → 0 or 1 depending on rounding).
let estimate_after = sketch.estimate(42);
assert_eq!(estimate_after, 2, "counter should be halved by decay");
assert!(sketch.estimate(99) <= 1);
}
}
......@@ -2,29 +2,14 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "ahash"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
dependencies = [
"cfg-if 1.0.0",
"getrandom 0.3.2",
"cfg-if 1.0.4",
"getrandom 0.3.4",
"once_cell",
"version_check",
"zerocopy",
......@@ -32,9 +17,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
......@@ -45,12 +30,6 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
......@@ -62,15 +41,18 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.98"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea"
[[package]]
name = "arc-swap"
version = "1.7.1"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
checksum = "9ded5f9a03ac8f24d1b8a25101ee812cd32cdc8c50a4c50237de2c4915850e73"
dependencies = [
"rustversion",
]
[[package]]
name = "arrayref"
......@@ -158,18 +140,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "async-trait"
version = "0.1.88"
version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -188,9 +170,9 @@ dependencies = [
[[package]]
name = "atomic"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994"
checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340"
dependencies = [
"bytemuck",
]
......@@ -203,15 +185,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "autocfg"
version = "1.4.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "aws-lc-rs"
version = "1.14.1"
version = "1.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879b6c89592deb404ba4dc0ae6b58ffd1795c78991cbb5b8bc441c48a070440d"
checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256"
dependencies = [
"aws-lc-sys",
"zeroize",
......@@ -219,11 +201,10 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
version = "0.32.3"
version = "0.37.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "107a4e9d9cab9963e04e84bb8dee0e25f2a987f9a8bad5ed054abd439caa8f8c"
checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549"
dependencies = [
"bindgen",
"cc",
"cmake",
"dunce",
......@@ -267,9 +248,9 @@ dependencies = [
[[package]]
name = "axum-core"
version = "0.5.2"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
dependencies = [
"bytes",
"futures-core",
......@@ -278,7 +259,6 @@ dependencies = [
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper",
"tower-layer",
"tower-service",
......@@ -293,7 +273,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -307,21 +287,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "backtrace"
version = "0.3.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
dependencies = [
"addr2line",
"cfg-if 1.0.0",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-targets 0.52.6",
]
[[package]]
name = "base64"
version = "0.22.1"
......@@ -330,9 +295,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.7.3"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "bincode"
......@@ -343,26 +308,6 @@ dependencies = [
"serde",
]
[[package]]
name = "bindgen"
version = "0.72.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
dependencies = [
"bitflags 2.9.0",
"cexpr",
"clang-sys",
"itertools 0.13.0",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.100",
]
[[package]]
name = "bitflags"
version = "1.3.2"
......@@ -371,21 +316,22 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.0"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
[[package]]
name = "blake3"
version = "1.8.2"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0"
checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"constant_time_eq",
"cpufeatures",
]
[[package]]
......@@ -399,15 +345,15 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.17.0"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "bytemuck"
version = "1.22.0"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
[[package]]
name = "byteorder"
......@@ -426,9 +372,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.45"
version = "1.2.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe"
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
dependencies = [
"find-msvc-tools",
"jobserver",
......@@ -436,15 +382,6 @@ dependencies = [
"shlex",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-expr"
version = "0.15.8"
......@@ -463,9 +400,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cfg_aliases"
......@@ -475,33 +412,21 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chrono"
version = "0.4.40"
version = "0.4.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"serde",
"windows-link 0.1.1",
]
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
"windows-link",
]
[[package]]
name = "cmake"
version = "0.1.54"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d"
dependencies = [
"cc",
]
......@@ -523,9 +448,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "constant_time_eq"
version = "0.3.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
[[package]]
name = "core-foundation"
......@@ -620,9 +545,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
......@@ -634,7 +559,7 @@ version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"cpufeatures",
"curve25519-dalek-derive",
"digest",
......@@ -651,7 +576,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -685,7 +610,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -699,7 +624,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -710,7 +635,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core 0.20.11",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -721,7 +646,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core 0.21.3",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -730,7 +655,7 @@ version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"crossbeam-utils",
"hashbrown 0.14.5",
"lock_api",
......@@ -740,9 +665,9 @@ dependencies = [
[[package]]
name = "data-encoding"
version = "2.9.0"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
[[package]]
name = "der"
......@@ -757,12 +682,12 @@ dependencies = [
[[package]]
name = "deranged"
version = "0.4.0"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4"
dependencies = [
"powerfmt",
"serde",
"serde_core",
]
[[package]]
......@@ -773,7 +698,7 @@ checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -794,7 +719,7 @@ dependencies = [
"darling 0.20.11",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -804,27 +729,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
"syn 2.0.100",
"syn",
]
[[package]]
name = "derive_more"
version = "2.0.1"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "2.0.1"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"rustc_version",
"syn",
]
[[package]]
......@@ -856,7 +782,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -931,8 +857,8 @@ dependencies = [
"rmp-serde",
"serde",
"serde_json",
"socket2 0.5.9",
"thiserror 2.0.17",
"socket2 0.5.10",
"thiserror 2.0.18",
"tmq",
"tokio",
"tokio-rayon",
......@@ -961,9 +887,9 @@ dependencies = [
[[package]]
name = "ed25519-dalek"
version = "2.1.1"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
dependencies = [
"curve25519-dalek",
"ed25519",
......@@ -981,7 +907,7 @@ dependencies = [
"enum-ordinalize",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -995,22 +921,22 @@ dependencies = [
[[package]]
name = "enum-ordinalize"
version = "4.3.0"
version = "4.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5"
checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0"
dependencies = [
"enum-ordinalize-derive",
]
[[package]]
name = "enum-ordinalize-derive"
version = "4.3.1"
version = "4.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff"
checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -1021,12 +947,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.11"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
......@@ -1099,21 +1025,20 @@ dependencies = [
[[package]]
name = "filetime"
version = "0.2.26"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"libc",
"libredox",
"windows-sys 0.60.2",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.4"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "fixedbitset"
......@@ -1135,9 +1060,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
dependencies = [
"percent-encoding",
]
......@@ -1229,7 +1154,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -1274,42 +1199,55 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"js-sys",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasi",
"wasm-bindgen",
]
[[package]]
name = "getrandom"
version = "0.3.2"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"js-sys",
"libc",
"r-efi",
"wasi 0.14.2+wasi-0.2.4",
"wasip2",
"wasm-bindgen",
]
[[package]]
name = "gimli"
version = "0.31.1"
name = "getrandom"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec"
dependencies = [
"cfg-if 1.0.4",
"libc",
"r-efi",
"wasip2",
"wasip3",
]
[[package]]
name = "glob"
version = "0.3.3"
name = "getset"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912"
dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "gloo-timers"
......@@ -1325,9 +1263,9 @@ dependencies = [
[[package]]
name = "h2"
version = "0.4.9"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633"
checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
dependencies = [
"atomic-waker",
"bytes",
......@@ -1350,15 +1288,21 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
version = "0.15.2"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "heck"
version = "0.5.0"
......@@ -1384,23 +1328,22 @@ dependencies = [
[[package]]
name = "hostname"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65"
checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"libc",
"windows-link 0.1.1",
"windows-link",
]
[[package]]
name = "http"
version = "1.3.1"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
dependencies = [
"bytes",
"fnv",
"itoa",
]
......@@ -1441,19 +1384,20 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
[[package]]
name = "hyper"
version = "1.6.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
dependencies = [
"atomic-waker",
"bytes",
"futures-channel",
"futures-util",
"futures-core",
"h2",
"http",
"http-body",
......@@ -1461,6 +1405,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
"pin-utils",
"smallvec",
"tokio",
"want",
......@@ -1477,12 +1422,12 @@ dependencies = [
"hyper-util",
"log",
"rustls",
"rustls-native-certs 0.8.2",
"rustls-native-certs 0.8.3",
"rustls-pki-types",
"tokio",
"tokio-rustls",
"tower-service",
"webpki-roots 1.0.2",
"webpki-roots 1.0.6",
]
[[package]]
......@@ -1500,14 +1445,13 @@ dependencies = [
[[package]]
name = "hyper-util"
version = "0.1.16"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
dependencies = [
"base64",
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"http",
"http-body",
......@@ -1516,7 +1460,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.6.1",
"socket2 0.6.2",
"tokio",
"tower-service",
"tracing",
......@@ -1524,9 +1468,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.63"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
......@@ -1548,21 +1492,22 @@ dependencies = [
[[package]]
name = "icu_collections"
version = "1.5.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
dependencies = [
"displaydoc",
"potential_utf",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_locid"
version = "1.5.0"
name = "icu_locale_core"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
dependencies = [
"displaydoc",
"litemap",
......@@ -1571,98 +1516,66 @@ dependencies = [
"zerovec",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.1"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
[[package]]
name = "icu_properties"
version = "1.5.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_locale_core",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerotrie",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
[[package]]
name = "icu_provider"
version = "1.5.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr",
"icu_locale_core",
"writeable",
"yoke",
"zerofrom",
"zerotrie",
"zerovec",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
name = "id-arena"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
]
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "ident_case"
......@@ -1672,9 +1585,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "1.0.3"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
dependencies = [
"idna_adapter",
"smallvec",
......@@ -1683,9 +1596,9 @@ dependencies = [
[[package]]
name = "idna_adapter"
version = "1.2.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
dependencies = [
"icu_normalizer",
"icu_properties",
......@@ -1693,12 +1606,14 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.9.0"
version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
"hashbrown 0.15.2",
"hashbrown 0.16.1",
"serde",
"serde_core",
]
[[package]]
......@@ -1724,7 +1639,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
"futures-core",
"inotify-sys",
"libc",
......@@ -1757,23 +1672,14 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "iri-string"
version = "0.7.8"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.14.0"
......@@ -1785,25 +1691,25 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.15"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
[[package]]
name = "jobserver"
version = "0.1.33"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
"getrandom 0.3.2",
"getrandom 0.3.4",
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.77"
version = "0.3.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
dependencies = [
"once_cell",
"wasm-bindgen",
......@@ -1831,7 +1737,7 @@ dependencies = [
"pest_derive",
"regex",
"serde_json",
"thiserror 2.0.17",
"thiserror 2.0.18",
]
[[package]]
......@@ -1856,9 +1762,9 @@ dependencies = [
[[package]]
name = "k8s-openapi"
version = "0.26.0"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d13f06d5326a915becaffabdfab75051b8cdc260c2a5c06c0e90226ede89a692"
checksum = "06d9e5e61dd037cdc51da0d7e2b2be10f497478ea7e120d85dad632adb99882b"
dependencies = [
"base64",
"chrono",
......@@ -1937,7 +1843,7 @@ dependencies = [
"serde",
"serde_json",
"serde_yaml",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tokio",
"tokio-util",
"tower",
......@@ -1961,7 +1867,7 @@ dependencies = [
"serde",
"serde-value",
"serde_json",
"thiserror 2.0.17",
"thiserror 2.0.18",
]
[[package]]
......@@ -1975,7 +1881,7 @@ dependencies = [
"quote",
"serde",
"serde_json",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -1990,7 +1896,7 @@ dependencies = [
"backon",
"educe",
"futures",
"hashbrown 0.15.2",
"hashbrown 0.15.5",
"hostname",
"json-patch",
"k8s-openapi",
......@@ -1999,7 +1905,7 @@ dependencies = [
"pin-project",
"serde",
"serde_json",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tokio",
"tokio-util",
"tracing",
......@@ -2012,54 +1918,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.172"
name = "leb128fmt"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libloading"
version = "0.8.9"
name = "libc"
version = "0.2.182"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
dependencies = [
"cfg-if 1.0.0",
"windows-link 0.2.1",
]
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
[[package]]
name = "libredox"
version = "0.1.10"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
"libc",
"redox_syscall",
"redox_syscall 0.7.1",
]
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
[[package]]
name = "litemap"
version = "0.7.5"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
[[package]]
name = "local-ip-address"
version = "0.6.4"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c986b1747bbd3666abe4d57c64e60e6a82c2216140d8b12d5ceb33feb9de44b3"
checksum = "79ef8c257c92ade496781a32a581d43e3d512cf8ce714ecf04ea80f93ed0ff4a"
dependencies = [
"libc",
"neli",
"thiserror 2.0.17",
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
......@@ -2073,9 +1974,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.27"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "lru"
......@@ -2083,7 +1984,7 @@ version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [
"hashbrown 0.15.2",
"hashbrown 0.15.5",
]
[[package]]
......@@ -2094,11 +1995,11 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
[[package]]
name = "matchers"
version = "0.1.0"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
dependencies = [
"regex-automata 0.1.10",
"regex-automata",
]
[[package]]
......@@ -2109,9 +2010,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "memchr"
version = "2.7.4"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "mime"
......@@ -2119,21 +2020,6 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "0.6.23"
......@@ -2161,19 +2047,19 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "mio"
version = "1.0.3"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
dependencies = [
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.52.0",
"wasi",
"windows-sys 0.61.2",
]
[[package]]
......@@ -2190,33 +2076,37 @@ dependencies = [
[[package]]
name = "multimap"
version = "0.10.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
[[package]]
name = "neli"
version = "0.6.5"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9"
checksum = "22f9786d56d972959e1408b6a93be6af13b9c1392036c5c1fafa08a1b0c6ee87"
dependencies = [
"bitflags 2.11.0",
"byteorder",
"derive_builder",
"getset",
"libc",
"log",
"neli-proc-macros",
"parking_lot",
]
[[package]]
name = "neli-proc-macros"
version = "0.1.4"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe"
checksum = "05d8d08c6e98f20a62417478ebf7be8e1425ec9acecc6f63e22da633f6b71609"
dependencies = [
"either",
"proc-macro2",
"quote",
"serde",
"syn 1.0.109",
"syn",
]
[[package]]
......@@ -2247,44 +2137,34 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.9.0",
"cfg-if 1.0.0",
"bitflags 2.11.0",
"cfg-if 1.0.4",
"cfg_aliases",
"libc",
]
[[package]]
name = "nkeys"
version = "0.4.4"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f49e787f4c61cbd0f9320b31cc26e58719f6aa5068e34697dd3aea361412fe3"
checksum = "879011babc47a1c7fdf5a935ae3cfe94f34645ca0cac1c7f6424b36fc743d1bf"
dependencies = [
"data-encoding",
"ed25519",
"ed25519-dalek",
"getrandom 0.2.16",
"getrandom 0.2.17",
"log",
"rand 0.8.5",
"signatory",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "notify"
version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
"filetime",
"fsevent-sys",
"inotify 0.9.6",
......@@ -2298,12 +2178,11 @@ dependencies = [
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"overload",
"winapi 0.3.9",
"windows-sys 0.61.2",
]
[[package]]
......@@ -2317,9 +2196,9 @@ dependencies = [
[[package]]
name = "num-conv"
version = "0.1.0"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
[[package]]
name = "num-traits"
......@@ -2339,15 +2218,6 @@ dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.21.3"
......@@ -2360,6 +2230,12 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-probe"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "opentelemetry"
version = "0.31.0"
......@@ -2370,7 +2246,7 @@ dependencies = [
"futures-sink",
"js-sys",
"pin-project-lite",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tracing",
]
......@@ -2400,7 +2276,7 @@ dependencies = [
"opentelemetry_sdk",
"prost",
"reqwest",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tokio",
"tonic",
"tracing",
......@@ -2431,7 +2307,7 @@ dependencies = [
"opentelemetry",
"percent-encoding",
"rand 0.9.2",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tokio",
"tokio-stream",
]
......@@ -2445,12 +2321,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking"
version = "2.2.1"
......@@ -2473,19 +2343,13 @@ version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"libc",
"redox_syscall",
"redox_syscall 0.5.18",
"smallvec",
"windows-link 0.2.1",
"windows-link",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pear"
version = "0.2.9"
......@@ -2506,7 +2370,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -2536,9 +2400,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pest"
version = "2.8.3"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4"
checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662"
dependencies = [
"memchr",
"ucd-trie",
......@@ -2546,9 +2410,9 @@ dependencies = [
[[package]]
name = "pest_derive"
version = "2.8.3"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de"
checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77"
dependencies = [
"pest",
"pest_generator",
......@@ -2556,22 +2420,22 @@ dependencies = [
[[package]]
name = "pest_generator"
version = "2.8.3"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843"
checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "pest_meta"
version = "2.8.3"
version = "2.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a"
checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220"
dependencies = [
"pest",
"sha2",
......@@ -2579,11 +2443,12 @@ dependencies = [
[[package]]
name = "petgraph"
version = "0.7.1"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
dependencies = [
"fixedbitset",
"hashbrown 0.15.5",
"indexmap",
]
......@@ -2604,7 +2469,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -2637,9 +2502,18 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "portable-atomic"
version = "1.11.0"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
[[package]]
name = "potential_utf"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
dependencies = [
"zerovec",
]
[[package]]
name = "powerfmt"
......@@ -2658,12 +2532,12 @@ dependencies = [
[[package]]
name = "prettyplease"
version = "0.2.32"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -2685,14 +2559,14 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
......@@ -2705,7 +2579,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
"version_check",
"yansi",
]
......@@ -2716,20 +2590,20 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ca5326d8d0b950a9acd87e6a3f94745394f62e4dae1b1ee22b2bc0c394af43a"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"fnv",
"lazy_static",
"memchr",
"parking_lot",
"protobuf",
"thiserror 2.0.17",
"thiserror 2.0.18",
]
[[package]]
name = "prost"
version = "0.14.1"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d"
checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
dependencies = [
"bytes",
"prost-derive",
......@@ -2737,15 +2611,14 @@ dependencies = [
[[package]]
name = "prost-build"
version = "0.14.1"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1"
checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7"
dependencies = [
"heck",
"itertools 0.14.0",
"itertools",
"log",
"multimap",
"once_cell",
"petgraph",
"prettyplease",
"prost",
......@@ -2753,28 +2626,28 @@ dependencies = [
"pulldown-cmark",
"pulldown-cmark-to-cmark",
"regex",
"syn 2.0.100",
"syn",
"tempfile",
]
[[package]]
name = "prost-derive"
version = "0.14.1"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425"
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
dependencies = [
"anyhow",
"itertools 0.14.0",
"itertools",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "prost-types"
version = "0.14.1"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72"
checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7"
dependencies = [
"prost",
]
......@@ -2805,25 +2678,25 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
"memchr",
"unicase",
]
[[package]]
name = "pulldown-cmark-to-cmark"
version = "21.1.0"
version = "22.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8246feae3db61428fd0bb94285c690b460e4517d83152377543ca802357785f1"
checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90"
dependencies = [
"pulldown-cmark",
]
[[package]]
name = "quinn"
version = "0.11.8"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8"
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
dependencies = [
"bytes",
"cfg_aliases",
......@@ -2832,8 +2705,8 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
"socket2 0.5.9",
"thiserror 2.0.17",
"socket2 0.6.2",
"thiserror 2.0.18",
"tokio",
"tracing",
"web-time",
......@@ -2841,12 +2714,12 @@ dependencies = [
[[package]]
name = "quinn-proto"
version = "0.11.12"
version = "0.11.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31"
dependencies = [
"bytes",
"getrandom 0.3.2",
"getrandom 0.3.4",
"lru-slab",
"rand 0.9.2",
"ring",
......@@ -2854,7 +2727,7 @@ dependencies = [
"rustls",
"rustls-pki-types",
"slab",
"thiserror 2.0.17",
"thiserror 2.0.18",
"tinyvec",
"tracing",
"web-time",
......@@ -2862,32 +2735,32 @@ dependencies = [
[[package]]
name = "quinn-udp"
version = "0.5.13"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970"
checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2 0.5.9",
"socket2 0.6.2",
"tracing",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.2.0"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rand"
......@@ -2907,7 +2780,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
"rand_core 0.9.5",
]
[[package]]
......@@ -2927,7 +2800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
"rand_core 0.9.5",
]
[[package]]
......@@ -2936,23 +2809,23 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.16",
"getrandom 0.2.17",
]
[[package]]
name = "rand_core"
version = "0.9.3"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
dependencies = [
"getrandom 0.3.2",
"getrandom 0.3.4",
]
[[package]]
name = "rayon"
version = "1.10.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
......@@ -2960,9 +2833,9 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.12.1"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
......@@ -2974,7 +2847,16 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
]
[[package]]
name = "redox_syscall"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b"
dependencies = [
"bitflags 2.11.0",
]
[[package]]
......@@ -2994,58 +2876,43 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "regex"
version = "1.11.1"
version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.4.9",
"regex-syntax 0.8.5",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.8.5",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
[[package]]
name = "reqwest"
version = "0.12.24"
version = "0.12.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
dependencies = [
"base64",
"bytes",
......@@ -3080,7 +2947,7 @@ dependencies = [
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
"webpki-roots 1.0.2",
"webpki-roots 1.0.6",
]
[[package]]
......@@ -3090,8 +2957,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if 1.0.0",
"getrandom 0.2.16",
"cfg-if 1.0.4",
"getrandom 0.2.17",
"libc",
"untrusted",
"windows-sys 0.52.0",
......@@ -3099,32 +2966,23 @@ dependencies = [
[[package]]
name = "rmp"
version = "0.8.14"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4"
checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c"
dependencies = [
"byteorder",
"num-traits",
"paste",
]
[[package]]
name = "rmp-serde"
version = "1.3.0"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db"
checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155"
dependencies = [
"byteorder",
"rmp",
"serde",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
version = "2.1.1"
......@@ -3142,29 +3000,29 @@ dependencies = [
[[package]]
name = "rustix"
version = "1.0.5"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
name = "rustls"
version = "0.23.26"
version = "0.23.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0"
checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b"
dependencies = [
"aws-lc-rs",
"log",
"once_cell",
"ring",
"rustls-pki-types",
"rustls-webpki 0.103.1",
"rustls-webpki 0.103.9",
"subtle",
"zeroize",
]
......@@ -3175,7 +3033,7 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5"
dependencies = [
"openssl-probe",
"openssl-probe 0.1.6",
"rustls-pemfile",
"rustls-pki-types",
"schannel",
......@@ -3184,14 +3042,14 @@ dependencies = [
[[package]]
name = "rustls-native-certs"
version = "0.8.2"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923"
checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63"
dependencies = [
"openssl-probe",
"openssl-probe 0.2.1",
"rustls-pki-types",
"schannel",
"security-framework 3.5.1",
"security-framework 3.6.0",
]
[[package]]
......@@ -3205,11 +3063,12 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
version = "1.11.0"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
dependencies = [
"web-time",
"zeroize",
]
[[package]]
......@@ -3224,9 +3083,9 @@ dependencies = [
[[package]]
name = "rustls-webpki"
version = "0.103.1"
version = "0.103.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
dependencies = [
"aws-lc-rs",
"ring",
......@@ -3236,15 +3095,15 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.20"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
version = "1.0.20"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "same-file"
......@@ -3257,18 +3116,18 @@ dependencies = [
[[package]]
name = "schannel"
version = "0.1.27"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
name = "schemars"
version = "1.1.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289"
checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
dependencies = [
"dyn-clone",
"ref-cast",
......@@ -3279,14 +3138,14 @@ dependencies = [
[[package]]
name = "schemars_derive"
version = "1.1.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301858a4023d78debd2353c7426dc486001bddc91ae31a76fb1f55132f7e2633"
checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f"
dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -3310,7 +3169,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
......@@ -3319,11 +3178,11 @@ dependencies = [
[[package]]
name = "security-framework"
version = "3.5.1"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38"
dependencies = [
"bitflags 2.9.0",
"bitflags 2.11.0",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
......@@ -3332,9 +3191,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.15.0"
version = "2.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a"
dependencies = [
"core-foundation-sys",
"libc",
......@@ -3342,9 +3201,9 @@ dependencies = [
[[package]]
name = "semver"
version = "1.0.26"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
[[package]]
name = "serde"
......@@ -3383,7 +3242,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -3394,19 +3253,20 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.140"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
"serde_core",
"zmij",
]
[[package]]
......@@ -3420,12 +3280,13 @@ dependencies = [
[[package]]
name = "serde_path_to_error"
version = "0.1.17"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
dependencies = [
"itoa",
"serde",
"serde_core",
]
[[package]]
......@@ -3436,14 +3297,14 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "serde_spanned"
version = "0.6.8"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
......@@ -3487,11 +3348,11 @@ dependencies = [
[[package]]
name = "sha2"
version = "0.10.8"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"cpufeatures",
"digest",
]
......@@ -3513,10 +3374,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.5"
version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
"errno",
"libc",
]
......@@ -3544,24 +3406,21 @@ dependencies = [
[[package]]
name = "slab"
version = "0.4.9"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "smallvec"
version = "1.15.0"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "socket2"
version = "0.5.9"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
"libc",
"windows-sys 0.52.0",
......@@ -3569,9 +3428,9 @@ dependencies = [
[[package]]
name = "socket2"
version = "0.6.1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0"
dependencies = [
"libc",
"windows-sys 0.60.2",
......@@ -3589,9 +3448,9 @@ dependencies = [
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "strsim"
......@@ -3607,20 +3466,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.100"
version = "2.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12"
dependencies = [
"proc-macro2",
"quote",
......@@ -3638,13 +3486,13 @@ dependencies = [
[[package]]
name = "synstructure"
version = "0.13.1"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -3684,15 +3532,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "tempfile"
version = "3.19.1"
version = "3.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1"
dependencies = [
"fastrand",
"getrandom 0.3.2",
"getrandom 0.4.1",
"once_cell",
"rustix",
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
......@@ -3706,11 +3554,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.17"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
dependencies = [
"thiserror-impl 2.0.17",
"thiserror-impl 2.0.18",
]
[[package]]
......@@ -3721,35 +3569,34 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "thiserror-impl"
version = "2.0.17"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.8"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if 1.0.0",
"once_cell",
"cfg-if 1.0.4",
]
[[package]]
name = "time"
version = "0.3.41"
version = "0.3.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
dependencies = [
"deranged",
"itoa",
......@@ -3757,22 +3604,22 @@ dependencies = [
"num-conv",
"num_threads",
"powerfmt",
"serde",
"serde_core",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.4"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
[[package]]
name = "time-macros"
version = "0.2.22"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
dependencies = [
"num-conv",
"time-core",
......@@ -3780,9 +3627,9 @@ dependencies = [
[[package]]
name = "tinystr"
version = "0.7.6"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
dependencies = [
"displaydoc",
"zerovec",
......@@ -3790,9 +3637,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
......@@ -3818,31 +3665,30 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.44.2"
version = "1.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio 1.0.3",
"mio 1.1.1",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.5.9",
"socket2 0.6.2",
"tokio-macros",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
name = "tokio-macros"
version = "2.5.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -3857,9 +3703,9 @@ dependencies = [
[[package]]
name = "tokio-rustls"
version = "0.26.2"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
dependencies = [
"rustls",
"tokio",
......@@ -3867,9 +3713,9 @@ dependencies = [
[[package]]
name = "tokio-stream"
version = "0.1.17"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70"
dependencies = [
"futures-core",
"pin-project-lite",
......@@ -3878,12 +3724,10 @@ dependencies = [
[[package]]
name = "tokio-test"
version = "0.4.4"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7"
checksum = "3f6d24790a10a7af737693a3e8f1d03faef7e6ca0cc99aae5066f533766de545"
dependencies = [
"async-stream",
"bytes",
"futures-core",
"tokio",
"tokio-stream",
......@@ -3891,15 +3735,14 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.15"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"futures-util",
"hashbrown 0.15.2",
"pin-project-lite",
"slab",
"tokio",
......@@ -3923,14 +3766,14 @@ dependencies = [
"tokio",
"tokio-rustls",
"tokio-util",
"webpki-roots 0.26.8",
"webpki-roots 0.26.11",
]
[[package]]
name = "toml"
version = "0.8.21"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900f6c86a685850b1bc9f6223b20125115ee3f31e01207d81655bbcc0aea9231"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
......@@ -3940,18 +3783,18 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "0.6.9"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.25"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
......@@ -3963,15 +3806,15 @@ dependencies = [
[[package]]
name = "toml_write"
version = "0.1.0"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28391a4201ba7eb1984cfeb6862c0b3ea2cfe23332298967c749dddc0d6cd976"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "tonic"
version = "0.14.2"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
checksum = "7f32a6f80051a4111560201420c7885d0082ba9efe2ab61875c587bb6b18b9a0"
dependencies = [
"async-trait",
"axum",
......@@ -3986,7 +3829,7 @@ dependencies = [
"hyper-util",
"percent-encoding",
"pin-project",
"socket2 0.6.1",
"socket2 0.6.2",
"sync_wrapper",
"tokio",
"tokio-rustls",
......@@ -3999,21 +3842,21 @@ dependencies = [
[[package]]
name = "tonic-build"
version = "0.14.2"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c40aaccc9f9eccf2cd82ebc111adc13030d23e887244bc9cfa5d1d636049de3"
checksum = "ce6d8958ed3be404120ca43ffa0fb1e1fc7be214e96c8d33bd43a131b6eebc9e"
dependencies = [
"prettyplease",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "tonic-prost"
version = "0.14.2"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
checksum = "9f86539c0089bfd09b1f8c0ab0239d80392af74c21bc9e0f15e1b4aca4c1647f"
dependencies = [
"bytes",
"prost",
......@@ -4022,25 +3865,25 @@ dependencies = [
[[package]]
name = "tonic-prost-build"
version = "0.14.2"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4a16cba4043dc3ff43fcb3f96b4c5c154c64cbd18ca8dce2ab2c6a451d058a2"
checksum = "65873ace111e90344b8973e94a1fc817c924473affff24629281f90daed1cd2e"
dependencies = [
"prettyplease",
"proc-macro2",
"prost-build",
"prost-types",
"quote",
"syn 2.0.100",
"syn",
"tempfile",
"tonic-build",
]
[[package]]
name = "tower"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
dependencies = [
"futures-core",
"futures-util",
......@@ -4057,12 +3900,12 @@ dependencies = [
[[package]]
name = "tower-http"
version = "0.6.6"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [
"base64",
"bitflags 2.9.0",
"bitflags 2.11.0",
"bytes",
"futures-util",
"http",
......@@ -4090,9 +3933,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
version = "0.1.41"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"log",
"pin-project-lite",
......@@ -4102,20 +3945,20 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.28"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.33"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
"valuable",
......@@ -4134,16 +3977,13 @@ dependencies = [
[[package]]
name = "tracing-opentelemetry"
version = "0.32.0"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6e5658463dd88089aba75c7791e1d3120633b1bfde22478b28f625a9bb1b8e"
checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc"
dependencies = [
"js-sys",
"opentelemetry",
"opentelemetry_sdk",
"rustversion",
"smallvec",
"thiserror 2.0.17",
"tracing",
"tracing-core",
"tracing-log",
......@@ -4163,14 +4003,14 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"regex-automata",
"serde",
"serde_json",
"sharded-slab",
......@@ -4191,20 +4031,19 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "tryhard"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9f0a709784e86923586cff0d872dba54cd2d2e116b3bc57587d15737cfce9d"
checksum = "9fe58ebd5edd976e0fe0f8a14d2a04b7c81ef153ea9a54eebc42e67c2c23b4e5"
dependencies = [
"futures",
"pin-project-lite",
"tokio",
]
[[package]]
name = "typenum"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "ucd-trie"
......@@ -4223,15 +4062,21 @@ dependencies = [
[[package]]
name = "unicase"
version = "2.8.1"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]]
name = "unicode-ident"
version = "1.0.18"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "unsafe-libyaml"
......@@ -4247,22 +4092,17 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.4"
version = "2.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
"serde",
"serde_derive",
]
[[package]]
name = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8_iter"
version = "1.0.4"
......@@ -4271,13 +4111,13 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "uuid"
version = "1.18.1"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb"
dependencies = [
"getrandom 0.3.2",
"getrandom 0.4.1",
"js-sys",
"serde",
"serde_core",
"wasm-bindgen",
]
......@@ -4308,7 +4148,7 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -4319,9 +4159,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "version-compare"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
[[package]]
name = "version_check"
......@@ -4350,52 +4190,49 @@ dependencies = [
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
version = "0.14.2+wasi-0.2.4"
name = "wasip2"
version = "1.0.2+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
dependencies = [
"wit-bindgen-rt",
"wit-bindgen",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
name = "wasip3"
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"cfg-if 1.0.0",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wit-bindgen",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
name = "wasm-bindgen"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn 2.0.100",
"cfg-if 1.0.4",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.50"
version = "0.4.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f"
dependencies = [
"cfg-if 1.0.0",
"cfg-if 1.0.4",
"futures-util",
"js-sys",
"once_cell",
"wasm-bindgen",
......@@ -4404,9 +4241,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.100"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
......@@ -4414,26 +4251,48 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.100"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn 2.0.100",
"wasm-bindgen-backend",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.100"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-encoder"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
dependencies = [
"leb128fmt",
"wasmparser",
]
[[package]]
name = "wasm-metadata"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [
"anyhow",
"indexmap",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasm-streams"
version = "0.4.2"
......@@ -4447,11 +4306,23 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wasmparser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags 2.11.0",
"hashbrown 0.15.5",
"indexmap",
"semver",
]
[[package]]
name = "web-sys"
version = "0.3.77"
version = "0.3.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
dependencies = [
"js-sys",
"wasm-bindgen",
......@@ -4469,18 +4340,18 @@ dependencies = [
[[package]]
name = "webpki-roots"
version = "0.26.8"
version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
"rustls-pki-types",
"webpki-roots 1.0.6",
]
[[package]]
name = "webpki-roots"
version = "1.0.2"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed"
dependencies = [
"rustls-pki-types",
]
......@@ -4515,11 +4386,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
......@@ -4530,45 +4401,39 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.61.0"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.1.1",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.0"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.1"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "windows-link"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
[[package]]
name = "windows-link"
version = "0.2.1"
......@@ -4577,20 +4442,20 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-result"
version = "0.3.2"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link 0.1.1",
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.4.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link 0.1.1",
"windows-link",
]
[[package]]
......@@ -4611,15 +4476,6 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
......@@ -4635,7 +4491,7 @@ version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link 0.2.1",
"windows-link",
]
[[package]]
......@@ -4675,7 +4531,7 @@ version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link 0.2.1",
"windows-link",
"windows_aarch64_gnullvm 0.53.1",
"windows_aarch64_msvc 0.53.1",
"windows_i686_gnu 0.53.1",
......@@ -4826,33 +4682,106 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
version = "0.7.7"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
dependencies = [
"bitflags 2.9.0",
"wit-bindgen-rust-macro",
]
[[package]]
name = "write16"
version = "1.0.0"
name = "wit-bindgen-core"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
dependencies = [
"anyhow",
"heck",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
dependencies = [
"anyhow",
"heck",
"indexmap",
"prettyplease",
"syn",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
dependencies = [
"anyhow",
"prettyplease",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
]
[[package]]
name = "wit-component"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
"bitflags 2.11.0",
"indexmap",
"log",
"serde",
"serde_derive",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"semver",
"serde",
"serde_derive",
"serde_json",
"unicode-xid",
"wasmparser",
]
[[package]]
name = "writeable"
version = "0.5.5"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
[[package]]
name = "ws2_32-sys"
......@@ -4878,11 +4807,10 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "yoke"
version = "0.7.5"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
......@@ -4890,34 +4818,34 @@ dependencies = [
[[package]]
name = "yoke-derive"
version = "0.7.5"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
"synstructure",
]
[[package]]
name = "zerocopy"
version = "0.8.25"
version = "0.8.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.25"
version = "0.8.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
......@@ -4937,15 +4865,15 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
"synstructure",
]
[[package]]
name = "zeroize"
version = "1.8.1"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zeromq-src"
......@@ -4957,11 +4885,22 @@ dependencies = [
"dircpy",
]
[[package]]
name = "zerotrie"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
dependencies = [
"displaydoc",
"yoke",
"zerofrom",
]
[[package]]
name = "zerovec"
version = "0.10.4"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
dependencies = [
"yoke",
"zerofrom",
......@@ -4970,15 +4909,21 @@ dependencies = [
[[package]]
name = "zerovec-derive"
version = "0.10.3"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn",
]
[[package]]
name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
[[package]]
name = "zmq"
version = "0.10.0"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment