@@ -42,10 +42,10 @@ where
4242
4343 /// Load the number of instructions in the currently executing `Transaction`.
4444 #[ inline( always) ]
45- pub fn num_instructions ( & self ) -> u16 {
45+ pub fn num_instructions ( & self ) -> usize {
4646 // SAFETY: The first 2 bytes of the Instructions sysvar data represents the
4747 // number of instructions.
48- unsafe { u16:: from_le_bytes ( * ( self . data . as_ptr ( ) as * const [ u8 ; 2 ] ) ) }
48+ u16:: from_le_bytes ( unsafe { * ( self . data . as_ptr ( ) as * const [ u8 ; 2 ] ) } ) as usize
4949 }
5050
5151 /// Load the current `Instruction`'s index in the currently executing
7575 . as_ptr ( )
7676 . add ( size_of :: < u16 > ( ) + index * size_of :: < u16 > ( ) ) as * const u16 ) ;
7777
78- IntrospectedInstruction {
79- raw : self . data . as_ptr ( ) . add ( offset as usize ) ,
80- marker : PhantomData ,
81- }
78+ IntrospectedInstruction :: new_unchecked ( self . data . as_ptr ( ) . add ( offset as usize ) )
8279 }
8380
8481 /// Creates and returns an `IntrospectedInstruction` for the instruction at the specified index.
8784 & self ,
8885 index : usize ,
8986 ) -> Result < IntrospectedInstruction , ProgramError > {
90- if index >= self . num_instructions ( ) as usize {
87+ if index >= self . num_instructions ( ) {
9188 return Err ( ProgramError :: InvalidInstructionData ) ;
9289 }
9390
@@ -133,10 +130,34 @@ impl<'a> TryFrom<&'a AccountView> for Instructions<Ref<'a, [u8]>> {
133130#[ derive( Clone , Debug , Eq , PartialEq ) ]
134131pub struct IntrospectedInstruction < ' a > {
135132 pub raw : * const u8 ,
136- pub marker : PhantomData < & ' a [ u8 ] > ,
133+ marker : PhantomData < & ' a [ u8 ] > ,
137134}
138135
139136impl IntrospectedInstruction < ' _ > {
137+ /// Create a new IntrospectedInstruction.
138+ ///
139+ /// # Safety
140+ ///
141+ /// This function is unsafe because it does not verify anything about the pointer.
142+ ///
143+ /// It is private and used internally within the `get_instruction_account_at` function, which
144+ /// performs the necessary index verification. However, to optimize performance for users
145+ /// who are sure that the index is in bounds, we have exposed it as an unsafe function.
146+ #[ inline( always) ]
147+ unsafe fn new_unchecked ( raw : * const u8 ) -> Self {
148+ Self {
149+ raw,
150+ marker : PhantomData ,
151+ }
152+ }
153+
154+ /// Load the number of instructions in the currently executing `Transaction`.
155+ #[ inline( always) ]
156+ pub fn num_account_metas ( & self ) -> usize {
157+ // SAFETY: The first 2 bytes represent the number of accounts in the instruction.
158+ u16:: from_le_bytes ( unsafe { * ( self . raw as * const [ u8 ; 2 ] ) } ) as usize
159+ }
160+
140161 /// Get the instruction account at the specified index.
141162 ///
142163 /// # Safety
@@ -166,9 +187,9 @@ impl IntrospectedInstruction<'_> {
166187 index : usize ,
167188 ) -> Result < & IntrospectedInstructionAccount , ProgramError > {
168189 // SAFETY: The first 2 bytes represent the number of accounts in the instruction.
169- let num_accounts = u16 :: from_le_bytes ( unsafe { * ( self . raw as * const [ u8 ; 2 ] ) } ) ;
190+ let num_accounts = self . num_account_metas ( ) ;
170191
171- if index >= num_accounts as usize {
192+ if index >= num_accounts {
172193 return Err ( ProgramError :: InvalidArgument ) ;
173194 }
174195
@@ -180,24 +201,23 @@ impl IntrospectedInstruction<'_> {
180201 #[ inline( always) ]
181202 pub fn get_program_id ( & self ) -> & Address {
182203 // SAFETY: The first 2 bytes represent the number of accounts in the instruction.
183- let num_accounts = u16 :: from_le_bytes ( unsafe { * ( self . raw as * const [ u8 ; 2 ] ) } ) ;
204+ let num_accounts = self . num_account_metas ( ) ;
184205
185206 // SAFETY: The program ID is located after the instruction accounts.
186207 unsafe {
187- & * ( self . raw . add (
188- size_of :: < u16 > ( )
189- + num_accounts as usize * size_of :: < IntrospectedInstructionAccount > ( ) ,
190- ) as * const Address )
208+ & * ( self
209+ . raw
210+ . add ( size_of :: < u16 > ( ) + num_accounts * size_of :: < IntrospectedInstructionAccount > ( ) )
211+ as * const Address )
191212 }
192213 }
193214
194215 /// Get the instruction data of the `Instruction`.
195216 #[ inline( always) ]
196217 pub fn get_instruction_data ( & self ) -> & [ u8 ] {
197218 // SAFETY: The first 2 bytes represent the number of accounts in the instruction.
198- let offset = u16:: from_le_bytes ( unsafe { * ( self . raw as * const [ u8 ; 2 ] ) } ) as usize
199- * size_of :: < IntrospectedInstructionAccount > ( )
200- + ADDRESS_BYTES ;
219+ let offset =
220+ self . num_account_metas ( ) * size_of :: < IntrospectedInstructionAccount > ( ) + ADDRESS_BYTES ;
201221
202222 // SAFETY: The instruction data length is located after the program ID.
203223 let data_len = u16:: from_le_bytes ( unsafe {
0 commit comments