Most programs support multiple discrete instructions - you decide when writing your program what these instructions are and what data must accompany them
Rust enums are often used to represent discrete program instructions.
enum NoteInstruction {
CreateNote {
title: String,
body: String,
id: u64
},
UpdateNote {
title: String,
body: String,
id: u64
},
DeleteNote {
id: u64
}
}
Given these instructions, it's standard practice to structure your program to expect the first byte (or other fixed number of bytes) to be an identifier for which instruction the program should run. This could be an integer or a string identifier. For this example, we'll use the first byte and map integers 0, 1, and 2 to instructions create, update, and delete, respectively.
impl NoteInstruction {
// Unpack inbound buffer to associated Instruction
// The expected format for input is a Borsh serialized vector
pub fn unpack(input: &[u8]) -> Result<Self, ProgramError> {
// Take the first byte as the variant to
// determine which instruction to execute
let (&variant, rest) = input.split_first().ok_or(ProgramError::InvalidInstructionData)?;
// Use the temporary payload struct to deserialize
let payload = NoteInstructionPayload::try_from_slice(rest).unwrap();
// Match the variant to determine which data struct is expected by
// the function and return the TestStruct or an error
Ok(match variant {
0 => Self::CreateNote {
title: payload.title,
body: payload.body,
id: payload.id
},
1 => Self::UpdateNote {
title: payload.title,
body: payload.body,
id: payload.id
},
2 => Self::DeleteNote {
id: payload.id
},
_ => return Err(ProgramError::InvalidInstructionData)
})
}
}
There's a lot in this example so let's take it one step at a time:
This function starts by using the split_first function on the input parameter to return a tuple. The first element, variant, is the first byte from the byte array and the second element, rest, is the rest of the byte array.
The function then uses the try_from_slice method on NoteInstructionPayload to deserialize the rest of the byte array into an instance of NoteInstructionPayload called payload
Finally, the function uses a match statement on variant to create and return the appropriate enum instance using information from payload
Will advise you to go through this module on the Solana course to see in detail how this works