@@ -19,7 +19,7 @@ pub enum Type {
1919 /// The first element is the Python class that represents the sequence,
2020 /// the second element is a dict of the (already converted) fields of the class.
2121 Sequence ( pyo3:: Py < pyo3:: types:: PyType > , pyo3:: Py < pyo3:: types:: PyDict > ) ,
22- /// SEQUENCEOF (`list[`T`]`)
22+ /// SEQUENCE OF (`list[`T`]`)
2323 SequenceOf ( pyo3:: Py < AnnotatedType > ) ,
2424 /// OPTIONAL (`T | None`)
2525 Option ( pyo3:: Py < AnnotatedType > ) ,
@@ -40,6 +40,8 @@ pub enum Type {
4040 UtcTime ( ) ,
4141 /// GeneralizedTime (`datetime`)
4242 GeneralizedTime ( ) ,
43+ /// BIT STRING (`bytes`)
44+ BitString ( ) ,
4345}
4446
4547/// A type that we know how to encode/decode, along with any
@@ -94,7 +96,6 @@ impl Annotation {
9496 }
9597 }
9698
97- #[ pyo3( signature = ( ) ) ]
9899 fn is_empty ( & self ) -> bool {
99100 self . default . is_none ( ) && self . encoding . is_none ( ) && self . size . is_none ( )
100101 }
@@ -148,7 +149,6 @@ impl PrintableString {
148149 Ok ( PrintableString { inner } )
149150 }
150151
151- #[ pyo3( signature = ( ) ) ]
152152 pub fn as_str ( & self , py : pyo3:: Python < ' _ > ) -> pyo3:: PyResult < pyo3:: Py < pyo3:: types:: PyString > > {
153153 Ok ( self . inner . clone_ref ( py) )
154154 }
@@ -192,7 +192,6 @@ impl UtcTime {
192192 Ok ( UtcTime { inner } )
193193 }
194194
195- #[ pyo3( signature = ( ) ) ]
196195 pub fn as_datetime (
197196 & self ,
198197 py : pyo3:: Python < ' _ > ,
@@ -232,7 +231,6 @@ impl GeneralizedTime {
232231 Ok ( GeneralizedTime { inner } )
233232 }
234233
235- #[ pyo3( signature = ( ) ) ]
236234 pub fn as_datetime (
237235 & self ,
238236 py : pyo3:: Python < ' _ > ,
@@ -249,6 +247,52 @@ impl GeneralizedTime {
249247 }
250248}
251249
250+ #[ derive( pyo3:: FromPyObject ) ]
251+ #[ pyo3:: pyclass( frozen, module = "cryptography.hazmat.bindings._rust.asn1" ) ]
252+ pub struct BitString {
253+ pub ( crate ) data : pyo3:: Py < pyo3:: types:: PyBytes > ,
254+ pub ( crate ) padding_bits : u8 ,
255+ }
256+
257+ #[ pyo3:: pymethods]
258+ impl BitString {
259+ #[ new]
260+ #[ pyo3( signature = ( data, padding_bits, ) ) ]
261+ fn new (
262+ py : pyo3:: Python < ' _ > ,
263+ data : pyo3:: Py < pyo3:: types:: PyBytes > ,
264+ padding_bits : u8 ,
265+ ) -> pyo3:: PyResult < Self > {
266+ if asn1:: BitString :: new ( data. as_bytes ( py) , padding_bits) . is_none ( ) {
267+ return Err ( pyo3:: exceptions:: PyValueError :: new_err ( format ! (
268+ "invalid BIT STRING: data: {data}, padding_bits: {padding_bits}"
269+ ) ) ) ;
270+ }
271+
272+ Ok ( BitString { data, padding_bits } )
273+ }
274+
275+ pub fn as_bytes ( & self , py : pyo3:: Python < ' _ > ) -> pyo3:: Py < pyo3:: types:: PyBytes > {
276+ self . data . clone_ref ( py)
277+ }
278+
279+ pub fn padding_bits ( & self ) -> u8 {
280+ self . padding_bits
281+ }
282+
283+ fn __eq__ ( & self , py : pyo3:: Python < ' _ > , other : pyo3:: PyRef < ' _ , Self > ) -> pyo3:: PyResult < bool > {
284+ Ok ( ( * * self . data . bind ( py) ) . eq ( other. data . bind ( py) ) ?
285+ && self . padding_bits == other. padding_bits )
286+ }
287+
288+ pub fn __repr__ ( & self ) -> pyo3:: PyResult < String > {
289+ Ok ( format ! (
290+ "BitString(data={}, padding_bits={})" ,
291+ self . data, self . padding_bits,
292+ ) )
293+ }
294+ }
295+
252296/// Utility function for converting builtin Python types
253297/// to their Rust `Type` equivalent.
254298#[ pyo3:: pyfunction]
@@ -270,6 +314,8 @@ pub fn non_root_python_to_rust<'p>(
270314 Type :: UtcTime ( ) . into_pyobject ( py)
271315 } else if class. is ( GeneralizedTime :: type_object ( py) ) {
272316 Type :: GeneralizedTime ( ) . into_pyobject ( py)
317+ } else if class. is ( BitString :: type_object ( py) ) {
318+ Type :: BitString ( ) . into_pyobject ( py)
273319 } else {
274320 Err ( pyo3:: exceptions:: PyTypeError :: new_err ( format ! (
275321 "cannot handle type: {class:?}"
@@ -326,6 +372,7 @@ pub(crate) fn type_to_tag(t: &Type, encoding: &Option<pyo3::Py<Encoding>>) -> as
326372 Type :: PrintableString ( ) => asn1:: PrintableString :: TAG ,
327373 Type :: UtcTime ( ) => asn1:: UtcTime :: TAG ,
328374 Type :: GeneralizedTime ( ) => asn1:: GeneralizedTime :: TAG ,
375+ Type :: BitString ( ) => asn1:: BitString :: TAG ,
329376 } ;
330377
331378 match encoding {
0 commit comments