This question already has answers here:
Converting number primitives (i32, f64, etc) to byte representations
(5 answers)
Closed 3 years ago.
I am trying to convert an integer to byte literal in Rust:
for x in 0..10000 {
let key = x.to_???;
other_function(key);
}
Could not find it in the docs.
A byte literal is something like b'f', a literal value written down. You probably mean a byte, which is usually a u8, sometimes an i8. You can use the TryFrom-trait on recent rust:
use std::convert::TryFrom;
fn main() {
for i in 253..257 {
let u = u8::try_from(i).expect("Not all integers can be represented via u8");
println!("{}", u);
}
}
u inside the loop is an u8. The code will print 253, 254, 255 and crash on the iteration where i becomes larger than what a u8 can represent.
Related
This question already has answers here:
How to slice a large Vec<i32> as &[u8]?
(2 answers)
What is the correct way to write `Vec<u16>` content to a file?
(2 answers)
How to convert vector of integers to and from bytes? [duplicate]
(2 answers)
Closed 1 year ago.
I am looking to build an array that will be copied into RAM and sent to an LCD driver. I would like to be able to pass in a color value (color: u16) and use it to populate the array. Note that I am using #![no_std] as this is intended for an embedded application.
The obvious simple approach would be as follows:
let mut block: [u8;256] = [0; 256];
for i in (0..block.len()).step_by(2) {
block[i] = ((color && 0xFF00) >> 8) as u8;
block[i+1] = (color && 0xFF) as u8;
}
As more of my personal experience comes from C, I wondered if there were any better solutions using type casting and conversion. For example, using Rust to initialize a u16 array and cast as a u8 array:
let block_u16: [u16; 128] = [color; 128]
let block_u8 = block_u16 as [u8; 256];
For reference, the target function prototype is:
spi::setup_block(block: &[u8]);
You could go the unsafe route via transmute, but I would not recommend it. I would not vouch for a C-style version to do the same on a little and big-endian machine.
Personally I would take the chunk iterator over the slice.
let color_bytes = color.to_le_bytes();
for word in block.chunks_exact_mut(2) {
word[0] = color_bytes[0];
word[1] = color_bytes[1];
}
You could use something like your second approach (casting the u16 array to a u8 pointer).
let color: u16 = 0x0102;
let mut block: [ u16; 128 ] = [ color; 128 ];
let mut block = unsafe {
core::slice::from_raw_parts_mut( block.as_mut_ptr( ) as *mut u8, block.len( ) * 2 )
};
Beware of endianness with this solution, it might not do what you want on your target architecture.
for chunk in block.chunks_exact_mut(2) {
chunk.copy_from_slice(&color.to_be_bytes());
}
This question already has answers here:
How does one round a floating point number to a specified number of digits?
(4 answers)
Closed 2 years ago.
In my rust code I have a function which takes a float and precision as args. The function should return the formatted string. However, I am not sure how I can format with dynamic precision,
fn convert(val: f32, precision: i16) -> String {
format!("{:.2}", val) // The 2 should be replaced with precision
}
// convert(1.2345, 1) -> 1.2
// convert(1.2345, 2) -> 1.23
According to the documentation:
There are three possible ways to specify the desired precision:
An integer .N:
the integer N itself is the precision.
An integer or name followed by dollar sign .N$:
use format argument N (which must be a usize) as the precision.
An asterisk .*:
.* means that this {...} is associated with two format inputs rather than one: the first input holds the usize precision, and the second holds the value to print. Note that in this case, if one uses the format string {<arg>:<spec>.*}, then the <arg> part refers to the value to print, and the precision must come in the input preceding <arg>.
That is, you can use:
fn convert(val: f32, precision: usize) -> String {
format!("{:.prec$}", val, prec = precision)
}
fn main() {
println!("{}", convert(3.14, 0));
println!("{}", convert(3.14, 1));
println!("{}", convert(3.14, 2));
println!("{}", convert(3.14, 3));
}
(Permalink to the playground)
This question already has answers here:
How to efficiently push displayable item into String? [duplicate]
(1 answer)
How can I append a formatted string to an existing String?
(1 answer)
Closed 3 years ago.
I can convert a u32 into String and append it to an existing string buffer like this
let mut a = String::new();
let b = 1_u32.to_string();
a.push_str(&b[..]);
But this involves allocation of a new string object in the heap.
How to push the string representation of a u32 without allocating a new String?
Should I implement an int-to-string function from scratch?
Use write! and its family:
use std::fmt::Write;
fn main() {
let mut foo = "answer ".to_string();
write!(&mut foo, "is {}.", 42).expect("This shouldn't fail");
println!("The {}", foo);
}
This prints The answer is 42., and does exactly one allocation (the explicit to_string).
(Permalink to the playground)
I'd like to define a function that can return a number whose type is specified when the function is called. The function takes a buffer (Vec<u8>) and returns numeric value, e.g.
let byte = buf_to_num<u8>(&buf);
let integer = buf_to_num<u32>(&buf);
The buffer contains an ASCII string that represents a number, e.g. b"827", where each byte is the ASCII code of a digit.
This is my non-working code:
extern crate num;
use num::Integer;
use std::ops::{MulAssign, AddAssign};
fn buf_to_num<T: Integer + MulAssign + AddAssign>(buf: &Vec::<u8>) -> T {
let mut result : T;
for byte in buf {
result *= 10;
result += (byte - b'0');
}
result
}
I get mismatched type errors for both the addition and the multiplication lines (expected type T, found u32). So I guess my problem is how to tell the type system that T can be expressed in terms of a literal 10 or in terms of the result of (byte - b'0')?
Welcome to the joys of having to specify every single operation you're using as a generic. It's a pain, but it is worth.
You have two problems:
result *= 10; without a corresponding From<_> definition. This is because, when you specify "10", there is no way for the compiler to know what "10" as a T means - it knows primitive types, and any conversion you defined by implementing From<_> traits
You're mixing up two operations - coercion from a vector of characters to an integer, and your operation.
We need to make two assumptions for this:
We will require From<u32> so we can cap our numbers to u32
We will also clarify your logic and convert each u8 to char so we can use to_digit() to convert that to u32, before making use of From<u32> to get a T.
use std::ops::{MulAssign, AddAssign};
fn parse_to_i<T: From<u32> + MulAssign + AddAssign>(buf: &[u8]) -> T {
let mut buffer:T = (0 as u32).into();
for o in buf {
buffer *= 10.into();
buffer += (*o as char).to_digit(10).unwrap_or(0).into();
}
buffer
}
You can convince yourself of its behavior on the playground
The multiplication is resolved by force-casting the constant as u8, which makes it benefit from our requirement of From<u8> for T and allows the rust compiler to know we're not doing silly stuff.
The final change is to set result to have a default value of 0.
Let me know if this makes sense to you (or if it doesn't), and I'll be glad to elaborate further if there is a problem :-)
In Python, this would be final_char = mystring[-1]. How can I do the same in Rust?
I have tried
mystring[mystring.len() - 1]
but I get the error the type 'str' cannot be indexed by 'usize'
That is how you get the last char (which may not be what you think of as a "character"):
mystring.chars().last().unwrap();
Use unwrap only if you are sure that there is at least one char in your string.
Warning: About the general case (do the same thing as mystring[-n] in Python): UTF-8 strings are not to be used through indexing, because indexing is not a O(1) operation (a string in Rust is not an array). Please read this for more information.
However, if you want to index from the end like in Python, you must do this in Rust:
mystring.chars().rev().nth(n - 1) // Python: mystring[-n]
and check if there is such a character.
If you miss the simplicity of Python syntax, you can write your own extension:
trait StrExt {
fn from_end(&self, n: usize) -> char;
}
impl<'a> StrExt for &'a str {
fn from_end(&self, n: usize) -> char {
self.chars().rev().nth(n).expect("Index out of range in 'from_end'")
}
}
fn main() {
println!("{}", "foobar".from_end(2)) // prints 'b'
}
One option is to use slices. Here's an example:
let len = my_str.len();
let final_str = &my_str[len-1..];
This returns a string slice from position len-1 through the end of the string. That is to say, the last byte of your string. If your string consists of only ASCII values, then you'll get the final character of your string.
The reason why this only works with ASCII values is because they only ever require one byte of storage. Anything else, and Rust is likely to panic at runtime. This is what happens when you try to slice out one byte from a 2-byte character.
For a more detailed explanation, please see the strings section of the Rust book.
As #Boiethios mentioned
let last_ch = mystring.chars().last().unwrap();
Or
let last_ch = codes.chars().rev().nth(0).unwrap();
I would rather have (how hard is that!?)
let last_ch = codes.chars(-1); // Not implemented as rustc 1.56.1