asn1-rs-impl-0.2.0/.cargo_vcs_info.json0000644000000001420000000000100132530ustar { "git": { "sha1": "a20e5f7319c896737ad0f2557037817b91ad854f" }, "path_in_vcs": "impl" }asn1-rs-impl-0.2.0/Cargo.toml0000644000000016340000000000100112600ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "asn1-rs-impl" version = "0.2.0" authors = ["Pierre Chifflier "] description = "Implementation details for the `asn1-rs` crate" homepage = "https://github.com/rusticata/asn1-rs" license = "MIT/Apache-2.0" repository = "https://github.com/rusticata/asn1-rs.git" [lib] proc-macro = true [dependencies.proc-macro2] version = "1" [dependencies.quote] version = "1" [dependencies.syn] version = "2.0" asn1-rs-impl-0.2.0/Cargo.toml.orig000064400000000000000000000006211046102023000147340ustar 00000000000000[package] name = "asn1-rs-impl" version = "0.2.0" authors = ["Pierre Chifflier "] description = "Implementation details for the `asn1-rs` crate" license = "MIT/Apache-2.0" homepage = "https://github.com/rusticata/asn1-rs" repository = "https://github.com/rusticata/asn1-rs.git" edition = "2018" [lib] proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" syn = "2.0" asn1-rs-impl-0.2.0/src/lib.rs000064400000000000000000000074511046102023000137600ustar 00000000000000extern 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()) } asn1-rs-impl-0.2.0/tests/test_oid.rs000064400000000000000000000005461046102023000153750ustar 00000000000000use asn1_rs_impl::{encode_int, encode_oid}; #[test] fn test_encode_oid() { // example from http://luca.ntop.org/Teaching/Appunti/asn1.html let oid = encode_oid! {1.2.840.113549}; assert_eq!(oid, [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d]); } #[test] fn test_encode_int() { // let int = encode_int!(1234); assert_eq!(int, [0x04, 0xd2]); }