The following Rust code tries to store a closure of zero arguments in an array and call the function.
fn main() {
println!("The answer is: {}", solution_fns[0]());
}
const solution_fns: [fn() -> isize] =
[|| (1..=999).filter(|e| divides(3, e) || divides(5, e)).sum()];
fn divides(d: usize, n: usize) -> bool {
n % d == 0
}
Link to Rust playground. Unfortunately it does not compile:
error[E0277]: the size for values of type [fn() -> isize] cannot be
known at compilation time --> src/main.rs:5:21 | 5 | const
solution_fns: [fn() -> isize] = |
^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | =
help: the trait Sized is not implemented for [fn() -> isize]
I understand that you cannot constuct an array (or Vec) of things of which the size is not known at compile-time. However I understand the type [fn() -> isize] to be array of function pointers, and I don't see why a function pointer should not have a known size. Sticking the closure in a Box does not seem to help:
const solution_fns: [Box<fn() -> isize>] = [Box::new(|| {
(1..=999).filter(|e| divides(3, e) || divides(5, e)).sum()
})];
How then can I store an array of closures?
The problem is not in the fn pointer, but that your array doesnt have a size. It is simply solved by adding the expected size to the array declaration:
const solution_fns: [fn() -> usize; 1] =
[|| (1..=999usize).filter(|&e| divides(3, e) || divides(5, e)).sum()];
Playground
If you use a slice, then you don't have to specify the size:
fn main() {
println!("The answer is: {}", SOLVERS[0]());
}
const SOLVERS : &[fn() -> usize] =
&[|| (1..=999).filter(|&e| divides(3, e) || divides(5, e)).sum()];
fn divides(d: usize, n: usize) -> bool {
n % d == 0
}
Link to the playground.
Related
I wonder if it is possible to implement this Unsigned trait that allows performing conversions from bytes arrays to this Unsigned type (like a constructor). The add function should work particularly for u32 and u64. For achieving it I was thinking in doing something like this:
pub enum Error {
BadLength,
}
trait Unsigned {
type Array;
const BYTES: usize;
fn from_le_bytes(bytes: Self::Array) -> Self;
}
impl Unsigned for u32 {
type Array = [u8; 4];
const BYTES: usize = 4;
fn from_le_bytes(bytes: Self::Array) -> Self {
u32::from_le_bytes(bytes)
}
}
fn add<W>(a: Vec<u8>, b: Vec<u8>) -> Result<W, Error>
where W: Unsigned + std::ops::Add<Output = W>
{
if a.len() != W::BYTES || b.len() != W::BYTES {
return Err(Error::BadLength)
}
const c: W = W::from_le_bytes(a[0..W::BYTES]);
const d: W = W::from_le_bytes(b[0..W::BYTES]);
Ok(c + d)
}
fn main() {
const a: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
const b: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
if let Ok(c) = add::<u32>(a, b) {
println!("{}", c);
}
}
Currently, the compiler is telling me:
Compiling from_le_bytes v0.1.0 (/home/guido/codes/from_le_bytes)
error[E0308]: mismatched types
--> src/main.rs:28:33
|
28 | let c: W = W::from_le_bytes(a[0..W::BYTES]);
| ^^^^^^^^^^^^^^ expected associated type, found slice `[u8]`
|
= note: expected associated type `<W as Unsigned>::Array`
found slice `[u8]`
help: consider constraining the associated type `<W as Unsigned>::Array` to `[u8]`
|
23 | where W: Unsigned<Array = [u8]> + std::ops::Add<Output = W>
| ++++++++++++++
error[E0308]: mismatched types
--> src/main.rs:29:33
|
29 | let d: W = W::from_le_bytes(b[0..W::BYTES]);
| ^^^^^^^^^^^^^^ expected associated type, found slice `[u8]`
|
= note: expected associated type `<W as Unsigned>::Array`
found slice `[u8]`
help: consider constraining the associated type `<W as Unsigned>::Array` to `[u8]`
|
23 | where W: Unsigned<Array = [u8]> + std::ops::Add<Output = W>
| ++++++++++++++
For more information about this error, try `rustc --explain E0308`.
error: could not compile `from_le_bytes` due to 2 previous errors
Is there any way to compile the code, transform those vectors into u32 and do the addition?
Something like this?
pub enum Error {
BadLength,
}
trait Unsigned {
type Array;
fn from_le_bytes(bytes: Self::Array) -> Self;
}
impl Unsigned for u32 {
type Array = [u8; 4];
fn from_le_bytes(bytes: Self::Array) -> Self {
u32::from_le_bytes(bytes)
}
}
fn add<W>(a: Vec<u8>, b: Vec<u8>) -> Result<W, Error>
where
W: Unsigned + std::ops::Add<Output = W>,
Vec<u8>: TryInto<W::Array>,
{
let a: W::Array = a.try_into().map_err(|_| Error::BadLength)?;
let b: W::Array = b.try_into().map_err(|_| Error::BadLength)?;
let c = W::from_le_bytes(a);
let d = W::from_le_bytes(b);
Ok(c + d)
}
fn main() {
let a: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
let b: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
if let Ok(c) = add::<u32>(a, b) {
println!("{}", c);
}
}
134611970
Explanation
I noticed that the TryInto is implemented for Vec<u8> and [u8; N]:
impl<T, A, const N: usize> TryFrom<Vec<T, A>> for [T; N]
This means if we have the full type, including N, we don't need the BYTES constant.
Further, we can use whether or not the try_into worked or failed to determine if the length was correct.
So therefore, I:
Changed the type Array to carry the length information N at compile time
Removed the BYTES constant
Replaced the length check with a success check of try_into()
And I replaced some erroneous consts with let.
I'm writing a MQTT5 library. To send a packet, I need to know the size of the payload before writing the payload. My solution for determining the size has the following constraints order by importance:
be easy to maintain
should not create copies of the data
should be fairly performant (avoid double calculations)
To determine the size I can do any of the following solutions:
do the calculations by hand, which is fairly annoying
hold a copy of the data to send in memory, which I want to avoid
Build an std::iter::ExactSizeIterator for the payload which consists of std::iter::Chains itself, which leads to ugly typings fast, if you don't create wrapper types
I decided to go with version 3.
The example below shows my try on writing a MQTT String iterator. A MQTT String consists of two bytes which are the length of the string followed by the data as utf8.
use std::iter::*;
use std::slice::Iter;
pub struct MQTTString<'a> {
chain: Chain<Iter<'a, u8>, Iter<'a, u8>>,
}
impl<'a> MQTTString<'a> {
pub fn new(s: &'a str) -> Self {
let u16_len = s.len() as u16;
let len_bytes = u16_len.to_be_bytes();
let len_iter = len_bytes.iter(); // len_bytes is borrowed here
let s_bytes = s.as_bytes();
let s_iter = s_bytes.iter();
let chain = len_iter.chain(s_iter);
MQTTString { chain }
}
}
impl<'a> Iterator for MQTTString<'a> {
type Item = &'a u8;
fn next(&mut self) -> Option<&'a u8> {
self.chain.next()
}
}
impl<'a> ExactSizeIterator for MQTTString<'a> {}
pub struct MQTTStringPait<'a> {
chain: Chain<std::slice::Iter<'a, u8>, std::slice::Iter<'a, u8>>,
}
This implementation doesn't compile because I borrow len_bytes instead of moving it, so it'd get dropped before the Chain can consume it:
error[E0515]: cannot return value referencing local variable `len_bytes`
--> src/lib.rs:19:9
|
12 | let len_iter = len_bytes.iter(); // len_bytes is borrowed here
| --------- `len_bytes` is borrowed here
...
19 | MQTTString { chain }
| ^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
Is there a nice way to do this? Adding len_bytes to the MQTTString struct doesn't help. Is there a better fourth option of solving the problem?
The root problem is that iter borrows the array. In nightly Rust, you can use array::IntoIter, but it does require that you change your iterator to return u8 instead of &u8:
#![feature(array_value_iter)]
use std::array::IntoIter;
use std::iter::*;
use std::slice::Iter;
pub struct MQTTString<'a> {
chain: Chain<IntoIter<u8, 2_usize>, Copied<Iter<'a, u8>>>,
}
impl<'a> MQTTString<'a> {
pub fn new(s: &'a str) -> Self {
let u16_len = s.len() as u16;
let len_bytes = u16_len.to_be_bytes();
let len_iter = std::array::IntoIter::new(len_bytes);
let s_bytes = s.as_bytes();
let s_iter = s_bytes.iter().copied();
let chain = len_iter.chain(s_iter);
MQTTString { chain }
}
}
impl<'a> Iterator for MQTTString<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
self.chain.next()
}
}
impl<'a> ExactSizeIterator for MQTTString<'a> {}
You could do the same thing in stable Rust by using a Vec, but that'd be a bit of overkill. Instead, since you know the exact size of the array, you could get the values and chain more:
use std::iter::{self, *};
use std::slice;
pub struct MQTTString<'a> {
chain: Chain<Chain<Once<u8>, Once<u8>>, Copied<slice::Iter<'a, u8>>>,
}
impl<'a> MQTTString<'a> {
pub fn new(s: &'a str) -> Self {
let u16_len = s.len() as u16;
let [a, b] = u16_len.to_be_bytes();
let s_bytes = s.as_bytes();
let s_iter = s_bytes.iter().copied();
let chain = iter::once(a).chain(iter::once(b)).chain(s_iter);
MQTTString { chain }
}
}
impl<'a> Iterator for MQTTString<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
self.chain.next()
}
}
impl<'a> ExactSizeIterator for MQTTString<'a> {}
See also:
How to implement Iterator and IntoIterator for a simple struct?
An iterator of &u8 is not a good idea from the point of view of pure efficiency. On a 64-bit system, &u8 takes up 64 bits, as opposed to the 8 bits that the u8 itself would take. Additionally, dealing with this data on a byte-by-byte basis will likely impede common optimizations around copying memory around.
Instead, I'd recommend creating something that can write itself to something implementing Write. One possible implementation:
use std::{
convert::TryFrom,
io::{self, Write},
};
pub struct MQTTString<'a>(&'a str);
impl MQTTString<'_> {
pub fn write_to(&self, mut w: impl Write) -> io::Result<()> {
let len = u16::try_from(self.0.len()).expect("length exceeded 16-bit");
let len = len.to_be_bytes();
w.write_all(&len)?;
w.write_all(self.0.as_bytes())?;
Ok(())
}
}
See also:
How do I convert between numeric types safely and idiomatically?
Converting number primitives (i32, f64, etc) to byte representations
I'm trying to combine my Rust program with a library written in C in a more complex scenario.
The library provides this interface:
use std::os::raw::{c_char, c_void};
extern "C" {
pub fn register_function(
name: *const c_char, signature: *const c_char,
func_ptr: *mut c_void, attachment: *mut c_void,
);
}
The signature can be a string describing the arguments and return type of the function as 32 or 64 bit ints and floats (representations: b'i' = i32, b'I' = i64, b'f' = f32, b'F' = f64). The registered function gets called with an array of u64 (uint64_t) values which correspond to the arguments from the signature.
I would like to abstract this registration and callback process, so that I can switch to another library in the future which provides a similar but different interface. My idea was to to create a proxy function that is registered instead of the actual function. This would then also provide a custom context struct.
My own functions could look like this:
use std::boxed::Box;
use std::pin::Pin;
fn return_void(context: Pin<Box<MyAttachment>>) {
// ...
}
fn return_32(context: Pin<Box<MyAttachment>>, a: u32, b: u32) -> u32 {
context.important_stuff();
// ...
}
// floating point values would be nice, but are optional
fn return_64(a: i32, b: i64, c: f64) -> f64 {
// ...
}
MyAttachment is supposed to be the context and provide the proxy function that gets an arbitrary number of arguments as array:
use std::cmp;
use std::ffi::CString;
use std::slice;
#[derive(PartialEq)]
enum ReturnType {
VOID,
BITS32,
BITS64,
}
struct MyAttachment {
real_func_ptr: *mut c_void,
signature: String,
argc: u32,
pass_attachment: bool,
return_type: ReturnType,
}
impl MyAttachment {
pub fn important_stuff(&self) {
// ...
}
unsafe extern "C" fn function_proxy(attachment: *mut c_void, argv: *mut u64) {
// Given: attachment is the pointer to MyAttachment and argv is the array of arguments.
let this = attachment.cast::<Self>();
if this.is_null() || argv.is_null() {
// error handling
return;
}
let this = Pin::new_unchecked(Box::from_raw(this)); // restore
let args = slice::from_raw_parts_mut(
argv,
// There is at least one element in argv if the function is supposed to return a value,
// because we need to write our result there.
cmp::max(
match this.return_type {
ReturnType::VOID => 0,
ReturnType::BITS32 | ReturnType::BITS64 => 1,
},
this.argc as usize,
),
);
let func_ptr = this.real_func_ptr;
// I can get the argument types from the signature.
// TODO cast to correct pointer type. For example:
// case return_void: Fn(Pin<Box<MyAttachment>>)
// case return_32: Fn(Pin<Box<MyAttachment>>, u64, u64) -> u32
// case return_64: Fn(u64, u64, f64) -> f64
// TODO call it:
if this.return_type != ReturnType::VOID {
//args[0] = func_ptr(...args);
// or
//args[0] = func_ptr(this, ...args);
} else {
//func_ptr(...args);
}
Box::into_raw(Pin::into_inner_unchecked(this)); // delay dropping of this
}
}
fn main() {
// defining functions like:
let func1 = Box::pin(MyAttachment {
real_func_ptr: return_32 as *mut _,
signature: String::from("(ii)i"),
argc: 2, // inferred from signature
pass_attachment: true,
return_type: ReturnType::BITS32, // inferred from signature
});
let name = CString::new("return_32").unwrap();
let signature = CString::new(func1.signature.as_str()).unwrap();
// leak the raw pointer
let func1_ptr = Box::into_raw(unsafe { Pin::into_inner_unchecked(func1) });
let _func1 = unsafe { Pin::new_unchecked(Box::from_raw(func1_ptr)) }; // just for housekeeping
unsafe {
register_function(
name.as_ptr(),
signature.as_ptr(),
MyAttachment::function_proxy as *mut _,
func1_ptr as *mut _,
)
};
// ...
// somewhere here is my proxy called from C
// ...
// automatic cleanup of MyAttachment structs, because the Boxes are dropped
}
How do I fill these TODOs with code?
I have seen this in C code somewhere by using a generic function pointer and defining a fixed number of calls:
void (*func_ptr)();
if (argc == 0)
func_ptr();
else if (argc == 1)
func_ptr(argv[0]);
else if (argc == 2)
func_ptr(argv[0], argv[1]);
// ... and so on
But is there a solution to do this in Rust? (This only needs to work for x86_64/amd64)
Thanks in advance for reading all this and trying to help.
(I added the reflection tag, because this would be done via reflection if Rust had any)
==== edit
I have seen these related questions, but I don't think they apply here:
Call a raw address from Rust -> My type is not given at compile time
How do I pass each element of a slice as a separate argument to a variadic C function? -> My arguments are somewhat of fixed size and don't use a valist
I am using an Array of non-optional values, and I want them to stay non-optional, but I can't use Array's default constructor because of problems described here.
Furthermore, the .also{} trick described in the linked won't work for me, because mine is not an array of some primitive type with its own special WhateverArray class.
Is there some Kotlin trick by which I can initialize my a below? Or must I resort to building some list and then converting it?
// please assume Stream<MyNonprimitiveType> magically gives me
// size() -> Int and
// next() -> MyNonprimitiveType
val stream : Stream<MyNonprimitiveType> = Stream<MyNonprimitiveType>()
val size : Int = stream.size()
val a : Array<MyNonprimitiveType> = ??? // use stream.next()
Here's a complete example doing what you want, without using a temporary list:
class Stream<T>(private val list: List<T>) {
val size = list.size;
private val it = list.iterator()
fun next(): T {
return it.next()
}
}
inline fun <reified T: Any> Stream<T>.toArray(): Array<T> {
val tmp: Array<T?> = arrayOfNulls(size)
for (i in 0 until size) {
tmp[i] = next()
}
return tmp as Array<T>
}
fun main() {
val stream : Stream<String> = Stream(listOf("a", "b"))
val a: Array<String> = stream.toArray()
println(Arrays.toString(a))
}
This question already has answers here:
"Expected fn item, found a different fn item" when working with function pointers
(2 answers)
Closed 6 years ago.
How do you stick functions (or function pointers) into an array for testing purposes?
fn foo() -> isize { 1 }
fn bar() -> isize { 2 }
fn main() {
let functions = vec![foo, bar];
println!("foo() = {}, bar() = {}", functions[0](), functions[1]());
}
This code in the Rust playground
This is the error code I get:
error: mismatched types:
expected `fn() -> isize {foo}`,
found `fn() -> isize {bar}`
(expected fn item,
found a different fn item) [E0308]
let functions = vec![foo, bar];
^~~
Rust is treating my functions (values) as different types despite having the same signatures, which I find surprising.
At some point recently, each function was given its own, distinct type for... reasons that I don't recall. Upshot is that you need to give the compiler a hint (note the type on functions):
fn foo() -> isize {
1
}
fn bar() -> isize {
2
}
fn main() {
let functions: Vec<fn() -> isize> = vec![foo, bar];
println!("foo() = {}, bar() = {}", functions[0](), functions[1]());
}
You can also do this like so:
let functions = vec![foo as fn() -> isize, bar];