From 085777ee9c739895b15b8db17a629826c469facd Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Tue, 21 Nov 2023 14:06:43 +0000 Subject: Import asn1-rs-impl crate. Request Document: go/android-rust-importing-crates For CL Reviewers: go/android3p#cl-review For Build Team: go/ab-third-party-imports Bug: 312436741 Test: Treehugger Change-Id: Ie6e96450b8bd28dfaec21f2a9af7d3827af8c2ca --- src/lib.rs | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/lib.rs (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ea635cc --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,126 @@ +extern crate proc_macro; +use proc_macro::{Span, TokenStream}; +use syn::{parse_macro_input, Error, LitInt}; + +#[proc_macro] +pub fn encode_oid(input: TokenStream) -> TokenStream { + let token_stream = input.to_string(); + let (s, relative) = if token_stream.starts_with("rel ") { + (&token_stream[4..], true) + } else { + (token_stream.as_ref(), false) + }; + let items: Result, _> = s.split('.').map(|x| x.trim().parse::()).collect(); + let mut items: &[_] = match items.as_ref() { + Ok(v) => v.as_ref(), + Err(_) => return create_error("Could not parse OID"), + }; + let mut v = Vec::new(); + if !relative { + if items.len() < 2 { + if items.len() == 1 && items[0] == 0 { + return "[0]".parse().unwrap(); + } + return create_error("Need at least two components for non-relative oid"); + } + if items[0] > 2 || items[1] > 39 { + return create_error("First components are too big"); + } + let first_byte = (items[0] * 40 + items[1]) as u8; + v.push(first_byte); + items = &items[2..]; + } + for &int in items { + let enc = encode_base128(int); + v.extend_from_slice(&enc); + } + // "fn answer() -> u32 { 42 }".parse().unwrap() + let mut s = String::with_capacity(2 + 6 * v.len()); + s.push('['); + for byte in v.iter() { + s.insert_str(s.len(), &format!("0x{:02x}, ", byte)); + } + s.push(']'); + s.parse().unwrap() +} + +#[inline] +fn create_error(msg: &str) -> TokenStream { + let s = format!("Invalid OID({})", msg); + Error::new(Span::call_site().into(), &s) + .to_compile_error() + .into() +} + +// encode int as base128 +fn encode_base128(int: u128) -> Vec { + let mut val = int; + let mut base128 = Vec::new(); + let lo = val & 0x7f; + base128.push(lo as u8); + val >>= 7; + loop { + if val == 0 { + base128.reverse(); + return base128; + } + let lo = val & 0x7f; + base128.push(lo as u8 | 0x80); + val >>= 7; + } +} + +#[proc_macro] +pub fn encode_int(input: TokenStream) -> TokenStream { + let lit = parse_macro_input!(input as LitInt); + + match impl_encode_int(lit) { + Ok(ts) => ts, + Err(e) => e.to_compile_error().into(), + } + + // let token_stream = input.to_string(); + // let items: Result, _> = token_stream + // .split('.') + // .map(|x| x.trim().parse::()) + // .collect(); + // let err = Error::new(Span::call_site().into(), "invalid OID"); + // if let Ok(items) = items { + // let mut v = Vec::new(); + // if items.len() < 2 || items[0] > 2 || items[1] > 39 { + // return err.to_compile_error().into(); + // } + // let first_byte = (items[0] * 40 + items[1]) as u8; + // v.push(first_byte); + // for &int in &items[2..] { + // let enc = encode_base128(int); + // v.extend_from_slice(&enc); + // } + // // "fn answer() -> u32 { 42 }".parse().unwrap() + // let mut s = String::with_capacity(2 + 6 * v.len()); + // s.push('['); + // for byte in v.iter() { + // s.insert_str(s.len(), &format!("0x{:02x}, ", byte)); + // } + // s.push(']'); + // s.parse().unwrap() + // } else { + // eprintln!("could not parse OID '{}'", token_stream); + // err.to_compile_error().into() + // } +} + +fn impl_encode_int(lit: LitInt) -> Result { + let value = lit.base10_parse::()?; + + let bytes = value.to_be_bytes(); + let v: Vec<_> = bytes.iter().skip_while(|&c| *c == 0).collect(); + + let mut s = String::with_capacity(2 + 6 * v.len()); + s.push('['); + for byte in v.iter() { + s.insert_str(s.len(), &format!("0x{:02x}, ", byte)); + } + s.push(']'); + Ok(s.parse().unwrap()) +} -- cgit v1.2.3