I have currently been dabbling in the Rust programming language and decided a good way to test my skills was to program an application that would find the median of any given list of numbers.
Eventually I got into the Final stretch of code and stumbled into a problem.
I needed to parse an f64 variable into a usize variable.
However, I don't know how to go about doing this (Wow what a surprise!).
Take a look at the second function, calc_med() in my code. The variable n2 is supposed to take n and parse it into a usize. The code is not finished yet, but if you can see any more problems with the code please let me know.
use std::io;
use std::sync::Mutex;
#[macro_use]
extern crate lazy_static;
lazy_static! {
static ref v1: Mutex<Vec<f64>> = Mutex::new(Vec::new());
}
fn main() {
loop {
println!("Enter: ");
let mut inp: String = String::new();
io::stdin().read_line(&mut inp).expect("Failure");
let upd_inp: f64 = match inp.trim().parse() {
Ok(num) => num,
Err(_) => if inp.trim() == String::from("q") {
break;
} else if inp.trim() == String::from("d"){
break
{
println!("Done!");
calc_med();
}
} else {
continue;
}
};
v1.lock().unwrap().push(upd_inp);
v1.lock().unwrap().sort_by(|a, b| a.partial_cmp(b).unwrap());
println!("{:?}", v1.lock().unwrap());
}
}
fn calc_med() { // FOR STACKOVERFLOW: THIS FUNCTION
let n: f64 = ((v1.lock().unwrap().len()) as f64 + 1.0) / 2.0;
let n2: usize = n.to_usize().expect("Failure");
let median: f64 = v1[n2];
println!("{}", median)
}
Related
I'm trying to understand Rust' memory mechanism, especially how it works when you need it to interoperate with C code.
Here I have small C code represents a linked list and a function prints its attr to stdout:
// this is wrapper.h
typedef struct elem {
int attr;
struct elem *next;
} elem;
typedef struct wrapper {
char name[16];
struct elem *first_elem;
} wrapper;
void print_all_attrs(wrapper *w);
// -----
// and this is how wrapper.c looks like:
#include <stdio.h>
#include "wrapper.h"
void print_all_attrs(wrapper *w) {
printf("NAME = %s\n", w->name);
elem *elem = w->first_elem;
while(elem != NULL) {
printf("ATTR = %d\n", elem->attr);
elem = elem->next;
}
}
We all know how to prepare a wrapper that can hold a linkedlist of elem which is created dynamically: we need to create a wrapper variable, then a logic allocates an area in heap for every elem, assigns the first one into wrapper->first_elem and then others to previous' next pointer. here the code does exactly same thing:
void main() {
wrapper w = {
.name = "ABCD",
};
elem *prev = NULL;
for(int i=0; i<10; i++) {
elem *new = malloc(sizeof(elem));
new->attr = i;
if(w.first_elem == NULL) {
w.first_elem = new;
prev = new;
continue;
}
prev->next = new;
prev = prev->next;
}
print_all_attrs(&w);
// CLEARING HEAP STUFF HERE...
}
So, in Rust, I'm trying to use those definitions by generating code bindgen and cc libraries, I'm skipping these details right now.
If I want to allocate something into heap, I know I can use Box but it doesn't work at all because it drops when it goes out scope. take a look below code that exits with segmentation fault:
unsafe {
let mut prev: *mut xxx::elem = w.first_elem;
for n in 0..10 {
let mut elem = Box::new(xxx::elem {
attr: n,
next: ptr::null_mut(),
});
if w.first_elem.is_null() {
w.first_elem = &mut *elem;
prev = &mut *elem;
continue;
}
(*prev).next = &mut *elem;
prev = (*prev).next;
}
xxx::print_all_attrs(&mut w);
}
I managed to use Layout and alloc, but these guys bring a cost that I need to dealloc the things after use:
unsafe {
use std::alloc::{Layout, alloc};
let mut prev: *mut xxx::elem = w.first_elem;
for n in 0..10 {
let layout = Layout::new::<xxx::elem>();
let mut p = alloc(layout) as *mut xxx::elem;
(*p).attr = n;
(*p).next = ptr::null_mut();
if w.first_elem.is_null() {
w.first_elem = p;
prev = p;
continue;
}
(*prev).next = p;
prev = (*prev).next;
}
xxx::print_all_attrs(&mut w);
// dealloc stuff here.
}
I wonder that if there is another possible way to do that without using Layout and its friends? I see this is one of the proper way to make it but it makes me feel this is not the expected "Rust-way".
I want to reinterpret a stack allocated byte array as a stack allocated (statically guaranteed) struct without doing any work - just to tell the compiler that "Yes, I promise they are the same size and anything". How do I do that?
I tried transmute, but it doesn't compile.
fn from_u8_fixed_size_array<T>(arr: [u8; size_of::<T>()]) -> T {
unsafe { mem::transmute(arr) }
}
cannot transmute between types of different sizes, or dependently-sized types E0512
Note: source type: `[u8; _]` (this type does not have a fixed size)
Note: target type: `T` (this type does not have a fixed size)
There is also this variant of such a function, that compiles, but it requires T to be Copy:
fn from_u8_fixed_size_array(arr: [u8; size_of::<T>()]) -> T {
unsafe { *(&arr as *const [u8; size_of::<T>()] as *const T) }
}
With Rust 1.64 I have a compilation error on [u8; size_of::<T>()] (cannot perform const operation using T).
I tried with a const generic parameter but the problem is still the same (I cannot introduce a where clause to constrain this constant to match size_of::<T>()).
Since the array is passed by value and the result is a value, some bytes have to be copied ; this implies a kind of memcpy().
I suggest using a slice instead of an array and checking the size at runtime.
If you are ready to deal with undefined behaviour, you might consider the second version which does not copy anything: it just reinterprets the storage as is.
I'm not certain I would do that, however...
Edit
The original code was compiled with nightly and a specific feature.
We can simply use transmute_copy() to get the array by value and emit a value.
And, I think the functions themselves should be qualified with unsafe instead of just some of their operations, because nothing guaranties (statically) that these conversions are correct.
#![feature(generic_const_exprs)] // nightly required
unsafe fn from_u8_slice_v1<T>(arr: &[u8]) -> T {
let mut result = std::mem::MaybeUninit::<T>::uninit();
let src = &arr[0] as *const u8;
let dst = result.as_mut_ptr() as *mut u8;
let count = std::mem::size_of::<T>();
assert_eq!(count, arr.len());
std::ptr::copy_nonoverlapping(src, dst, count);
result.assume_init()
}
unsafe fn from_u8_slice_v2<T>(arr: &[u8]) -> &T {
let size = std::mem::size_of::<T>();
let align = std::mem::align_of::<T>();
assert_eq!(size, arr.len());
let addr = &arr[0] as *const _ as usize;
assert_eq!(addr % align, 0);
&*(addr as *const T) // probably UB
}
unsafe fn from_u8_fixed_size_array<T>(
arr: [u8; std::mem::size_of::<T>()]
) -> T {
std::mem::transmute_copy(&arr)
}
fn main() {
let a = [1, 2];
println!("{:?}", a);
let i1 = unsafe { from_u8_slice_v1::<i16>(&a) };
println!("{:?}", i1);
let i2 = unsafe { from_u8_slice_v2::<i16>(&a) };
println!("{:?}", i2);
let i3 = unsafe { from_u8_fixed_size_array::<i16>(a) };
println!("{:?}", i3);
}
/*
[1, 2]
513
513
513
*/
I have this function:
use std::io;
pub fn recv(mut buf: &mut [u8]) -> io::Result<usize> {
let size_to_extend = 50; // I want to increase the size of "buf" by 50
unsafe {
/* ??? */
}
}
How can I adjust the size of the array buf, even though it's a parameter? It is necessary that this method needs to happen.
What you are attempting to do is all-but-guaranteed to cause undefined behavior. Find a better API.
If you want the changes to be reflected outside of the function, you are out of luck. There's no way that this function signature will allow for that to happen, for the same reason that fn foo(x: i32) won't allow you to change the value passed in as observed by the caller.
If you just need this inside of the function, use slice::from_raw_parts. I've marked the entire function as unsafe because certain inputs will cause undefined behavior and this code cannot possibly guard against it:
use std::slice;
pub unsafe fn recv(buf: &mut [u8]) {
let size_to_extend = 50;
let ptr = buf.as_mut_ptr();
let len = buf.len();
let bad_idea = slice::from_raw_parts_mut(ptr, len + size_to_extend);
for b in bad_idea.iter_mut() {
*b = 10;
}
}
If you can change the API, something like this works to expose the change outside the function:
pub unsafe fn recv(buf: &mut &mut [u8]) {
let size_to_extend = 50;
let ptr = buf.as_mut_ptr();
let len = buf.len();
let bad_idea = slice::from_raw_parts_mut(ptr, len + size_to_extend);
for b in bad_idea.iter_mut() {
*b = 10;
}
*buf = bad_idea;
}
See also:
How can I get an array or a slice from a raw pointer?
I need to take an octal string, such as "42.1", and get a float from it (34.125). What's the best way to do this in Rust? I see there previously was a from_str_radix function, but it's now removed.
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseFloatError {
_private: (),
}
impl ParseFloatError {
fn new() -> ParseFloatError {
ParseFloatError { _private: () }
}
}
impl fmt::Display for ParseFloatError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Could not parse float")
}
}
pub fn parse_float_radix(s: &str, radix: u32) -> Result<f64, ParseFloatError> {
let s2 = s.replace(".", "");
let i = i64::from_str_radix(&s2, radix).map_err(|_| ParseFloatError::new())?;
let count = s.split('.').count();
let fraction_len: usize;
match count {
0 => unreachable!(),
1 => fraction_len = 0,
2 => fraction_len = s.split('.').last().unwrap().len(),
_ => return Err(ParseFloatError::new()),
}
let f = (i as f64) / f64::from(radix).powi(fraction_len as i32);
Ok(f)
}
fn main() {
println!("{}", parse_float_radix("42.1", 8).unwrap());
}
It first parses the input as an integer and then divides it by radix^number_of_fractional_digits.
It doesn't support scientific notation or special values like infinity or NaN. It also fails if the intermediate integer overflows.
Since posting this question, a crate has appeared that solves this: lexical. Compiling with the radix feature enables a parse_radix function, which can parse strings into floats with radices from 2 to 36.
So I'm trying to find a pattern in a string and convert it to an integer.
Firstly I look for a string:
let haystack = "HTTP/1.1 200\r\n";
let needle = "HTTP/1.";
let http_location = haystack.rfind(needle);
if (http_location.is_some()) {
Now that I've found it I can think of two ways to get the numerical status. Either:
let mut temp_str = haystack.char_at(http_location.unwrap());
let status = String::from_str(temp_str);
}
Or:
let status = String::from_str(&haystack[http_location.unwrap()]);
}
Unfortunately both of them are deprecated (and probably wrong anyway). What is currently the correct way of doing this?
Also, is this part stylistically correct?:
let http_location = haystack.rfind(needle);
if (http_location.is_some())
Parsing is a wide and varied topic. There are easy parsing tools and there are performant parsing tools and a spectrum in between.
fn main() {
let haystack = "HTTP/1.1 200\r\n";
let needle = "HTTP/1.";
let z: Option<u8> = haystack.rfind(needle).and_then(|pt| {
let after_match = &haystack[(pt + needle.len())..];
after_match.splitn(2, " ").next()
}).and_then(|val| {
val.parse().ok()
});
println!("{:?}", z)
}
Here, we use rfind as you did before, which can fail. We use and_then to run the closure if the result was Some. The first closure slices the string after the needle, then splits it on spaces, with a maximum of 2 parts. That can fail, so we use a second and_then to use parse, which can also fail with a Result, so we convert that into an Option to preserve the type.
And the end of this, we still might have failed, as the thing we parsed might not have been a parseable number!
Rust really helps you make explicit places you can fail, and you have to deal with them. ^_^
In this case:
Maybe the string doesn't have "HTTP/1." in it
Iterators have to end at some point, so they can return None.
Parsing a string to a number can fail.
Here's an alternate solution that uses the regex crate:
extern crate regex;
use regex::Regex;
fn main() {
let haystack = "HTTP/1.1 200\r\n";
let re = Regex::new(r"HTTP/1.(\d) (\d+)\r\n").unwrap();
let captures = re.captures(haystack).unwrap();
let version: Option<u8> = captures.at(1).and_then(|version| version.parse().ok());
let status: Option<u8> = captures.at(2).and_then(|version| version.parse().ok());
assert_eq!(Some(1), version);
assert_eq!(Some(200), status);
println!("Version: {:?}, Status: {:?}", version, status);
}
You'll see that we have the same types of failure modes, but the structure is a bit different.
Or maybe a version that uses Result and try!:
#[derive(Debug,Copy,Clone,PartialEq)]
enum Error {
StartNotFound,
NotANumber,
}
fn parse_it(haystack: &str) -> Result<u8, Error> {
let needle = "HTTP/1.";
let pt = try!(haystack.rfind(needle).ok_or(Error::StartNotFound));
let after_match = &haystack[(pt + needle.len())..];
let val = after_match.splitn(2, " ").next().unwrap();
val.parse().map_err(|_| Error::NotANumber)
}
fn main() {
println!("{:?}", parse_it("HTTP/1.1 200\r\n"));
println!("{:?}", parse_it("HTTP/1"));
println!("{:?}", parse_it("HTTP/1.cow"));
}