• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use proc_macro::TokenStream;
2 
encode_components(components: &[num_bigint::BigUint], relative: bool) -> Vec<u8>3 fn encode_components(components: &[num_bigint::BigUint], relative: bool) -> Vec<u8> {
4     use num_traits::cast::ToPrimitive;
5 
6     let mut enc = Vec::new();
7     let mut dec = components;
8     if !relative {
9         if dec.len() < 2 {
10             if dec.len() == 1 && dec[0] == 0u8.into() {
11                 return vec![0];
12             }
13             panic!("Need at least two components for non-relative oid");
14         }
15         if dec[0] >= 7u8.into() || dec[1] >= 40u8.into() {
16             panic!("First components are too big");
17         }
18         enc.push(dec[0].to_u8().unwrap() * 40 + dec[1].to_u8().unwrap());
19         dec = &dec[2..];
20     }
21 
22     for int in dec.iter() {
23         let mut bytes = int.to_bytes_be();
24         if bytes[0] == 0 {
25             enc.push(0u8);
26             continue;
27         }
28         let total_bits = (8 - bytes[0].leading_zeros()) as usize + (bytes.len() - 1) * 8;
29         let octects_needed = ((total_bits + 6) / 7).max(1);
30         enc.resize_with(enc.len() + octects_needed, Default::default);
31 
32         let mut pos = enc.len() - 1;
33         let mut extra = 0u8;
34         let mut extra_size = 0u8;
35         bytes.reverse();
36         let mut bytes_stored = 0;
37         for byte in bytes.into_iter() {
38             if extra_size == 7 {
39                 // there a seven bits in extra
40                 enc[pos] = extra | (1 << 7);
41                 bytes_stored += 1;
42                 pos -= 1;
43                 extra = 0;
44                 extra_size = 0;
45             }
46             // make space for the extra bits
47             enc[pos] = (byte << extra_size) | extra | (1 << 7);
48             bytes_stored += 1;
49             if pos > 0 {
50                 pos -= 1;
51                 extra_size += 1;
52                 extra = byte >> (8 - extra_size);
53             }
54         }
55         let last = enc.len() - 1;
56         if bytes_stored != octects_needed {
57             let first = last + 1 - octects_needed;
58             enc[first] = extra | (1 << 7);
59         }
60         enc[last] ^= 1 << 7;
61     }
62     enc
63 }
64 
65 #[proc_macro]
encode_oid(input: TokenStream) -> TokenStream66 pub fn encode_oid(input: TokenStream) -> TokenStream {
67     let s = input.to_string();
68 
69     let (rem, relative) = if s.starts_with("rel ") {
70         (&s[4..], true)
71     } else {
72         (s.as_ref(), false)
73     };
74 
75     let ints: Vec<num_bigint::BigUint> = rem
76         .split('.')
77         .map(|segment| segment.trim())
78         .map(|s| s.parse().unwrap())
79         .collect();
80 
81     let enc = encode_components(&ints, relative);
82 
83     let mut s = String::with_capacity(2 + 6 * enc.len());
84     s.push('[');
85     for byte in enc.iter() {
86         s.insert_str(s.len(), &format!("0x{:02x}, ", byte));
87     }
88     s.push(']');
89     s.parse().unwrap()
90 }
91