1#![deny(missing_docs)]
17
18use quote::quote;
35use syn::DeriveInput;
36
37#[proc_macro_derive(Num)]
39pub fn num_traits_num(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
40 let ast: DeriveInput = syn::parse(input).unwrap();
41
42 let ident = ast.ident;
43 let mut toks = proc_macro2::TokenStream::new();
44 toks.extend(quote! {
45 impl ::num_traits::Num for #ident {
46 type FromStrRadixErr = ::std::num::ParseIntError;
47
48 fn from_str_radix(s: &str, r: u32)-> Result<Self, Self::FromStrRadixErr> {
49 if s.is_empty() {
50 return Err(u32::from_str_radix(s, r).err().unwrap());
52 }
53
54 if s == "0" {
55 return Ok(<Self as ::ff::Field>::zero());
56 }
57
58 let mut res = <Self as ::ff::Field>::zero();
59 let radix = Self::from(r as u64);
60 let mut first_digit = true;
61 for c in s.chars() {
62 match c.to_digit(r) {
63 Some(c) => {
64 if first_digit {
65 if c == 0 {
66 return Err(u32::from_str_radix("3", 2).err().unwrap());
67 }
68 first_digit = false;
69 }
70
71 res *= &radix;
72 res += Self::from(c as u64);
73 }
74 None => {
75 return Err(u32::from_str_radix("3", 2).err().unwrap());
76 }
77 }
78 }
79 Ok(res)
80 }
81 }
82
83 impl ::num_traits::Zero for #ident {
84 fn zero() -> Self {
85 <Self as ::ff::Field>::zero()
86 }
87
88 fn is_zero(&self) -> bool {
89 bool::from(<Self as ::ff::Field>::is_zero(self))
90 }
91 }
92
93 impl ::num_traits::One for #ident {
94 fn one() -> Self {
95 <Self as ::ff::Field>::one()
96 }
97
98 fn is_one(&self) -> bool {
99 self == &<Self as ::ff::Field>::one()
100 }
101 }
102
103 #[allow(clippy::suspicious_arithmetic_impl)]
104 impl ::std::ops::Div<#ident> for #ident {
105 type Output = Self;
106
107 #[must_use]
108 fn div(self, rhs: Self) -> Self {
109 use ::ff::Field;
110 self * <Self as ::ff::Field>::invert(&rhs).unwrap()
111 }
112 }
113
114 #[allow(clippy::suspicious_arithmetic_impl)]
115 impl ::std::ops::Div<&#ident> for #ident {
116 type Output = Self;
117
118 fn div(self, rhs: &Self) -> Self {
119 self * <Self as ::ff::Field>::invert(rhs).unwrap()
120 }
121 }
122
123 impl ::std::ops::Rem<#ident> for #ident {
124 type Output = Self;
125
126 #[must_use]
127 fn rem(self, rhs: Self) -> Self {
128 if bool::from(<Self as ::ff::Field>::is_zero(&self)) {
129 panic!("divide by zero");
130 }
131
132 <Self as ::ff::Field>::zero()
133 }
134 }
135
136 impl ::std::ops::Rem<&#ident> for #ident {
137 type Output = Self;
138
139 #[must_use]
140 fn rem(self, rhs: &Self) -> Self {
141 if bool::from(<Self as ::ff::Field>::is_zero(&self)) {
142 panic!("divide by zero");
143 }
144
145 <Self as ::ff::Field>::zero()
146 }
147 }
148
149 impl ::num_traits::ops::mul_add::MulAdd for #ident {
150 type Output = Self;
151
152 fn mul_add(mut self, a: Self, b: Self) -> Self {
153 self *= &a;
154 self += &b;
155 self
156 }
157 }
158
159 impl ::num_traits::ops::mul_add::MulAdd<&#ident, &#ident> for #ident {
160 type Output = Self;
161
162 fn mul_add(mut self, a: &Self, b: &Self) -> Self {
163 self *= a;
164 self += b;
165 self
166 }
167 }
168 });
169
170 toks.into()
171}