Skip to content

feat: add array map#1991

Merged
ananas-block merged 1 commit intomainfrom
jorrit/feat-array-map
Oct 14, 2025
Merged

feat: add array map#1991
ananas-block merged 1 commit intomainfrom
jorrit/feat-array-map

Conversation

@ananas-block
Copy link
Contributor

@ananas-block ananas-block commented Oct 13, 2025

Summary by CodeRabbit

  • New Features

    • Added a lightweight, no_std-compatible fixed-capacity array-backed map with key-based lookups and optimized support for 32-byte keys.
    • Added a method to access a public key's underlying 32-byte array.
  • Tests

    • Added comprehensive tests for creation, insertion, retrieval, mutation, capacity limits, and last-updated tracking.
  • Chores

    • Updated CI to run tests for the new map utility.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 13, 2025

Walkthrough

Adds a new no_std crate light-array-map (ArrayMap) with tests and workspace/CI integration, introduces tinyvec dependency, and adds Pubkey::array_ref() to compressed-account.

Changes

Cohort / File(s) Summary
Workspace & CI integration
Cargo.toml, .github/workflows/rust.yml
Add program-libs/array-map workspace member; expose light-array-map = { path = "program-libs/array-map", version = "0.1.0" } and tinyvec = "1.10.0" in workspace dependencies; CI updated to run tests for light-array-map (fast group, --all-features).
ArrayMap crate manifest
program-libs/array-map/Cargo.toml
New crate manifest for light-array-map (v0.1.0) with metadata and dependency on tinyvec.
ArrayMap implementation
program-libs/array-map/src/lib.rs
New no_std ArrayMap<K,V,const N:usize> backed by tinyvec::ArrayVec: constructors, len/is_empty, indexed and key-based get/find/get_mut/find_mut, insert with capacity error handling, last-updated index tracking, specialized fast helpers for [u8; 32] pubkeys, ArrayMapError enum, and pubkey_eq const fn.
ArrayMap tests
program-libs/array-map/tests/array_map_tests.rs
New test module covering creation, insertion, lookups by index/key/pubkey, mutable access, index finding, last-updated tracking, capacity errors, and helper methods; introduces a test-specific error wrapper for conversions.
Compressed-account Pubkey
program-libs/compressed-account/src/pubkey.rs
Add pub fn array_ref(&self) -> &[u8; 32] accessor on Pubkey.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant AM as ArrayMap<K,V,N>
  Note over Client,AM: high-level ArrayMap interactions

  Client->>AM: new()
  Client->>AM: insert(key, value, error_token)
  alt capacity available
    AM-->>Client: Ok(index)
  else capacity exceeded
    AM-->>Client: Err(ArrayMapError::CapacityExceeded.into())
  end

  Client->>AM: find(&key)
  alt found
    AM-->>Client: Some((index, &(K,V)))
    Note right of AM: update last_updated_index
  else not found
    AM-->>Client: None
  end

  Client->>AM: get(index)
  alt in-bounds
    AM-->>Client: Some(&(K,V))
  else out-of-bounds
    AM-->>Client: None
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • sergeytimoshin
  • SwenSchaeferjohann

Poem

I’m a rabbit with a tiny map in paw,
Keys snug in rows with no big flaw.
I hop to insert, I hop to find,
Last-touch remembered, tidy and kind.
Tests hum, pubkeys shown—hop, hooray! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.21% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “feat: add array map” clearly and concisely summarizes the primary change of introducing the ArrayMap data structure to the codebase without extraneous detail or jargon. It directly references the main feature addition and is easily understood by reviewers scanning PR history. There is no misleading or unrelated content.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jorrit/feat-array-map

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (13)
.github/workflows/rust.yml (1)

48-65: Also build light-array-map in no_std to catch regressions early

Mirror light-zero-copy by adding a no-default-features build for light-array-map.

           cargo test -p aligned-sized
+          cargo build -p light-array-map --no-default-features  # Ensure no_std builds
           cargo test -p light-array-map --all-features
program-libs/compressed-account/src/pubkey.rs (1)

78-80: array_ref() addition is useful; consider also implementing AsRef<[u8; 32]>

This makes the API more idiomatic for consumers that want a typed 32-byte reference.

Outside this hunk, add:

impl AsRef<[u8; 32]> for Pubkey {
    fn as_ref(&self) -> &[u8; 32] {
        &self.0
    }
}
program-libs/array-map/tests/array_map_tests.rs (2)

43-45: Avoid temporary String allocations in assertions

Compare by str to prevent needless allocs and borrowed temporaries.

-    assert_eq!(map.get_by_key(&1), Some(&"one".to_string()));
-    assert_eq!(map.get_by_key(&2), Some(&"two".to_string()));
+    assert_eq!(map.get_by_key(&1).map(String::as_str), Some("one"));
+    assert_eq!(map.get_by_key(&2).map(String::as_str), Some("two"));

1-14: Add tests for pubkey-optimized accessors

Cover get_by_pubkey/find_pubkey_index and pubkey_eq to ensure the fast-path stays correct.

I can draft a small test using ArrayMap<[u8; 32], u8, 4> with a few fixed keys if helpful.

program-libs/array-map/src/lib.rs (8)

10-12: Doc nit: clarify last_accessed_index semantics

Currently it’s updated on insert and via set_last_accessed_index, not on reads.

-/// Maintains insertion order and tracks the last accessed entry index.
+/// Maintains insertion order.
+/// Tracks an optional `last_accessed_index`, updated on insert and via `set_last_accessed_index`.

12-19: Remove unnecessary Default bounds from ArrayMap

K/V don’t need Default for current operations; keeping only K: PartialEq widens usability.

-pub struct ArrayMap<K, V, const N: usize>
-where
-    K: PartialEq + Default,
-    V: Default,
-{
+pub struct ArrayMap<K, V, const N: usize>
+where
+    K: PartialEq,
+{

21-25: Same here: drop Default bounds in impl block

No methods rely on Default.

-impl<K, V, const N: usize> ArrayMap<K, V, N>
-where
-    K: PartialEq + Default,
-    V: Default,
-{
+impl<K, V, const N: usize> ArrayMap<K, V, N>
+where
+    K: PartialEq,
+{

110-118: Default impl doesn’t require K/V: Default

Tighten bounds to match actual needs.

-impl<K, V, const N: usize> Default for ArrayMap<K, V, N>
-where
-    K: PartialEq + Default,
-    V: Default,
-{
+impl<K, V, const N: usize> Default for ArrayMap<K, V, N>
+where
+    K: PartialEq,
+{

120-124: Specialization for [u8; 32]: V doesn’t need Default

Drop the bound to keep API flexible.

-impl<V, const N: usize> ArrayMap<[u8; 32], V, N>
-where
-    V: Default,
-{
+impl<V, const N: usize> ArrayMap<[u8; 32], V, N> {

99-107: Consider using CapacityExceeded variant instead of passing an error token

You already define ArrayMapError::CapacityExceeded and require E: From; returning that (via .into()) simplifies the API and avoids threading an error value through all callsites.

If you want to keep both behaviors, we can add try_insert(&mut self, key, value) -> Result<usize, ArrayMapError> and keep insert as-is.


158-171: ArrayMapError::CapacityExceeded is currently unused

Either use it in insert (preferred) or remove to reduce API surface.


173-184: Avoid const on pubkey_eq to reduce MSRV pressure

read_unaligned in const contexts depends on newer compilers. Unless you rely on const-eval here, a plain inline fn is safer for MSRV.

-#[inline(always)]
-pub const fn pubkey_eq(p1: &[u8; 32], p2: &[u8; 32]) -> bool {
+#[inline(always)]
+pub fn pubkey_eq(p1: &[u8; 32], p2: &[u8; 32]) -> bool {

If you prefer keeping it const, please confirm the workspace rust-version supports ptr::read_unaligned in const fns (and set rust-version accordingly).

Cargo.toml (1)

64-67: Add workspace rust-version to Cargo.toml
Under [workspace.package], add rust-version = "1.90.0" (to match your rust-toolchain.toml channel) and lock the MSRV:

[workspace.package]
 version = "0.1.0"
 edition = "2021"
+rust-version = "1.90.0"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af746de and fd17280.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .github/workflows/rust.yml (1 hunks)
  • Cargo.toml (2 hunks)
  • program-libs/array-map/Cargo.toml (1 hunks)
  • program-libs/array-map/src/lib.rs (1 hunks)
  • program-libs/array-map/tests/array_map_tests.rs (1 hunks)
  • program-libs/compressed-account/src/pubkey.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/**/Cargo.toml : Define features solana, pinocchio, and test-only in Cargo.toml; default build should enable none

Applied to files:

  • .github/workflows/rust.yml
🧬 Code graph analysis (1)
program-libs/array-map/tests/array_map_tests.rs (1)
program-libs/array-map/src/lib.rs (9)
  • new (26-31)
  • len (33-35)
  • is_empty (37-39)
  • last_accessed_index (41-43)
  • get (45-47)
  • get_by_key (61-63)
  • find_index (83-85)
  • get_u8 (53-55)
  • get_mut_u8 (57-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: cli-v2
  • GitHub Check: system-programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-syst...
  • GitHub Check: system-programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test ...
  • GitHub Check: system-programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-t...
  • GitHub Check: system-programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip te...
  • GitHub Check: system-programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test...
  • GitHub Check: system-programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_addre...
  • GitHub Check: system-programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test",...
  • GitHub Check: system-programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_c...
  • GitHub Check: stateless-js-v2
  • GitHub Check: Test program-libs-slow
  • GitHub Check: stateless-js-v1
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client, cargo test...
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: lint
  • GitHub Check: cli-v1
🔇 Additional comments (1)
program-libs/array-map/Cargo.toml (1)

1-14: Manifest looks good

Clear features, workspace dep wiring, license and metadata are correct.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (10)
program-libs/compressed-account/src/pubkey.rs (1)

78-80: Accessor looks good; consider adding inline and AsRef<[u8; 32]>

  • Add #[inline(always)] to hint inlining.
  • Provide impl AsRef<[u8; 32]> for Pubkey to integrate with generic APIs taking AsRef<[u8;32]>.
  • Optional: alias name as as_array() for consistency with as_ref/as_bytes-style API.

Example:

     pub fn array_ref(&self) -> &[u8; 32] {
         &self.0
     }
+
+    #[inline(always)]
+    pub fn as_array(&self) -> &[u8; 32] {
+        &self.0
+    }

And add:

 impl AsRef<[u8]> for Pubkey {
     fn as_ref(&self) -> &[u8] {
         &self.0
     }
 }
+
+impl AsRef<[u8; 32]> for Pubkey {
+    fn as_ref(&self) -> &[u8; 32] {
+        &self.0
+    }
+}
program-libs/array-map/Cargo.toml (1)

9-14: Clarify/justify the alloc feature; it may be a no‑op here

This crate currently uses ArrayVec only; enabling tinyvec/alloc affects TinyVec, not ArrayVec. If the intent is merely to gate certain tests (heap-allocated value types), consider:

  • Keeping the feature but document its purpose; or
  • Gating tests with cfg(feature = "alloc") via a dev‑feature, not forwarding tinyvec/alloc; or
  • Removing the feature until TinyVec is introduced.

Based on learnings

program-libs/array-map/tests/array_map_tests.rs (3)

43-45: Avoid allocs in asserts

Constructing String in assertions allocates. Compare as &str instead:

-    assert_eq!(map.get_by_key(&1), Some(&"one".to_string()));
-    assert_eq!(map.get_by_key(&2), Some(&"two".to_string()));
+    assert_eq!(map.get_by_key(&1).map(|s| s.as_str()), Some("one"));
+    assert_eq!(map.get_by_key(&2).map(|s| s.as_str()), Some("two"));

58-59: Same here: compare as &str

-    assert_eq!(map.get_by_key(&1), Some(&"ONE".to_string()));
+    assert_eq!(map.get_by_key(&1).map(|s| s.as_str()), Some("ONE"));

141-186: Add coverage for pubkey-optimized methods

Please add tests for [u8; 32] key specialization:

  • get_by_pubkey / get_mut_by_pubkey
  • find_by_pubkey / find_mut_by_pubkey / find_pubkey_index

I can draft a test module if helpful.

program-libs/array-map/src/lib.rs (4)

10-12: Doc/behavior mismatch: “tracks last accessed index” but accessors don’t update it

Currently only insert() and set_last_accessed_index() update the field; get*/find* do not. Either:

  • Update the doc to “tracks last inserted or explicitly set index”, or
  • Update successful get*/find* paths to set last_accessed_index.

Minimal doc fix:

-/// Maintains insertion order and tracks the last accessed entry index.
+/// Maintains insertion order and tracks the last inserted (or explicitly set) entry index.

Or update, e.g., get():

 pub fn get(&self, index: usize) -> Option<&(K, V)> {
-    self.entries.get(index)
+    let r = self.entries.get(index);
+    if r.is_some() {
+        // SAFETY: requires &mut; consider making `self` mutable or providing a separate accessor that mutates state.
+    }
+    r
 }

If you choose to track access on reads, prefer dedicated mutating accessors (e.g., get_and_track) to avoid hidden interior mutability.


99-107: Provide a standardized capacity error path (non-alloc friendly)

Insert returns a caller-provided error; meanwhile ArrayMapError::CapacityExceeded exists but isn’t used here. Consider adding a sibling API that uses it:

pub fn try_insert<E>(&mut self, key: K, value: V) -> Result<usize, E>
where
    E: From<ArrayMapError>,
{
    let new_idx = self.entries.len();
    if self.entries.try_push((key, value)).is_some() {
        return Err(ArrayMapError::CapacityExceeded.into());
    }
    self.last_accessed_index = Some(new_idx);
    Ok(new_idx)
}

This keeps insert for custom error types while offering a consistent default.


125-156: Generalize pubkey APIs to accept any AsRef<[u8; 32]>

To reduce friction with types like Pubkey that can expose an array ref, consider:

-pub fn get_by_pubkey(&self, key: &[u8; 32]) -> Option<&V> {
+pub fn get_by_pubkey<T: AsRef<[u8; 32]>>(&self, key: T) -> Option<&V> {
-    self.entries.iter().find(|(k, _)| pubkey_eq(k, key)).map(|(_, v)| v)
+    let key = key.as_ref();
+    self.entries.iter().find(|(k, _)| pubkey_eq(k, key)).map(|(_, v)| v)
}

Apply similarly to get_mut_by_pubkey/find*/find*_index.


173-184: Simplify pubkey_eq to safe slice equality

At program-libs/array-map/src/lib.rs:173–184, replace the const fn and unsafe block with:

#[inline(always)]
pub fn pubkey_eq(p1: &[u8; 32], p2: &[u8; 32]) -> bool {
    p1 == p2
}

LLVM will optimize this to a fast memcmp, removing unsafe and avoiding any const stability concerns.

.github/workflows/rust.yml (1)

45-47: Also build light-array-map in no_std mode

Add a no-default-features build to ensure the no_std crate compiles without std:

               cargo test -p aligned-sized
+              cargo build -p light-array-map --no-default-features
               cargo test -p light-array-map --all-features

Also applies to: 50-50

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af746de and fd17280.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .github/workflows/rust.yml (1 hunks)
  • Cargo.toml (2 hunks)
  • program-libs/array-map/Cargo.toml (1 hunks)
  • program-libs/array-map/src/lib.rs (1 hunks)
  • program-libs/array-map/tests/array_map_tests.rs (1 hunks)
  • program-libs/compressed-account/src/pubkey.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/**/Cargo.toml : Define features solana, pinocchio, and test-only in Cargo.toml; default build should enable none

Applied to files:

  • .github/workflows/rust.yml
🧬 Code graph analysis (1)
program-libs/array-map/tests/array_map_tests.rs (1)
program-libs/array-map/src/lib.rs (9)
  • new (26-31)
  • len (33-35)
  • is_empty (37-39)
  • last_accessed_index (41-43)
  • get (45-47)
  • get_by_key (61-63)
  • find_index (83-85)
  • get_u8 (53-55)
  • get_mut_u8 (57-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: cli-v2
  • GitHub Check: system-programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-syst...
  • GitHub Check: system-programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test ...
  • GitHub Check: system-programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-t...
  • GitHub Check: system-programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip te...
  • GitHub Check: system-programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test...
  • GitHub Check: system-programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_addre...
  • GitHub Check: system-programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test",...
  • GitHub Check: system-programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_c...
  • GitHub Check: stateless-js-v2
  • GitHub Check: Test program-libs-slow
  • GitHub Check: stateless-js-v1
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client, cargo test...
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: lint
  • GitHub Check: cli-v1

@ananas-block ananas-block force-pushed the jorrit/feat-array-map branch 2 times, most recently from 7a3fcf4 to 3d94c88 Compare October 13, 2025 16:50
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
program-libs/array-map/src/lib.rs (3)

96-104: Ergonomics: add a non-allocating, canonical try_insert returning ArrayMapError

Current insert forces constructing an error value even on success and leaves CapacityExceeded unused. Keep insert for custom errors, but add a canonical try_insert that returns ArrayMapError.

     pub fn insert<E>(&mut self, key: K, value: V, error: E) -> Result<usize, E> {
         let new_idx = self.entries.len();
         // tinyvec's try_push returns Some(item) on failure, None on success
         if self.entries.try_push((key, value)).is_some() {
             return Err(error);
         }
         self.last_accessed_index = Some(new_idx);
         Ok(new_idx)
     }
+
+    /// Insert without requiring a pre-constructed error; returns a canonical error on overflow.
+    pub fn try_insert(&mut self, key: K, value: V) -> Result<usize, ArrayMapError> {
+        let new_idx = self.entries.len();
+        if self
+            .entries
+            .try_push((key, value))
+            .is_some()
+        {
+            return Err(ArrayMapError::CapacityExceeded);
+        }
+        self.last_accessed_index = Some(new_idx);
+        Ok(new_idx)
+    }

30-36: Add capacity() helper

Exposing fixed capacity helps callers preflight inserts without attempting them.

     pub fn is_empty(&self) -> bool {
         self.entries.is_empty()
     }
 
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        N
+    }

170-181: Replace pubkey_eq with safe slice equality

The current const fn + unsafe impl isn’t needed for comparing fixed‐size arrays, adds risk, and may break older MSRVs—simplify to:

 #[inline(always)]
-pub const fn pubkey_eq(p1: &[u8; 32], p2: &[u8; 32]) -> bool {
-    let p1_ptr = p1.as_ptr() as *const u64;
-    let p2_ptr = p2.as_ptr() as *const u64;
-
-    unsafe {
-        read_unaligned(p1_ptr) == read_unaligned(p2_ptr)
-            && read_unaligned(p1_ptr.add(1)) == read_unaligned(p2_ptr.add(1))
-            && read_unaligned(p1_ptr.add(2)) == read_unaligned(p2_ptr.add(2))
-            && read_unaligned(p1_ptr.add(3)) == read_unaligned(p2_ptr.add(3))
-    }
-}
+pub fn pubkey_eq(p1: &[u8; 32], p2: &[u8; 32]) -> bool {
+    p1 == p2
+}

And remove the unused import:

-use core::ptr::read_unaligned;

If you need a const fn or observed a perf benefit, please provide benchmarks and confirm your MSRV supports const equality.

program-libs/array-map/tests/array_map_tests.rs (2)

43-45: Avoid temporary String allocations in assertions

Compare by &str to remove needless allocations and temporaries.

-    assert_eq!(map.get_by_key(&1), Some(&"one".to_string()));
-    assert_eq!(map.get_by_key(&2), Some(&"two".to_string()));
+    assert_eq!(map.get_by_key(&1).map(String::as_str), Some("one"));
+    assert_eq!(map.get_by_key(&2).map(String::as_str), Some("two"));

1-198: Add coverage for pubkey-optimized APIs

No tests cover get_by_pubkey/get_mut_by_pubkey/find_pubkey_index or pubkey_eq. Add a small test to exercise the [u8; 32] path.

#[test]
fn test_pubkey_apis() {
    let mut m = ArrayMap::<[u8; 32], u32, 4>::new();
    let a = [1u8; 32];
    let b = [2u8; 32];

    // try_insert variant if added; otherwise use insert with a custom error.
    m.try_insert(a, 10).unwrap();
    m.try_insert(b, 20).unwrap();

    assert!(light_array_map::pubkey_eq(&a, &a));
    assert!(!light_array_map::pubkey_eq(&a, &b));

    assert_eq!(m.get_by_pubkey(&a), Some(&10));
    assert_eq!(m.find_pubkey_index(&b), Some(1));
    if let Some(v) = m.get_mut_by_pubkey(&b) {
        *v += 1;
    }
    assert_eq!(m.get_by_pubkey(&b), Some(&21));
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd17280 and 3d94c88.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .github/workflows/rust.yml (1 hunks)
  • Cargo.toml (2 hunks)
  • program-libs/array-map/Cargo.toml (1 hunks)
  • program-libs/array-map/src/lib.rs (1 hunks)
  • program-libs/array-map/tests/array_map_tests.rs (1 hunks)
  • program-libs/compressed-account/src/pubkey.rs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • program-libs/array-map/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (1)
  • Cargo.toml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/**/Cargo.toml : Define features solana, pinocchio, and test-only in Cargo.toml; default build should enable none

Applied to files:

  • .github/workflows/rust.yml
🧬 Code graph analysis (1)
program-libs/array-map/tests/array_map_tests.rs (1)
program-libs/array-map/src/lib.rs (9)
  • new (23-28)
  • len (30-32)
  • is_empty (34-36)
  • last_accessed_index (38-40)
  • get (42-44)
  • get_by_key (58-60)
  • find_index (80-82)
  • get_u8 (50-52)
  • get_mut_u8 (54-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: cli-v1
  • GitHub Check: stateless-js-v1
  • GitHub Check: lint
  • GitHub Check: stateless-js-v2
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client, cargo test...
  • GitHub Check: system-programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test ...
  • GitHub Check: system-programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-t...
  • GitHub Check: system-programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test",...
  • GitHub Check: system-programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-syst...
  • GitHub Check: system-programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip te...
  • GitHub Check: system-programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test...
  • GitHub Check: system-programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_c...
  • GitHub Check: system-programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_addre...
  • GitHub Check: Test program-libs-slow
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: cli-v2

@ananas-block ananas-block force-pushed the jorrit/feat-array-map branch from 3d94c88 to e0b67df Compare October 13, 2025 18:52
@ananas-block ananas-block force-pushed the jorrit/feat-array-map branch from e0b67df to e19435c Compare October 13, 2025 19:05
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
program-libs/compressed-account/src/pubkey.rs (1)

78-80: LGTM! Useful addition for typed array access.

The method provides efficient typed access to the internal byte array by reference, filling the gap between the slice reference from AsRef<[u8]> and the owned copy from to_bytes(). This is particularly useful for interfacing with code that expects &[u8; 32], such as the new array-map crate mentioned in the PR.

Optional: Consider adding doc comments for clarity.

While the method name is self-explanatory, adding a brief doc comment could help clarify when to use this method versus the alternatives:

/// Returns a reference to the 32-byte array.
///
/// Use this when you need a reference to the sized array type `&[u8; 32]`.
/// For a slice reference `&[u8]`, use `AsRef::<[u8]>::as_ref()`.
/// For an owned copy, use `to_bytes()`.
pub fn array_ref(&self) -> &[u8; 32] {
    &self.0
}
.github/workflows/rust.yml (1)

45-51: Add a no_std build check for light-array-map.

Thanks for wiring the new crate into CI. Because light-array-map is advertised as no_std, we should mirror what we do for other no_std crates (e.g., light-zero-copy) and add a --no-default-features build to catch regressions early. Right now we only exercise --all-features, so a future change could silently break the no_std configuration.

Suggested patch:

               cargo test -p light-macros
               cargo test -p aligned-sized
+              cargo build -p light-array-map --no-default-features
               cargo test -p light-array-map --all-features
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0b67df and e19435c.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .github/workflows/rust.yml (1 hunks)
  • Cargo.toml (2 hunks)
  • program-libs/array-map/Cargo.toml (1 hunks)
  • program-libs/array-map/src/lib.rs (1 hunks)
  • program-libs/array-map/tests/array_map_tests.rs (1 hunks)
  • program-libs/compressed-account/src/pubkey.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • program-libs/array-map/Cargo.toml
  • program-libs/array-map/tests/array_map_tests.rs
  • Cargo.toml
  • program-libs/array-map/src/lib.rs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-11T21:59:25.201Z
Learnt from: CR
PR: Lightprotocol/light-protocol#0
File: program-libs/account-checks/CLAUDE.md:0-0
Timestamp: 2025-10-11T21:59:25.201Z
Learning: Applies to program-libs/account-checks/**/Cargo.toml : Define features solana, pinocchio, and test-only in Cargo.toml; default build should enable none

Applied to files:

  • .github/workflows/rust.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: system-programs (system-cpi-test-v2-functional-account-infos, ["cargo-test-sbf -p system-cpi-v2-t...
  • GitHub Check: system-programs (compressed-token-and-e2e, ["cargo-test-sbf -p compressed-token-test -- --skip te...
  • GitHub Check: system-programs (system-cpi-test-v2-functional-read-only, ["cargo-test-sbf -p system-cpi-v2-test ...
  • GitHub Check: system-programs (account-compression-and-registry, ["cargo-test-sbf -p account-compression-test",...
  • GitHub Check: system-programs (light-system-program-address, ["cargo-test-sbf -p system-test -- test_with_addre...
  • GitHub Check: system-programs (compressed-token-batched-tree, ["cargo-test-sbf -p compressed-token-test -- test...
  • GitHub Check: system-programs (light-system-program-compression, ["cargo-test-sbf -p system-test -- test_with_c...
  • GitHub Check: system-programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test", "cargo test -p light-syst...
  • GitHub Check: stateless-js-v2
  • GitHub Check: cli-v2
  • GitHub Check: stateless-js-v1
  • GitHub Check: Test program-libs-fast
  • GitHub Check: Test program-libs-slow
  • GitHub Check: system-programs (sdk-libs, light-sdk-macros light-sdk light-program-test light-client, cargo test...
  • GitHub Check: Test batched-merkle-tree-simulate
  • GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-native-test", "cargo-test-sbf -p sdk-v...
  • GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test", "cargo-test-sbf -...
  • GitHub Check: lint
  • GitHub Check: cli-v1

Copy link
Contributor

@SwenSchaeferjohann SwenSchaeferjohann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where use?

@ananas-block
Copy link
Contributor Author

Instead of a hash map. for example to store hashes in the ctoken program.

@ananas-block ananas-block merged commit 7aafcb5 into main Oct 14, 2025
29 checks passed
@ananas-block ananas-block deleted the jorrit/feat-array-map branch October 14, 2025 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants