1#![deny(missing_docs)]
5#![cfg_attr(not(test), forbid(unsafe_code))]
6
7extern crate self as spl_discriminator;
8
9pub mod discriminator;
11
12pub use {
14 discriminator::{ArrayDiscriminator, SplDiscriminate},
15 spl_discriminator_derive::SplDiscriminate,
16};
17
18#[cfg(test)]
19mod tests {
20 use {super::*, crate::discriminator::ArrayDiscriminator};
21
22 #[allow(dead_code)]
23 #[derive(SplDiscriminate)]
24 #[discriminator_hash_input("my_first_instruction")]
25 pub struct MyInstruction1 {
26 arg1: String,
27 arg2: u8,
28 }
29
30 #[allow(dead_code)]
31 #[derive(SplDiscriminate)]
32 #[discriminator_hash_input("global:my_second_instruction")]
33 pub enum MyInstruction2 {
34 One,
35 Two,
36 Three,
37 }
38
39 #[allow(dead_code)]
40 #[derive(SplDiscriminate)]
41 #[discriminator_hash_input("global:my_instruction_with_lifetime")]
42 pub struct MyInstruction3<'a> {
43 data: &'a [u8],
44 }
45
46 #[allow(dead_code)]
47 #[derive(SplDiscriminate)]
48 #[discriminator_hash_input("global:my_instruction_with_one_generic")]
49 pub struct MyInstruction4<T> {
50 data: T,
51 }
52
53 #[allow(dead_code)]
54 #[derive(SplDiscriminate)]
55 #[discriminator_hash_input("global:my_instruction_with_one_generic_and_lifetime")]
56 pub struct MyInstruction5<'b, T> {
57 data: &'b [T],
58 }
59
60 #[allow(dead_code)]
61 #[derive(SplDiscriminate)]
62 #[discriminator_hash_input("global:my_instruction_with_multiple_generics_and_lifetime")]
63 pub struct MyInstruction6<'c, U, V> {
64 data1: &'c [U],
65 data2: &'c [V],
66 }
67
68 #[allow(dead_code)]
69 #[derive(SplDiscriminate)]
70 #[discriminator_hash_input(
71 "global:my_instruction_with_multiple_generics_and_lifetime_and_where"
72 )]
73 pub struct MyInstruction7<'c, U, V>
74 where
75 U: Clone + Copy,
76 V: Clone + Copy,
77 {
78 data1: &'c [U],
79 data2: &'c [V],
80 }
81
82 fn assert_discriminator<T: spl_discriminator::discriminator::SplDiscriminate>(
83 hash_input: &str,
84 ) {
85 let discriminator = build_discriminator(hash_input);
86 assert_eq!(
87 T::SPL_DISCRIMINATOR,
88 discriminator,
89 "Discriminator mismatch: case: {}",
90 hash_input
91 );
92 assert_eq!(
93 T::SPL_DISCRIMINATOR_SLICE,
94 discriminator.as_slice(),
95 "Discriminator mismatch: case: {}",
96 hash_input
97 );
98 }
99
100 fn build_discriminator(hash_input: &str) -> ArrayDiscriminator {
101 let preimage = miraland_program::hash::hashv(&[hash_input.as_bytes()]);
102 let mut bytes = [0u8; 8];
103 bytes.copy_from_slice(&preimage.to_bytes()[..8]);
104 ArrayDiscriminator::new(bytes)
105 }
106
107 #[test]
108 fn test_discrminators() {
109 let runtime_discrim = ArrayDiscriminator::new_with_hash_input("my_runtime_hash_input");
110 assert_eq!(
111 runtime_discrim,
112 build_discriminator("my_runtime_hash_input"),
113 );
114
115 assert_discriminator::<MyInstruction1>("my_first_instruction");
116 assert_discriminator::<MyInstruction2>("global:my_second_instruction");
117 assert_discriminator::<MyInstruction3<'_>>("global:my_instruction_with_lifetime");
118 assert_discriminator::<MyInstruction4<u8>>("global:my_instruction_with_one_generic");
119 assert_discriminator::<MyInstruction5<'_, u8>>(
120 "global:my_instruction_with_one_generic_and_lifetime",
121 );
122 assert_discriminator::<MyInstruction6<'_, u8, u8>>(
123 "global:my_instruction_with_multiple_generics_and_lifetime",
124 );
125 assert_discriminator::<MyInstruction7<'_, u8, u8>>(
126 "global:my_instruction_with_multiple_generics_and_lifetime_and_where",
127 );
128 }
129}
130
131#[cfg(all(test, feature = "borsh"))]
132mod borsh_test {
133 use super::*;
134
135 #[test]
136 fn borsh_test() {
137 let my_discrim = ArrayDiscriminator::new_with_hash_input("my_discrim");
138 let mut buffer = [0u8; 8];
139 my_discrim.serialize(&mut buffer[..]).unwrap();
140 let my_discrim_again = ArrayDiscriminator::try_from_slice(&buffer).unwrap();
141 assert_eq!(my_discrim, my_discrim_again);
142 assert_eq!(buf, my_discrim.into());
143 }
144}