ark_ff_macros/
utils.rs
1use std::str::FromStr;
2
3use num_bigint::{BigInt, Sign};
4use num_traits::Num;
5use proc_macro::TokenStream;
6use syn::{Expr, Lit};
7
8pub fn parse_string(input: TokenStream) -> Option<String> {
9 let input: Expr = syn::parse(input).unwrap();
10 let input = if let Expr::Group(syn::ExprGroup { expr, .. }) = input {
11 expr
12 } else {
13 panic!("could not parse");
14 };
15 match *input {
16 Expr::Lit(expr_lit) => match expr_lit.lit {
17 Lit::Str(s) => Some(s.value()),
18 _ => None,
19 },
20 _ => None,
21 }
22}
23
24pub fn str_to_limbs(num: &str) -> (bool, Vec<String>) {
25 let (sign, limbs) = str_to_limbs_u64(num);
26 (sign, limbs.into_iter().map(|l| format!("{l}u64")).collect())
27}
28
29pub fn str_to_limbs_u64(num: &str) -> (bool, Vec<u64>) {
30 let is_negative = num.starts_with('-');
31 let num = if is_negative { &num[1..] } else { num };
32 let number = if num.starts_with("0x") || num.starts_with("0X") {
33 BigInt::from_str_radix(&num[2..], 16)
35 } else if num.starts_with("0o") || num.starts_with("0O") {
36 BigInt::from_str_radix(&num[2..], 8)
38 } else if num.starts_with("0b") || num.starts_with("0B") {
39 BigInt::from_str_radix(&num[2..], 2)
41 } else {
42 BigInt::from_str(num)
44 }
45 .expect("could not parse to bigint");
46 let number = if is_negative { -number } else { number };
47 let (sign, digits) = number.to_radix_le(16);
48
49 let limbs = digits
50 .chunks(16)
51 .map(|chunk| {
52 let mut this = 0u64;
53 for (i, hexit) in chunk.iter().enumerate() {
54 this += (*hexit as u64) << (4 * i);
55 }
56 this
57 })
58 .collect::<Vec<_>>();
59
60 let sign_is_positive = sign != Sign::Minus;
61 (sign_is_positive, limbs)
62}