-
-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
area:coreCore compiler (parser, generator, IR, transform)Core compiler (parser, generator, IR, transform)type:enhancementImprovement to existing featureImprovement to existing featuretype:featureNew feature or functionalityNew feature or functionality
Description
Goal
Support const generic parameters for fixed-size arrays, enabling flexible array sizes without code duplication.
Phase: 5.3 Advanced Type System
Problem
Current array syntax is limited:
- ❌ Only supports
[T](dynamic Vec) - ❌ No fixed-size array support
[T; N] - ❌ Can't express Solana's common patterns (e.g.,
[u8; 32]for hashes) - ❌ Have to use Vec even when size is known
Solution
Add fixed-size array syntax with const generics.
Syntax
#[solana]
struct PlayerAccount {
wallet: PublicKey, // Already supported (32 bytes internally)
inventory: [PublicKey; 10], // NEW: Fixed-size array
data: [u8; 32], // NEW: Fixed 32 bytes
}
Generated Code
Rust
#[account]
pub struct PlayerAccount {
pub wallet: Pubkey,
pub inventory: [Pubkey; 10],
pub data: [u8; 32],
}TypeScript
export interface PlayerAccount {
wallet: PublicKey;
inventory: PublicKey[]; // Array of exactly 10 items
data: number[]; // Array of exactly 32 items
}
// Borsh schema
export const PlayerAccountBorshSchema = borsh.struct([
borsh.publicKey('wallet'),
borsh.array(borsh.publicKey(), 10, 'inventory'),
borsh.array(borsh.u8(), 32, 'data'),
]);Implementation
1. Parser Changes
Location: packages/core/src/parser.rs
pub enum Type {
// Existing...
Vec(Box<Type>),
// NEW
Array {
element: Box<Type>,
size: usize,
},
}
impl Type {
fn parse_array(input: &str) -> Result<Self, Error> {
// Parse [T; N]
// Extract element type T
// Extract size N (must be const)
}
}2. Validation
Location: packages/core/src/transform.rs
fn validate_array_size(size: usize) -> Result<(), Error> {
if size == 0 {
return Err("Array size must be > 0");
}
if size > 1024 {
return Err("Array size too large (max 1024)");
}
Ok(())
}3. Rust Generator
Location: packages/core/src/generators/rust.rs
fn generate_type(ty: &Type) -> String {
match ty {
Type::Array { element, size } => {
format!("[{}; {}]", generate_type(element), size)
}
// ... other cases
}
}4. TypeScript Generator
Location: packages/core/src/generators/typescript.rs
fn generate_borsh_schema_field(field: &Field) -> String {
match &field.ty {
Type::Array { element, size } => {
let elem_borsh = generate_borsh_type(element);
format!("borsh.array({}, {}, '{}')", elem_borsh, size, field.name)
}
// ... other cases
}
}Examples
Example 1: Solana Hash
struct Transaction {
hash: [u8; 32],
}
Example 2: Fixed Inventory
struct Player {
inventory_slots: [PublicKey; 50],
}
Example 3: Nested Arrays
struct Grid {
cells: [[u8; 10]; 10], // 10x10 grid
}
Borsh Serialization
Fixed arrays in Borsh:
- No length prefix (size known at compile time)
- More efficient than Vec
- Exact byte count
// Vec<u8> serialization: [length: 4 bytes] + [data: N bytes]
// [u8; 32] serialization: [data: 32 bytes] (no length prefix)Const Generics (Future Enhancement)
For now, only literal sizes supported:
inventory: [PublicKey; 10] // ✓ Supported
Future: Generic sizes
struct Holder<const N: usize> {
items: [PublicKey; N], // 🚧 Not yet supported
}
Testing
Unit Tests
#[test]
fn test_parse_fixed_array() {
let ty = parse_type("[u8; 32]");
assert!(matches!(ty, Type::Array { size: 32, .. }));
}
#[test]
fn test_array_size_validation() {
assert!(validate_array_size(0).is_err());
assert!(validate_array_size(10).is_ok());
assert!(validate_array_size(2000).is_err());
}
#[test]
fn test_generate_rust_array() {
let ty = Type::Array {
element: Box::new(Type::U8),
size: 32,
};
assert_eq!(generate_type(&ty), "[u8; 32]");
}Integration Tests
- Parse schema with fixed arrays
- Generate Rust code
- Compile and verify size
- Generate TypeScript
- Verify Borsh serialization
E2E Tests
#[test]
fn test_fixed_array_serialization() {
let data = PlayerAccount {
inventory: [Pubkey::default(); 10],
};
let serialized = data.try_to_vec().unwrap();
// Verify size = 10 * 32 bytes = 320 bytes (no length prefix)
assert_eq!(serialized.len(), 320);
}Success Criteria
- Parser accepts
[T; N]syntax - Validates array size (1-1024)
- Generates correct Rust fixed arrays
- Generates correct TypeScript Borsh schema
- Borsh serialization works without length prefix
- Supports nested arrays
- All tests passing
- Documentation with examples
Documentation
Update Files
-
docs/syntax.md- Document fixed array syntax -
docs/types.md- Add array type section -
README.md- Add fixed array example -
CHANGELOG.md- Document new feature -
ROADMAP.md- Mark Phase 5.3 item as complete ✅
Related
- ROADMAP.md Phase 5.3 - Advanced Type System
Priority: High (common Solana pattern)
Complexity: Medium
Timeline: 3-4 days
📌 Remember: Update ROADMAP.md after completing this issue!
Metadata
Metadata
Assignees
Labels
area:coreCore compiler (parser, generator, IR, transform)Core compiler (parser, generator, IR, transform)type:enhancementImprovement to existing featureImprovement to existing featuretype:featureNew feature or functionalityNew feature or functionality