derive_usage/
derive_usage.rs1#[cfg(feature = "derive")]
11fn main() {
12 use std::str::FromStr;
13 use synta::{
14 BitString, FromDer, Integer, ObjectIdentifier, OctetString, PrintableString, ToDer, UtcTime,
15 };
16 use synta_derive::{Asn1Choice, Asn1Sequence};
17
18 println!("=== Derive Macro Usage Example ===\n");
19
20 #[derive(Asn1Sequence, Debug, Clone)]
27 struct AlgorithmIdentifier {
28 algorithm: ObjectIdentifier,
29 parameters: Option<OctetString>,
30 }
31
32 #[derive(Asn1Sequence, Debug, Clone)]
37 struct Validity {
38 not_before: UtcTime,
39 not_after: UtcTime,
40 }
41
42 #[derive(Asn1Sequence, Debug, Clone)]
47 struct Name {
48 common_name: PrintableString,
49 }
50
51 #[derive(Asn1Sequence, Debug, Clone)]
60 struct TBSCertificate {
61 #[asn1(tag(0, explicit))]
62 version: Option<Integer>,
63 serial_number: Integer,
64 signature: AlgorithmIdentifier,
65 issuer: Name,
66 validity: Validity,
67 subject: Name,
68 }
69
70 #[derive(Asn1Sequence, Debug, Clone)]
76 struct Certificate {
77 tbs_certificate: TBSCertificate,
78 signature_algorithm: AlgorithmIdentifier,
79 signature_value: BitString,
80 }
81
82 #[derive(Asn1Choice, Debug, Clone)]
88 enum Time {
89 Utc(UtcTime),
90 }
93
94 println!("1. Creating Certificate Structure\n");
95
96 let alg_id = AlgorithmIdentifier {
98 algorithm: ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap(), parameters: None,
100 };
101
102 let validity = Validity {
103 not_before: UtcTime::new(2024, 1, 1, 0, 0, 0).unwrap(),
104 not_after: UtcTime::new(2025, 1, 1, 0, 0, 0).unwrap(),
105 };
106
107 let issuer = Name {
108 common_name: PrintableString::new("Example CA".to_string()).unwrap(),
109 };
110
111 let subject = Name {
112 common_name: PrintableString::new("example.com".to_string()).unwrap(),
113 };
114
115 let tbs = TBSCertificate {
116 version: Some(Integer::from(2)), serial_number: Integer::from(123456),
118 signature: alg_id.clone(),
119 issuer: issuer.clone(),
120 validity,
121 subject,
122 };
123
124 let cert = Certificate {
125 tbs_certificate: tbs,
126 signature_algorithm: alg_id,
127 signature_value: BitString::new(vec![0xDE, 0xAD, 0xBE, 0xEF], 0).unwrap(),
128 };
129
130 println!("Created certificate with:");
131 println!(" - Version: v3");
132 println!(" - Serial: 123456");
133 println!(" - Algorithm: SHA-256 with RSA (1.2.840.113549.1.1.11)");
134 println!(" - Issuer: Example CA");
135 println!(" - Subject: example.com");
136
137 println!("\n2. Encoding Certificate\n");
138
139 let encoded = cert.to_der().expect("Failed to encode certificate");
141
142 println!("Encoded certificate: {} bytes", encoded.len());
143 println!(
144 "First 32 bytes: {:02X?}...",
145 &encoded[..32.min(encoded.len())]
146 );
147
148 println!("\n3. Decoding Certificate\n");
149
150 let decoded_cert = Certificate::from_der(&encoded).expect("Failed to decode certificate");
152
153 println!("Successfully decoded certificate!");
154 println!(
155 " - Serial number matches: {}",
156 decoded_cert.tbs_certificate.serial_number.as_i64().unwrap() == 123456
157 );
158 println!(
159 " - Version matches: {}",
160 decoded_cert.tbs_certificate.version.is_some()
161 );
162
163 println!("\n4. Tagged Fields Example\n");
164
165 println!("Version field uses [0] EXPLICIT tag");
168 println!("This wrapping is automatic with #[asn1(tag(0, explicit))]");
169
170 println!("\n5. CHOICE Type Example\n");
171
172 let time = Time::Utc(UtcTime::new(2024, 6, 15, 12, 30, 0).unwrap());
174
175 let encoded_time = time.to_der().expect("Failed to encode time");
176 println!("Encoded CHOICE (Time): {} bytes", encoded_time.len());
177
178 let decoded_time = Time::from_der(&encoded_time).expect("Failed to decode time");
179
180 match decoded_time {
181 Time::Utc(utc) => println!("Decoded UTC time: {:?}", utc),
182 }
183
184 println!("\n=== Summary ===\n");
185 println!("Derive macros eliminate ~150 lines of boilerplate per struct!");
186 println!("No manual Encode/Decode/Tagged implementations needed.");
187 println!("Tagged fields (#[asn1(tag(...))]) are handled automatically.");
188 println!("CHOICE types work seamlessly with enums.");
189}
190
191#[cfg(not(feature = "derive"))]
192fn main() {
193 println!("This example requires the 'derive' feature.");
194 println!("Run with: cargo run --example derive_usage --features derive");
195}