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