Skip to main content

AddressToIdMapper

Struct AddressToIdMapper 

Source
pub struct AddressToIdMapper<SA, A = CurrentStorage>
where SA: StorageMapperApi, A: StorageAddress<SA>,
{ /* private fields */ }
Expand description

A specialized bidirectional mapper between addresses and auto-incrementing numeric IDs.

§Storage Layout

The AddressToIdMapper maintains bidirectional mappings with sequential ID assignment:

  1. Address to ID mapping:

    • base_key + "addr" + encoded_address → assigned ID (u64)
  2. ID to address mapping:

    • base_key + "addrId" + id → address
  3. ID counter:

    • base_key + "lastId" → highest assigned ID (for generating new IDs)

§ID Assignment

  • IDs start from 1 and increment sequentially
  • NULL_ID (0) represents “no ID assigned” or “not found”
  • Once an ID is assigned, it remains associated with that address until explicitly removed
  • Removed IDs are not reused (IDs only increment, never decrement)

§Main Operations

  • Auto-insert: get_id_or_insert(address) - Gets ID or assigns new one if not exists. O(1).
  • Strict insert: insert_new(address) - Assigns ID only if address is new, errors if exists. O(1).
  • Lookup ID: get_id(address) - Returns ID for address (0 if not found). O(1).
  • Lookup Address: get_address(id) - Returns address for ID. O(1).
  • Contains: contains_id(id) - Checks if ID is assigned. O(1).
  • Remove by ID: remove_by_id(id) - Removes mapping by ID, returns address. O(1).
  • Remove by Address: remove_by_address(address) - Removes mapping by address, returns ID. O(1).
  • Counter: get_last_id() - Returns the highest assigned ID.

§Trade-offs

  • Pros: Sequential IDs are compact and predictable; auto-increment simplifies ID management; O(1) bidirectional lookup; no duplicate addresses.
  • Cons: IDs are never reused (gaps after removal); ID overflow at u64::MAX (unlikely but possible); slightly less flexible than generic BiDiMapper.

§Comparison with BiDiMapper

  • AddressToIdMapper: Specialized for addresses; auto-incrementing IDs; single type for IDs (u64)
  • BiDiMapper: Generic; manual ID/value assignment; supports any types for both sides

§Use Cases

  • User registration systems (address → user ID)
  • Whitelist/participant management with sequential numbering
  • Address indexing for efficient iteration
  • Mapping external addresses to internal compact IDs
  • Any scenario where addresses need numeric identifiers

§Example

// Auto-assign IDs (get or create)
let id1 = mapper.get_id_or_insert(&addr1);  // Returns 1
let id2 = mapper.get_id_or_insert(&addr2);  // Returns 2
let id1_again = mapper.get_id_or_insert(&addr1);  // Returns 1 (existing)

assert_eq!(id1, 1);
assert_eq!(id2, 2);
assert_eq!(id1_again, 1);
assert_eq!(mapper.get_last_id(), 2);

// Strict insert (errors if address already exists)
let id3 = mapper.insert_new(&addr3);  // Returns 3
assert_eq!(id3, 3);
// mapper.insert_new(&addr1);  // Would error: "Address already registered"

// Bidirectional lookup
assert_eq!(mapper.get_id(&addr1), 1);
assert_eq!(mapper.get_address(1), Some(addr1.clone()));

// Check existence
assert!(mapper.contains_id(2));
assert_eq!(mapper.get_id(&addr2), 2);  // Returns 2

// Non-zero lookup (errors if not found)
let id = mapper.get_id_non_zero(&addr1);  // Returns 1
assert_eq!(id, 1);
// mapper.get_id_non_zero(&unknown_addr);  // Would error: "Unknown address"

// Remove by address
let removed_id = mapper.remove_by_address(&addr2);
assert_eq!(removed_id, 2);
assert_eq!(mapper.get_id(&addr2), 0);  // Now returns NULL_ID
assert!(!mapper.contains_id(2));

// Remove by ID
let removed_addr = mapper.remove_by_id(1);
assert_eq!(removed_addr, Some(addr1.clone()));
assert_eq!(mapper.get_id(&addr1), 0);

// Note: next inserted address gets ID 4, not 2 (IDs never reused)

Implementations§

Source§

impl<SA, A> AddressToIdMapper<SA, A>
where SA: StorageMapperApi, A: StorageAddress<SA>,

Source

pub fn contains_id(&self, id: AddressId) -> bool

Source

pub fn get_id(&self, address: &ManagedAddress<SA>) -> AddressId

Source

pub fn get_id_non_zero(&self, address: &ManagedAddress<SA>) -> AddressId

Source

pub fn get_address(&self, id: AddressId) -> Option<ManagedAddress<SA>>

Source

pub fn get_last_id(&self) -> AddressId

Source§

impl<SA> AddressToIdMapper<SA, CurrentStorage>
where SA: StorageMapperApi,

Source

pub fn get_id_or_insert(&self, address: &ManagedAddress<SA>) -> AddressId

Source

pub fn insert_new(&self, address: &ManagedAddress<SA>) -> AddressId

Source

pub fn remove_by_id(&self, id: AddressId) -> Option<ManagedAddress<SA>>

Source

pub fn remove_by_address(&self, address: &ManagedAddress<SA>) -> AddressId

Trait Implementations§

Source§

impl<SA> StorageMapper<SA> for AddressToIdMapper<SA>
where SA: StorageMapperApi,

Source§

fn new(base_key: StorageKey<SA>) -> Self

Will be called automatically by the #[storage_mapper] annotation generated code.
Source§

impl<SA> StorageMapperFromAddress<SA> for AddressToIdMapper<SA, ManagedAddress<SA>>
where SA: StorageMapperApi,

Source§

fn new_from_address( address: ManagedAddress<SA>, base_key: StorageKey<SA>, ) -> Self

Will be called automatically by the #[storage_mapper_from_address] annotation generated code.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.