Creating a macro with infinte arguments - rust

struct Foo{
value: i32
}
impl Foo{
fn get_and_change_value(&mut self) -> i32{
let v = self.value;
self.value = 42;
v
}
}
//glue_code_macro
fn main(){
let mut f1 = Foo{value:1};
let mut f2 = Foo{value:2};
let mut f3 = Foo{value:3};
let v: Vec<i32> = glue_code_macro!(f1,f2,f3);
}
I want to create the glue_code_macro which takes n variables and creates a vector. I don't think that I can achieve this with a normal function because I have a mutable reference and I would be unable to change its content.
In my head it would expand to
let v = {
let v1 = f1.get_and_change_value();
let v2 = f2.get_and_change_value();
let v3 = f3.get_and_change_value();
vec!(v1,v2,v3)
}
Is this possible? If yes how would I do this?

It's possible. Add this to the top of your module:
#![feature(macro_rules)]
macro_rules! glue_code_macro(
($($element:ident),*) => (
vec![$($element.get_and_change_value(),)*]
)
)
The macro guide explains how it works: http://doc.rust-lang.org/guide-macros.html

Related

How to create a vector of functions from an iterator of functions

I have an iterator of functions (i_adder). I want to get a vector(nv_adder) from this iterator.
struct Int{
i : i32
}
fn main() {
let adder = move |x : &Int| Int{ i: x.i + 1};
let v_adder=vec![adder];
let i_adder=v_adder.iter();
let nv_adder=i_adder.collect::<Vec<&dyn Fn(&Int)->Int>>();
}
error[E0277]: a value of type Vec<&dyn for<'r> Fn(&'r Int) -> Int> cannot be built from an iterator over elements of type &[closure#src/main.rs:8:17: 8:49]
code
Using the Box smart pointer and type specification :
fn main() {
let adder = move |x : &Int| Int{ i: x.i + 1};
let v_adder: Vec<Box<dyn Fn(&Int) -> Int>>=vec![Box::new(adder)];
let i_adder=v_adder.iter();
let nv_adder=i_adder.collect::<Vec<&Box<dyn Fn(&Int) -> Int>>>();
}
You need the Box smart pointer since the compilator does not know the size of a trait object at compile time.
This code works. But I still don´t know what why collect doesn´t work.
struct Int{
i : i32
}
fn main() {
let adder = move |x : &Int| Int{ i: x.i + 1};
let v_adder=vec![adder];
let i_adder=v_adder.iter();
let v = Vec::from_iter(i_adder);
let p= v[0](&Int{i:1}).i;
println!("{}",p)
}
code

How to get X and Y coordinates of an EC Point in Rust?

I'm trying to extract X and Y coordinates from a EcKeyopenssl::pkey::Private key in Rust.
I have managed to convert it to a point and bytes, but I don't know how to get the coordinates.
pub fn exportpubkey(key: &EcKey<openssl::pkey::Private>) -> (){
let group: EcGroup = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
let mut ctx: BigNumContext = openssl::bn::BigNumContext::new().unwrap();
let bytes = key.public_key().to_bytes(&group,openssl::ec::PointConversionForm::COMPRESSED, &mut ctx).unwrap();
println!("{}", display_bytes(&bytes));
}
You might want to look at the method affine_coordinates
use openssl::{bn::*, ec::*, nid::Nid};
pub fn print_pub_key(key: &EcKey<openssl::pkey::Private>) -> () {
let group: EcGroup = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
let mut ctx: BigNumContext = BigNumContext::new().unwrap();
let public_key = key.public_key();
let mut x = BigNum::new().unwrap();
let mut y = BigNum::new().unwrap();
public_key
.affine_coordinates_gfp(group.as_ref(), &mut x, &mut y, &mut ctx)
.expect("extract coords");
println!("{}, {}", x, y);
}
fn main() {
let group: EcGroup = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
let key = EcKey::generate(&group).unwrap();
print_pub_key(&key);
}
Note that affine_coordinates_gfp and affine_coordinates_gf2m seem to give back the same coordinate in your chosen group.

Pushing data back upstream from thread

I'm completely open to any and all critiques. I'm completely new to multi-threading and the docs don't make much sense to me.
The code provided is min-reproducible. The matrix I'm using is much more elaborate, but this works. The point is to use a global process for various vectors within the structs concurrently, then push all the data upstream and back into the global.
I'm receiving an error at line 59 the first unwrap(). Is there a better way to approach this problem altogether???
use std::{
sync::mpsc::channel,
sync::{Arc, Mutex},
thread,
};
#[derive(Debug, Clone)]
struct Data {
block: Vec<List>,
}
#[derive(Debug, Clone)]
struct List {
multiplier: f64,
num: f64,
}
static mut IterationData: Data = Data { block: Vec::new() };
const N: u128 = 100;
fn main() {
unsafe {
for n in 0..N {
let mut number = 0.0;
let list = List {
multiplier: n as f64,
num: 1.0,
};
IterationData.block.push(list);
}
let mut data = Arc::new(Mutex::new(IterationData.clone()));
let (tx, rx) = channel();
for n in 0..IterationData.block.len() {
let (data, tx) = (Arc::clone(&data), tx.clone());
thread::spawn(move || {
let mut data = data.lock().unwrap();
let mut data_2 = Arc::new(Mutex::new(IterationData.block[n].clone()));
let (t, r) = channel();
for m in 0..IterationData.block.len() {
let (data_2, t) = (Arc::clone(&data_2), t.clone());
thread::spawn(move || {
let mut data_2 = data_2.lock().unwrap();
data_2.num += N as f64;
if m + 1 == IterationData.block.len() {
t.send(()).unwrap();
}
});
}
r.recv().unwrap();
let test_2 = Arc::try_unwrap(data_2).unwrap().into_inner().unwrap();
data.block[n] = test_2;
if n + 1 == IterationData.block.len() {
tx.send(()).unwrap();
}
});
}
rx.recv().unwrap();
let test_1 = Arc::try_unwrap(data).unwrap().into_inner().unwrap();
IterationData = test_1;
}
}

How to use a clone in a Rust thread

In this rust program, inside the run function, I am trying to pass the "pair_clone" as a parameter for both threads but I keep getting a mismatched type error? I thought I was passing the pair but it says I'm passing an integer instead.
use std::sync::{Arc, Mutex, Condvar};
fn producer(pair: &(Mutex<bool>, Condvar), num_of_loops: u32) {
let (mutex, cv) = pair;
//prints "producing"
}
}
fn consumer(pair: &(Mutex<bool>, Condvar), num_of_loops: u32) {
let (mutex, cv) = pair;
//prints "consuming"
}
}
pub fn run() {
println!("Main::Begin");
let num_of_loops = 5;
let num_of_threads = 4;
let mut array_of_threads = vec!();
let pair = Arc ::new((Mutex::new(true), Condvar::new()));
for pair in 0..num_of_threads {
let pair_clone = pair.clone();
array_of_threads.push(std::thread::spawn( move || producer(&pair_clone, num_of_loops)));
array_of_threads.push(std::thread::spawn( move || consumer(&pair_clone, num_of_loops)));
}
for i in array_of_threads {
i.join().unwrap();
}
println!("Main::End");
}
You have two main errors
The first: you are using the name of the pair as the loop index. This makes pair be the integer the compiler complains about.
The second: you are using one copy while you need two, one for the producer and the other for the consumer
After Edit
use std::sync::{Arc, Mutex, Condvar};
fn producer(pair: &(Mutex<bool>, Condvar), num_of_loops: u32) {
let (mutex, cv) = pair;
//prints "producing"
}
fn consumer(pair: &(Mutex<bool>, Condvar), num_of_loops: u32) {
let (mutex, cv) = pair;
//prints "consuming"
}
pub fn run() {
println!("Main::Begin");
let num_of_loops = 5;
let num_of_threads = 4;
let mut array_of_threads = vec![];
let pair = Arc ::new((Mutex::new(true), Condvar::new()));
for _ in 0..num_of_threads {
let pair_clone1 = pair.clone();
let pair_clone2 = pair.clone();
array_of_threads.push(std::thread::spawn( move || producer(&pair_clone1, num_of_loops)));
array_of_threads.push(std::thread::spawn( move || consumer(&pair_clone2, num_of_loops)));
}
for i in array_of_threads {
i.join().unwrap();
}
println!("Main::End");
}
Demo
Note that I haven't given any attention to the code quality. just fixed the compile errors.

Rust: Map two Vecs into a third Vec of composite structs

I have three structs:
struct A;
struct B;
struct C {
a: Option<A>,
b: Option<B>
}
Given inputs Vec<A> and Vec<B> and some predicate function, I want to create an output Vec<C>, which is a combination of the elements of the inputs, something like the following:
let aVec: Vec<A> = vec![];
let bVec: Vec<B> = vec![];
let mut cVec: Vec<C> = vec![];
for a in aVec {
if let Some(b) = bVec.into_iter().find(predicate) {
cVec.push(C{a: Some(a), b: Some(b)});
}
}
Is there a way to do this without needing B to be copyable? Both input vectors aren't required after the operation. Also, is this possible without the loop?
You can:
Find the index of the element satisfying predicate. (I would use Iterator::position.)
remove or swap_remove the element at the position obtained by the previous step.
push the previously removed element into result.
In code:
use itertools; // 0.8.2
use itertools::Itertools;
struct A {}
struct B {
n: usize,
}
struct C {
a: Option<A>,
b: Option<B>
}
fn main() {
let aVec: Vec<A> = vec![];
let mut bVec: Vec<B> = vec![];
let mut cVec: Vec<C> = vec![];
for a in aVec {
if let Some(idx) = bVec.iter()
.position(|b| b.n==42)
{
let b = bVec.remove(idx); // or swap_remove if ordering does not need to be preserved
cVec.push(C{a: Some(a), b: Some(b)});
}
}
}

Resources