Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lang/derive/space/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ fn len_from_type(ty: Type, attrs: &mut Option<VecDeque<TokenStream2>>) -> TokenS
}
}
}
Type::Tuple(ty_tuple) => {
let recurse = ty_tuple
.elems
.iter()
.map(|t| len_from_type(t.clone(), attrs));
quote! {
(0 #(+ #recurse)*)
}
}
_ => panic!("Type {ty:?} is not supported"),
}
}
Expand Down
109 changes: 109 additions & 0 deletions lang/tests/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,38 @@ pub struct TestUnnamedStruct(
#[derive(InitSpace)]
pub struct TestUnitStruct;

#[derive(InitSpace)]
#[allow(clippy::type_complexity)]
pub struct TestTupleStruct {
pub test_tuple: (u8, u16, u32, u64, u128),
pub mixed_tuple: (bool, f32, f64, i8, i16, i32, i64, i128),

pub nested_tuple: (u8, (u16, u32, u64, u128)),
pub deeply_nested: (u8, (u16, (u32, (u64, u128)))),
pub complex_nested: (bool, (u8, u16), (u32, (u64, u128))),

pub option_tuple: Option<(u8, u16, u32, u64, u128)>,
pub tuple_with_option: (u8, Option<u16>, u32),
pub nested_option_tuple: (u8, Option<(u16, u32)>, u64),

pub pubkey_tuple: (Pubkey, u64),
pub tuple_with_pubkeys: (Pubkey, Pubkey, u8),

pub struct_tuple: (ChildStruct, u8),
pub nested_struct_tuple: (u8, (ChildStruct, u16)),

pub single_tuple: (u64,),
pub single_nested: ((u8,),),

pub empty_tuple: (),
pub tuple_with_empty: (u8, (), u16),

pub array_tuple: ([u8; 4], u16),
pub tuple_array_nested: (u8, ([u16; 2], u32)),

pub ultimate_complex: (u8, (bool, Option<(u16, u32)>, ChildStruct), Pubkey),
}

#[test]
fn test_empty_struct() {
assert_eq!(TestEmptyAccount::INIT_SPACE, 0);
Expand Down Expand Up @@ -172,3 +204,80 @@ fn test_unnamed_struct() {
fn test_unit_struct() {
assert_eq!(TestUnitStruct::INIT_SPACE, 0)
}

#[test]
fn test_basic_tuple() {
let basic_tuple_size = 1 + 2 + 4 + 8 + 16; // 31
assert!(TestTupleStruct::INIT_SPACE >= basic_tuple_size);
}

#[test]
fn test_tuple_space_calculations() {
let basic_tuple_size = 1 + 2 + 4 + 8 + 16; // 31

let mixed_tuple_size = 1 + 4 + 8 + 1 + 2 + 4 + 8 + 16; // 44

let nested_tuple_size = 1 + (2 + 4 + 8 + 16); // 31

let option_tuple_size = 1 + (1 + 2 + 4 + 8 + 16); // 32

let pubkey_tuple_size = 32 + 8; // 40

let single_tuple_size = 8;

let empty_tuple_size = 0;

let minimum_expected_size = basic_tuple_size
+ mixed_tuple_size
+ nested_tuple_size
+ option_tuple_size
+ pubkey_tuple_size
+ single_tuple_size
+ empty_tuple_size;

assert!(TestTupleStruct::INIT_SPACE >= minimum_expected_size);
}

#[test]
fn test_tuple_with_structs() {
// Test that tuples containing other structs work correctly
// struct_tuple: (ChildStruct, u8) = ChildStruct::INIT_SPACE + 1
let expected_struct_tuple_contribution = ChildStruct::INIT_SPACE + 1;

assert!(TestTupleStruct::INIT_SPACE >= expected_struct_tuple_contribution);
}

#[test]
fn test_nested_tuple_complexity() {
// Test deeply_nested: (u8, (u16, (u32, (u64, u128))))
// = 1 + (2 + (4 + (8 + 16))) = 1 + (2 + (4 + 24)) = 1 + (2 + 28) = 1 + 30 = 31
let deeply_nested_size = 1 + 2 + 4 + 8 + 16; // 31

// Test complex_nested: (bool, (u8, u16), (u32, (u64, u128)))
// = 1 + (1 + 2) + (4 + (8 + 16)) = 1 + 3 + (4 + 24) = 1 + 3 + 28 = 32
let complex_nested_size = 1 + (1 + 2) + (4 + (8 + 16)); // 32

assert!(TestTupleStruct::INIT_SPACE >= deeply_nested_size + complex_nested_size);
}

#[test]
fn test_tuple_with_options() {
// tuple_with_option: (u8, Option<u16>, u32) = 1 + (1 + 2) + 4 = 8
let tuple_with_option_size = 1 + (1 + 2) + 4; // 8

// nested_option_tuple: (u8, Option<(u16, u32)>, u64) = 1 + (1 + (2 + 4)) + 8 = 16
let nested_option_tuple_size = 1 + (1 + (2 + 4)) + 8; // 16

assert!(TestTupleStruct::INIT_SPACE >= tuple_with_option_size + nested_option_tuple_size);
}

#[test]
fn test_tuple_with_arrays() {
// array_tuple: ([u8; 4], u16) = (4 * 1) + 2 = 6
let array_tuple_size = 4 + 2; // 6

// tuple_array_nested: (u8, ([u16; 2], u32)) = 1 + ((2 * 2) + 4) = 1 + (4 + 4) = 9
let tuple_array_nested_size = 1 + ((2 * 2) + 4); // 9

assert!(TestTupleStruct::INIT_SPACE >= array_tuple_size + tuple_array_nested_size);
}