1use pyo3::prelude::*;
4
5use synta::Encoder;
6
7use super::error::SyntaErr;
8
9use super::types::{
10 PyBitString, PyBmpString, PyBoolean, PyGeneralString, PyGeneralizedTime, PyIA5String,
11 PyInteger, PyNull, PyNumericString, PyObjectIdentifier, PyOctetString, PyPrintableString,
12 PyReal, PyTeletexString, PyUniversalString, PyUtcTime, PyUtf8String, PyVisibleString,
13};
14use super::PyEncoding;
15
16#[pyclass(name = "Encoder")]
25pub struct PyEncoder {
26 encoder: Encoder,
27}
28
29#[pymethods]
30impl PyEncoder {
31 #[new]
36 fn new(encoding: PyEncoding) -> Self {
37 Self {
38 encoder: Encoder::new(encoding.into()),
39 }
40 }
41
42 fn encode_integer(
53 &mut self,
54 py: Python,
55 value: &Bound<'_, pyo3::types::PyAny>,
56 ) -> PyResult<()> {
57 if let Ok(v) = value.extract::<i64>() {
59 self.encoder
60 .encode(&synta::Integer::from_i64(v))
61 .map_err(SyntaErr)?;
62 return Ok(());
63 }
64 if let Ok(v) = value.extract::<i128>() {
66 self.encoder
67 .encode(&synta::Integer::from_i128(v))
68 .map_err(SyntaErr)?;
69 return Ok(());
70 }
71 let bit_len: usize = value
75 .call_method0(pyo3::intern!(py, "bit_length"))?
76 .extract()?;
77 let byte_len = ((bit_len + 8) / 8).max(1);
78 let kwargs = pyo3::types::PyDict::new(py);
79 kwargs.set_item(pyo3::intern!(py, "signed"), true)?;
80 let raw: Vec<u8> = value
81 .call_method(
82 pyo3::intern!(py, "to_bytes"),
83 (byte_len, pyo3::intern!(py, "big")),
84 Some(&kwargs),
85 )?
86 .extract()?;
87 self.encoder
88 .encode(&synta::Integer::from_bytes(&raw))
89 .map_err(SyntaErr)?;
90 Ok(())
91 }
92
93 fn encode_integer_object(&mut self, value: &PyInteger) -> PyResult<()> {
98 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
99 Ok(())
100 }
101
102 fn encode_octet_string(&mut self, data: &[u8]) -> PyResult<()> {
107 let octet_string = synta::OctetStringRef::new(data);
108 self.encoder.encode(&octet_string).map_err(SyntaErr)?;
109 Ok(())
110 }
111
112 fn encode_octet_string_object(&mut self, value: &PyOctetString) -> PyResult<()> {
117 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
118 Ok(())
119 }
120
121 fn encode_oid(&mut self, value: &PyObjectIdentifier) -> PyResult<()> {
126 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
127 Ok(())
128 }
129
130 fn encode_oid_object(&mut self, value: &PyObjectIdentifier) -> PyResult<()> {
132 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
133 Ok(())
134 }
135
136 fn encode_bit_string(&mut self, value: &PyBitString) -> PyResult<()> {
141 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
142 Ok(())
143 }
144
145 fn encode_bit_string_object(&mut self, value: &PyBitString) -> PyResult<()> {
147 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
148 Ok(())
149 }
150
151 fn encode_boolean(&mut self, value: bool) -> PyResult<()> {
156 let boolean = synta::Boolean::new(value);
157 self.encoder.encode(&boolean).map_err(SyntaErr)?;
158 Ok(())
159 }
160
161 fn encode_boolean_object(&mut self, value: &PyBoolean) -> PyResult<()> {
166 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
167 Ok(())
168 }
169
170 fn encode_utc_time(&mut self, value: &PyUtcTime) -> PyResult<()> {
175 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
176 Ok(())
177 }
178
179 fn encode_utc_time_object(&mut self, value: &PyUtcTime) -> PyResult<()> {
181 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
182 Ok(())
183 }
184
185 fn encode_generalized_time(&mut self, value: &PyGeneralizedTime) -> PyResult<()> {
190 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
191 Ok(())
192 }
193
194 fn encode_generalized_time_object(&mut self, value: &PyGeneralizedTime) -> PyResult<()> {
196 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
197 Ok(())
198 }
199
200 fn encode_real(&mut self, value: f64) -> PyResult<()> {
205 let real = synta::Real::new(value);
206 self.encoder.encode(&real).map_err(SyntaErr)?;
207 Ok(())
208 }
209
210 fn encode_real_object(&mut self, value: &PyReal) -> PyResult<()> {
215 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
216 Ok(())
217 }
218
219 fn encode_null(&mut self) -> PyResult<()> {
221 self.encoder.encode(&synta::Null).map_err(SyntaErr)?;
222 Ok(())
223 }
224
225 fn encode_null_object(&mut self, _value: &PyNull) -> PyResult<()> {
227 self.encoder.encode(&synta::Null).map_err(SyntaErr)?;
228 Ok(())
229 }
230
231 fn encode_utf8_string(&mut self, value: &str) -> PyResult<()> {
236 let s = synta::Utf8String::new(value.to_string());
237 self.encoder.encode(&s).map_err(SyntaErr)?;
238 Ok(())
239 }
240
241 fn encode_utf8_string_object(&mut self, value: &PyUtf8String) -> PyResult<()> {
243 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
244 Ok(())
245 }
246
247 fn encode_printable_string(&mut self, value: &str) -> PyResult<()> {
252 let s = synta::PrintableString::new(value.to_string()).map_err(|e| {
253 pyo3::exceptions::PyValueError::new_err(format!("Invalid PrintableString: {:?}", e))
254 })?;
255 self.encoder.encode(&s).map_err(SyntaErr)?;
256 Ok(())
257 }
258
259 fn encode_printable_string_object(&mut self, value: &PyPrintableString) -> PyResult<()> {
261 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
262 Ok(())
263 }
264
265 fn encode_ia5_string(&mut self, value: &str) -> PyResult<()> {
270 let s = synta::IA5String::new(value.to_string()).map_err(|e| {
271 pyo3::exceptions::PyValueError::new_err(format!("Invalid IA5String: {:?}", e))
272 })?;
273 self.encoder.encode(&s).map_err(SyntaErr)?;
274 Ok(())
275 }
276
277 fn encode_ia5_string_object(&mut self, value: &PyIA5String) -> PyResult<()> {
279 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
280 Ok(())
281 }
282
283 fn encode_numeric_string(&mut self, value: &str) -> PyResult<()> {
285 let s = synta::NumericString::new(value.to_string()).map_err(|e| {
286 pyo3::exceptions::PyValueError::new_err(format!("Invalid NumericString: {:?}", e))
287 })?;
288 self.encoder.encode(&s).map_err(SyntaErr)?;
289 Ok(())
290 }
291
292 fn encode_numeric_string_object(&mut self, value: &PyNumericString) -> PyResult<()> {
294 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
295 Ok(())
296 }
297
298 fn encode_teletex_string(&mut self, data: &[u8]) -> PyResult<()> {
300 let s = synta::TeletexString::new(data.to_vec());
301 self.encoder.encode(&s).map_err(SyntaErr)?;
302 Ok(())
303 }
304
305 fn encode_teletex_string_object(&mut self, value: &PyTeletexString) -> PyResult<()> {
307 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
308 Ok(())
309 }
310
311 fn encode_visible_string(&mut self, value: &str) -> PyResult<()> {
313 let s = synta::VisibleString::new(value.to_string()).map_err(|e| {
314 pyo3::exceptions::PyValueError::new_err(format!("Invalid VisibleString: {:?}", e))
315 })?;
316 self.encoder.encode(&s).map_err(SyntaErr)?;
317 Ok(())
318 }
319
320 fn encode_visible_string_object(&mut self, value: &PyVisibleString) -> PyResult<()> {
322 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
323 Ok(())
324 }
325
326 fn encode_general_string(&mut self, data: &[u8]) -> PyResult<()> {
328 let s = synta::GeneralString::new(data.to_vec());
329 self.encoder.encode(&s).map_err(SyntaErr)?;
330 Ok(())
331 }
332
333 fn encode_general_string_object(&mut self, value: &PyGeneralString) -> PyResult<()> {
335 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
336 Ok(())
337 }
338
339 fn encode_universal_string(&mut self, value: &str) -> PyResult<()> {
341 let s = synta::UniversalString::new(value.to_string());
342 self.encoder.encode(&s).map_err(SyntaErr)?;
343 Ok(())
344 }
345
346 fn encode_universal_string_object(&mut self, value: &PyUniversalString) -> PyResult<()> {
348 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
349 Ok(())
350 }
351
352 fn encode_bmp_string(&mut self, value: &str) -> PyResult<()> {
356 let s = synta::BmpString::new(value.to_string()).map_err(|e| {
357 pyo3::exceptions::PyValueError::new_err(format!("Invalid BMPString: {:?}", e))
358 })?;
359 self.encoder.encode(&s).map_err(SyntaErr)?;
360 Ok(())
361 }
362
363 fn encode_bmp_string_object(&mut self, value: &PyBmpString) -> PyResult<()> {
365 self.encoder.encode(&value.inner).map_err(SyntaErr)?;
366 Ok(())
367 }
368
369 fn encode_sequence(&mut self, inner_bytes: &[u8]) -> PyResult<()> {
384 use synta::tag::TAG_SEQUENCE;
385 self.encoder
386 .write_tag(synta::Tag::universal_constructed(TAG_SEQUENCE))
387 .map_err(SyntaErr)?;
388 self.encoder
389 .write_length(inner_bytes.len())
390 .map_err(SyntaErr)?;
391 self.encoder.write_bytes(inner_bytes);
392 Ok(())
393 }
394
395 fn encode_set(&mut self, inner_bytes: &[u8]) -> PyResult<()> {
397 use synta::tag::TAG_SET;
398 self.encoder
399 .write_tag(synta::Tag::universal_constructed(TAG_SET))
400 .map_err(SyntaErr)?;
401 self.encoder
402 .write_length(inner_bytes.len())
403 .map_err(SyntaErr)?;
404 self.encoder.write_bytes(inner_bytes);
405 Ok(())
406 }
407
408 fn encode_explicit_tag(
418 &mut self,
419 tag_num: u32,
420 tag_class: &str,
421 inner_bytes: &[u8],
422 ) -> PyResult<()> {
423 use pyo3::exceptions::PyValueError;
424 use synta::tag::TagClass;
425
426 let class = match tag_class {
427 "Context" => TagClass::ContextSpecific,
428 "Application" => TagClass::Application,
429 "Private" => TagClass::Private,
430 other => {
431 return Err(PyValueError::new_err(format!(
432 "Unknown tag class '{}'; expected 'Context', 'Application', or 'Private'",
433 other
434 )))
435 }
436 };
437 let tag = synta::Tag::new(class, true, tag_num);
439 self.encoder.write_tag(tag).map_err(SyntaErr)?;
440 self.encoder
441 .write_length(inner_bytes.len())
442 .map_err(SyntaErr)?;
443 self.encoder.write_bytes(inner_bytes);
444 Ok(())
445 }
446
447 fn encode_implicit_tag(
461 &mut self,
462 tag_num: u32,
463 tag_class: &str,
464 is_constructed: bool,
465 value_bytes: &[u8],
466 ) -> PyResult<()> {
467 use pyo3::exceptions::PyValueError;
468 use synta::tag::TagClass;
469
470 let class = match tag_class {
471 "Context" => TagClass::ContextSpecific,
472 "Application" => TagClass::Application,
473 "Private" => TagClass::Private,
474 other => {
475 return Err(PyValueError::new_err(format!(
476 "Unknown tag class '{other}'; expected 'Context', 'Application', or 'Private'",
477 )))
478 }
479 };
480 let tag = synta::Tag::new(class, is_constructed, tag_num);
481 self.encoder.write_tag(tag).map_err(SyntaErr)?;
482 self.encoder
483 .write_length(value_bytes.len())
484 .map_err(SyntaErr)?;
485 self.encoder.write_bytes(value_bytes);
486 Ok(())
487 }
488
489 fn finish<'py>(&mut self, py: Python<'py>) -> PyResult<Bound<'py, pyo3::types::PyBytes>> {
494 let encoding = self.encoder.encoding();
496 let encoder = std::mem::replace(&mut self.encoder, Encoder::new(encoding));
497 let bytes = encoder.finish().map_err(SyntaErr)?;
498 Ok(pyo3::types::PyBytes::new(py, &bytes))
499 }
500
501 fn __repr__(&self) -> String {
502 format!("Encoder(encoding={:?})", self.encoder.encoding())
503 }
504}