Converting between extprim::u128::u128 and primitive u128 in Rust? - rust

I'm working with an old Rust module that uses the extprim crate to provide a u128 type.
I'm trying to use this with a newer crate that uses Rust's primitive u128 type (available since Rust 1.26).
What's an efficient way to convert back and forth between these two types?

Update:
When your rustc version is greater than 1.26.0 the From trait is implemented and you can use into respectively from easily.
For a lower version than that see below.
As a note: "The most efficient way" is very subjective.
I would use the low64() and high64() methods to generate a rust u128.
extern crate extprim; // 1.6.0
use extprim::u128;
fn main() {
let number = u128::u128::from_parts(6_692_605_942, 14_083_847_773_837_265_618);
println!("{:?}", number);
// going forth
let real_number = u128::from(number.high64()) << 64 | u128::from(number.low64());
println!("{:?}", number);
assert_eq!(number.to_string(), real_number.to_string());
// and back
let old_number = u128::u128::from_parts((real_number >> 64) as u64, (real_number) as u64);
assert_eq!(number, old_number);
}
(playground)
Since you can't compare both directly, I used the to_string() function to convert them to a string and compare those.

Related

Is there an easier way of calling functions at static addresses? [duplicate]

I am writing an OS in Rust and need to directly call into a virtual address that I'm calculating (of type u32). I expected this to be relatively simple:
let code = virtual_address as (extern "C" fn ());
(code)();
However, this complains that the cast is non-primitive. It suggests I use the From trait, but I don't see how this could help (although I am relatively new to Rust and so could be missing something).
error[E0605]: non-primitive cast: `u32` as `extern "C" fn()`
--> src/main.rs:3:16
|
3 | let code = virtual_address as (extern "C" fn ());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
I have everything in libcore at my disposal, but haven't ported std and so can't rely on anything that isn't no_std
Casts of the type _ as f-ptr are not allowed (see the Rustonomicon chapter on casts). So, as far as I can tell, the only way to cast to function pointer types is to use the all mighty weapon mem::transmute().
But before we can use transmute(), we have to bring our input into the right memory layout. We do this by casting to *const () (a void pointer). Afterwards we can use transmute() to get what we want:
let ptr = virtual_address as *const ();
let code: extern "C" fn() = unsafe { std::mem::transmute(ptr) };
(code)();
If you find yourself doing this frequently, various kinds of macros can remove the boilerplate. One possibility:
macro_rules! example {
($address:expr, $t:ty) => {
std::mem::transmute::<*const (), $t>($address as _)
};
}
let f = unsafe { example!(virtual_address, extern "C" fn()) };
f();
However, a few notes on this:
If you, future reader, want to use this to do simple FFI things: please take a moment to think about it again. Calculating function pointers yourself is rarely necessary.
Usually extern "C" functions have the type unsafe extern "C" fn(). This means that those functions are unsafe to call. You should probably add the unsafe to your function.

How to convert a very large decimal string to hexadecimal?

let hex = "100000000000000000".as_bytes().to_hex();
// hex == "313030303030303030303030303030303030"
println!("{:x}", 100000000000000000000000u64);
// literal out of range for u64
How can I got that value?
In Python, I would just call hex(100000000000000000000000) and I get '0x152d02c7e14af6800000'.
to_hex() comes from the hex crate.
One needs to be aware of the range of representable values for different numeric types in Rust. In this particular case, the value exceeds the limits of an u64, but the u128 type accommodates the value. The following code outputs the same value as the example in Python:
fn main() {
let my_string = "100000000000000000000000".to_string(); // `parse()` works with `&str` and `String`!
let my_int = my_string.parse::<u128>().unwrap();
let my_hex = format!("{:X}", my_int);
println!("{}", my_hex);
}
Checked with the Rust Playground:
152D02C7E14AF6800000
An explicit usage of arbitrary precision arithmetic is required in the general case. A few suggestions from What's the best crate for arbitrary precision arithmetic in Rust? on Reddit:
num_bigint works on stable and does not have unsafe code.
ramp uses unsafe and does not work on stable Rust, but it is faster.
rust-gmp and rug bind to the state-of-the-art bigint implementation in C (GMP). They are the fastest and have the most features. You probably want to use one of those.

Ergonomics issues with fixed size byte arrays in Rust

Rust sadly cannot produce a fixed size array [u8; 16] with a fixed size slicing operator s[0..16]. It'll throw errors like "expected array of 16 elements, found slice".
I've some KDFs that output several keys in wrapper structs like
pub struct LeafKey([u8; 16]);
pub struct MessageKey([u8; 32]);
fn kdfLeaf(...) -> (MessageKey,LeafKey) {
// let mut r: [u8; 32+16];
let mut r: (MessageKey, LeafKey);
debug_assert_eq!(mem::size_of_val(&r), 384/8);
let mut sha = Sha3::sha3_384();
sha.input(...);
// sha.result(r);
sha.result(
unsafe { mem::transmute::<&mut (MessageKey, LeafKey),&mut [u8;32+16]>(&r) }
);
sha.reset();
// (MessageKey(r[0..31]), LeafKey(r[32..47]))
r
}
Is there a safer way to do this? We know mem::transmute will refuse to compile if the types do not have the same size, but that only checks that pointers have the same size here, so I added that debug_assert.
In fact, I'm not terribly worried about extra copies though since I'm running SHA3 here, but afaik rust offers no ergonomic way to copy amongst byte arrays.
Can I avoid writing (MessageKey, LeafKey) three times here? Is there a type alias for the return type of the current function? Is it safe to use _ in the mem::transmute given that I want the code to refuse to compile if the sizes do not match? Yes, I know I could make a type alias, but that seems silly.
As an aside, there is a longer discussion of s[0..16] not having type [u8; 16] here
There's the copy_from_slice method.
fn main() {
use std::default::Default;
// Using 16+8 because Default isn't implemented
// for [u8; 32+16] due to type explosion unfortunateness
let b: [u8; 24] = Default::default();
let mut c: [u8; 16] = Default::default();
let mut d: [u8; 8] = Default::default();
c.copy_from_slice(&b[..16])
d.copy_from_slice(&b[16..16+8]);
}
Note, unfortunately copy_from_slice throws a runtime error if the slices are not the same length, so make sure you thoroughly test this yourself, or use the lengths of the other arrays to guard.
Unfortunately, c.copy_from_slice(&b[..c.len()]) doesn't work because Rust thinks c is borrowed both immutably and mutably at the same time.
I marked the accepted answer as best since it's safe, and led me to the clone_into_array answer here, but..
Another idea that improves the safety is to make a version of mem::transmute for references that checks the sizes of the referenced types, as opposed to just the pointers. It might look like :
#[inline]
unsafe fn transmute_ptr_mut<A,B>(v: &mut A) -> &mut B {
debug_assert_eq!(core::mem::size_of(A),core::mem::size_of(B));
core::mem::transmute::<&mut A,&mut B>(v)
}
I have raised an issue on the arrayref crate to discuss this, as arrayref might be a reasonable crate for it to live in.
Update : We've a new "best answer" by the arrayref crate developer :
let (a,b) = array_refs![&r,32,16];
(MessageKey(*a), LeafKey(*b))

How to build an Rc<str> or Rc<[T]>?

I'd like to create an Rc<str> because I want reduce the indirection from following the 2 pointers that accessing an Rc<String> requires. I need to use an Rc because I truly have shared ownership. I detail in another question more specific issues I have around my string type.
Rc has a ?Sized bound:
pub struct Rc<T: ?Sized> { /* fields omitted */ }
I've also heard that Rust 1.2 will come with proper support for storing unsized types in an Rc, but I'm unsure how this differs from 1.1.
Taking the str case as example, my naive attempt (also this for building from a String) fails with:
use std::rc::Rc;
fn main() {
let a: &str = "test";
let b: Rc<str> = Rc::new(*a);
println!("{}", b);
}
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> src/main.rs:5:22
|
5 | let b: Rc<str> = Rc::new(*a);
| ^^^^^^^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: required by `<std::rc::Rc<T>>::new`
It's clear that in order to create an Rc<str>, I need to copy the whole string: RcBox would be itself an unsized type, storing the string itself alongside the weak and strong pointers — the naive code above doesn't even make sense.
I've been told that one can not instantiate such type, but instead instantiate an Rc<T> with a sized T and then coerce it to an unsized type. The example given is for the storing a trait object: first create Rc<ConcreteType> and then coerce to Rc<Trait>. But this doesn't make sense either: neither this nor this work (and you can't coerce from &str or String to str anyway).
As of Rust 1.21.0 and as mandated by RFC 1845, creating an Rc<str> or Arc<str> is now possible:
use std::rc::Rc;
use std::sync::Arc;
fn main() {
let a: &str = "hello world";
let b: Rc<str> = Rc::from(a);
println!("{}", b);
// or equivalently:
let b: Rc<str> = a.into();
println!("{}", b);
// we can also do this for Arc,
let a: &str = "hello world";
let b: Arc<str> = Arc::from(a);
println!("{}", b);
}
(Playground)
See <Rc as From<&str>> and <Arc as From<&str>>.
Creating an Rc<[T]> can be done via coercions and as-casts from fixed sized arrays, e.g. coercions can be done as follows:
use std::rc::Rc;
fn main() {
let x: Rc<[i32; 4]> = Rc::new([1, 2, 3, 4]);
let y: Rc<[i32]> = x;
println!("{:?}", y);
}
However, this doesn't work for strings, since they have no raw fixed-sized equivalent to create the first value. It is possible to do unsafely, e.g. by creating a UTF-8 encoded Rc<[u8]> and transmuting that to Rc<str>. Theoretically there could be a crate on crates.io for it, but I can't find one at the moment.
An alternative is owning_ref, which isn't quite std::rc::Rc itself, but should allow, for example, getting an RcRef<..., str> pointing into an Rc<String>. (This approach will work best if one uses RcRef uniformly in place of Rc, except for construction.)
extern crate owning_ref;
use owning_ref::RcRef;
use std::rc::Rc;
fn main() {
let some_string = "foo".to_owned();
let val: RcRef<String> = RcRef::new(Rc::new(some_string));
let borrowed: RcRef<String, str> = val.map(|s| &**s);
let erased: RcRef<owning_ref::Erased, str> = borrowed.erase_owner();
}
The erasing means that RcRef<..., str>s can come from multiple different sources, e.g. a RcRef<Erased, str> can come from a string literal too.
NB. at the time of writing, the erasure with RcRef requires a nightly compiler, and depending on owning_ref with the nightly feature:
[dependencies]
owning_ref = { version = "0.1", features = ["nightly"] }

What is the stable alternative of to_string()

I'm working my way through the rust book. In the Strings chapter a lot of the examples use to_string() which my version of the compiler(rustc 1.0.0-dev) gives the following warning
strings.rs:3:23: 3:34 warning: use of unstable item, #[warn(unstable)] on by default
strings.rs:3 let mut s = "Hello".to_string();
Code:
fn main() {
let mut s = "Hello".to_string();
println!("{}", s);
}
I understand from this question that this is because the API is likely to change, but I would like to know what I should use instead if I want to convert a string slice (str&) to a String
You can work around these things, e.g. format!("Hello"), but I really wouldn’t bother for the moment.

Resources