Is it possible to create a Box<(T, [U])>? - rust

The question pretty much says it: can I create a boxed tuple (or any struct) that directly contains a slice as one of its fields?
The Vec::into_boxed_slice method works to create Box<[U]>, but I would like to add on some additional data directly in the box alongside the slice.
For example, here is the kind of struct I would like to box up without using Vec into something like Box<(i32,[u8])>:
struct ConsolidateMe {
data: i32,
arr: Vec<u8>,
}
impl ConsolidateMe {
fn new(n: usize) -> Self {
let mut arr = Vec::with_capacity(n);
arr.resize(n, 42);
ConsolidateMe {
data: 15,
arr,
}
}
}
(In my application, I am creating many structs on the heap, each of which contains a small array and a few other values. The arrays have different sizes, but the size doesn't change after the struct is created. I'd like these to be compactly stored and to avoid extra indirection to the extent possible.)

The slice-dst crate looks like a perfect fit.
Example:
use slice_dst::SliceWithHeader;
#[derive(Debug, Clone)]
struct MyType {
inner: Box<SliceWithHeader<String, i32>>,
}
impl MyType {
fn new(value: &str) -> Self {
let values: Vec<i32> = value.split(" ").map(|s| s.trim().parse().unwrap()).collect();
Self {
inner: SliceWithHeader::new(value.into(), values.into_iter()),
}
}
}
fn main() {
println!("{:?}", MyType::new("1 2 3"));
}

Related

How can I mutate fields of a struct while referencing other fields?

Here's an example of a problem I ran into:
pub struct Item {
name: String,
value: LockableValue, // another struct that I'd like to mutate
}
impl Item {
pub fn name(&self) -> &str {
&self.name
}
pub fn value_mut(&mut self) -> &mut LockableValue {
&self.value
}
}
pub fn update(item: &mut Item) {
let value = item.value_mut();
value.change(); // how it changes is unimportant
println!("Updated item: {}", item.name());
}
Now, I know why this fails. I have a mutable reference to item through the mutable reference to the value.
If I convert the reference to an owned String, it works fine, but looks strange to me:
pub fn update(item: &mut Item) {
let name = { item.name().to_owned() };
let value = item.value_mut();
value.change(); // how it changes is unimportant
println!("Updated item: {}", name); // It works!
}
If I let value reference drop, then everything is fine.
pub fn update(item: &mut Item) {
{
let value = item.value_mut();
value.change(); // how it changes is unimportant
}
println!("Updated item: {}", item.name()); // It works!
}
The value.change() block is rather large, and accessing other fields in item might be helpful. So while I do have solutions to this issue, I'm wondering if there is a better (code-smell) way to do this. Any suggestions?
My intention behind the above structs was to allow Items to change values, but the name should be immutable. LockableValue is an tool to interface with another memory system, and copying/cloning the struct is not a good idea, as the memory is managed there. (I implement Drop on LockableValue to clean up.)
I was hoping it would be straight-forward to protect members of the struct from modification (even if it were immutable) like this... and I can, but it ends up looking weird to me. Maybe I just need to get used to it?
You could use interior mutability on only the part that you want to mutate by using a RefCell like ths:
use std::cell::{RefCell, RefMut};
pub struct LockableValue;
impl LockableValue {
fn change(&mut self) {}
}
pub struct Item {
name: String,
value: RefCell<LockableValue>, // another struct that I'd like to mutate
}
impl Item {
pub fn name(&self) -> &str {
&self.name
}
pub fn value_mut(&self) -> RefMut<'_, LockableValue> {
self.value.borrow_mut()
}
}
pub fn update(item: &Item) {
let name = item.name();
let mut value = item.value_mut();
value.change(); // how it changes is unimportant
println!("Updated item: {}", name);
}
That way you only need a shared reference to Item and you don't run into an issue with the borrow checker.
Not that this forces the borrow checks on value to be done at runtime though and thus comes with a performance hit.

Create a Set of Sets

How does one create a set of sets in Rust? Is it necessary to write an impl block for every concrete type satisfying HashSet<HashSet<_>>?
Minimal failing example:
fn main () {
let a: HashSet<u32> = HashSet::new();
let c: HashSet<HashSet<u32>> = HashSet::new();
c.insert(a);
}
Error:
"insert" method cannot be called on `std::collections::HashSet<std::collections::HashSet<u32>>` due to unsatisfied trait bounds
HashSet doesn't satisfy `std::collections::HashSet<u32>: Hash
Is it possible to override the fact that HashSet is unhashable? I'd like to use a HashSet and need my contents to be unique by actual (memory) equality; I don't need to unique by contents.
I'd like to have a set of sets and want them to be unique by "actual" (memory) equality, not by contents.
To do so you first need to box the hashset so that it has a stable memory address. For example:
struct Set<T>(Box<HashSet<T>>);
To make your Set hashable, you'll need to implement Hash and Eq:
impl<T> Set<T> {
fn as_addr(&self) -> usize {
// as_ref() gives the reference to the heap-allocated contents
// inside the Box, which is stable; convert that reference to a
// pointer and then to usize, and use it for hashing and equality.
self.0.as_ref() as *const _ as usize
}
}
impl<T> Hash for Set<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_addr().hash(state);
}
}
impl<T> Eq for Set<T> {}
impl<T> PartialEq for Set<T> {
fn eq(&self, other: &Self) -> bool {
self.as_addr() == other.as_addr()
}
}
Finally, you'll need to add some set-like methods and a constructor to make it usable:
impl<T: Hash + Eq> Set<T> {
pub fn new() -> Self {
Set(Box::new(HashSet::new()))
}
pub fn insert(&mut self, value: T) {
self.0.insert(value);
}
pub fn contains(&mut self, value: &T) -> bool {
self.0.contains(value)
}
}
Now your code will work, with the additional use of Rc so that you have the original Set available for lookup after you insert it:
fn main() {
let mut a: Set<u32> = Set::new();
a.insert(1);
let a = Rc::new(a);
let mut c: HashSet<_> = HashSet::new();
c.insert(Rc::clone(&a));
assert!(c.contains(&a));
}
Playground
As pointed out helpfully in the comments, it's not possible to hash sets because they have no fixed address. An effective, if inelegant, solution, is to wrap them in a specialized struct:
struct HashableHashSet<T> {
hash: ...
hashset: HashSet<T>
}
And then hash the struct by memory equality.

How do I get automagic convertions from Rust Into trait?

I have a struct Object for which I have many implementations of From (including isize and &str). I got the sense from this article where Into is described as 'genius' that things could get automatically converted for me. I've incorporated the suggestions that people have made, and made something that is standalone in the playground but it still gets a couple of errors.
#[derive(Copy,Clone)]
pub union Object {
d:f64,
i:isize,
}
impl From<isize> for Object {
fn from(i:isize) -> Self {
Object{i}
}
}
impl From<f64> for Object {
fn from(d:f64) -> Self {
Object{d}
}
}
pub fn old_convert(foo: Object, _elements: &[Object]) -> Object {
foo
}
pub fn new_convert<'a,T>(foo: impl Into<Object>, elements: &'a [T]) -> Object
where
&'a T: Into<Object>,
Object: From<T>,
{
let mut el = Vec::new();
for o in elements.iter() {
el.push(o.into())
}
old_convert(foo.into(),&el)
}
#[test]
fn testOldConvert() {
old_convert(Object::from(42), &[Object::from(3.1415)]);
}
#[test]
fn testNewConvert() {
new_convert(42, &[3.1415]);
}
So you can see what I currently do. I'd like to not have to include all the Object::from(...) when I use my function.
There is 1 error, and 1 problem:
I don't know how to implement the From it's asking for
I don't want to create the temporary vector... surely there's some zero-cost abstraction that allows me to pass the converted array along

How can I implement Ord when the comparison depends on data not part of the compared items?

I have a small struct containing only an i32:
struct MyStruct {
value: i32,
}
I want to implement Ord in order to store MyStruct in a BTreeMap or any other data structure that requires you to have Ord on its elements.
In my case, comparing two instances of MyStruct does not depend on the values in them, but asking another data structure (a dictionary), and that data structure is unique for each instance of the BTreeMap I will create. So ideally it would look like this:
impl Ord for MyStruct {
fn cmp(&self, other: &Self, dict: &Dictionary) -> Ordering {
dict.lookup(self.value).cmp(dict.lookup(other.value))
}
}
However this won't be possible, since an Ord implementation only can access two instances of MyStruct, nothing more.
One solution would be storing a pointer to the dictionary in MyStruct but that's overkill. MyStruct is supposed to be a simple wrapper and the pointer would double its size. Another solution is to use a static global, but that's not a good solution either.
In C++ the solution would be easy: Most STL algorithms/data structures let you pass a comparator, where it can be a function object with some state. So I believe Rust would have an idiom to match this somehow, is there any way to accomplish this?
Rust (more specifically Rust's libcollections) currently has no comparator-like construct, so using a mutable static is probably your best bet. This is also used within rustc, e.g. the string interner is static. With that said, the use case isn't exactly uncommon, so maybe if we petition for it, Rust will get external comparators one day.
I remember the debate over whether allowing a custom comparator was worth it or not, and it was decided that this complicated the API a lot when most of the times one could achieve the same effect by using a new (wrapping) type and redefine PartialOrd for it.
It was, ultimately, a trade-off: weighing API simplicity versus unusual needs (which are probably summed up as access to external resources).
In your specific case, there are two solutions:
use the API the way it was intended: create a wrapper structure containing both an instance of MyStruct and a reference to the dictionary, then define Ord on that wrapper and use this as key in the BTreeMap
circumvent the API... somehow
I would personally advise starting with using the API as intended, and measure, before going down the road of trying to circumvent it.
#ker was kind enough to provide the following illustration of achieving wrapping in comments (playground version):
#[derive(Eq, PartialEq, Debug)]
struct MyStruct {
value: i32,
}
#[derive(Debug)]
struct MyStructAsKey<'a> {
inner: MyStruct,
dict: &'a Dictionary,
}
impl<'a> Eq for MyStructAsKey<'a> {}
impl<'a> PartialEq for MyStructAsKey<'a> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner && self.dict as *const _ as usize == other.dict as *const _ as usize
}
}
impl<'a> Ord for MyStructAsKey<'a> {
fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
self.dict.lookup(&self.inner).cmp(&other.dict.lookup(&other.inner))
}
}
impl<'a> PartialOrd for MyStructAsKey<'a> {
fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
Some(self.dict.lookup(&self.inner).cmp(&other.dict.lookup(&other.inner)))
}
}
#[derive(Default, Debug)]
struct Dictionary(::std::cell::RefCell<::std::collections::HashMap<i32, u64>>);
impl Dictionary {
fn ord_key<'a>(&'a self, ms: MyStruct) -> MyStructAsKey<'a> {
MyStructAsKey {
inner: ms,
dict: self,
}
}
fn lookup(&self, key: &MyStruct) -> u64 {
self.0.borrow()[&key.value]
}
fn create(&self, value: u64) -> MyStruct {
let mut map = self.0.borrow_mut();
let n = map.len();
assert!(n as i32 as usize == n);
let n = n as i32;
map.insert(n, value);
MyStruct {
value: n,
}
}
}
fn main() {
let dict = Dictionary::default();
let a = dict.create(99);
let b = dict.create(42);
let mut set = ::std::collections::BTreeSet::new();
set.insert(dict.ord_key(a));
set.insert(dict.ord_key(b));
println!("{:#?}", set);
let c = dict.create(1000);
let d = dict.create(0);
set.insert(dict.ord_key(c));
set.insert(dict.ord_key(d));
println!("{:#?}", set);
}

Same object with different API faces at compile time?

I have an object that can be in either of two modes: a source or a sink. It is always in one of them and it is always known at compile time (when passed the object you know if you are going to read or write to it obviously).
I can put all the methods on the same object, and just assume I won't be called improperly or error when I do, or I was thinking I could be make two
tuple structs of the single underlying object and attach the methods to those tuple structs instead. The methods are almost entirely disjoint.
It is kind of abusing the fact that both tuple structs have the same layout and there is zero overhead for the casts and tuple storage.
Think of this similar to the Java ByteBuffer and related classes where you write then flip then read then flip back and write more. Except this would catch errors in usage.
However, it does seem a little unusual and might be overly confusing for such a small problem. And it seems like there is a better way to do this -- only requirement is zero overhead so no dynamic dispatch.
https://play.rust-lang.org/?gist=280d2ec2548e4f38e305&version=stable
#[derive(Debug)]
struct Underlying {
a: u32,
b: u32,
}
#[derive(Debug)]
struct FaceA(Underlying);
impl FaceA {
fn make() -> FaceA { FaceA(Underlying{a:1,b:2}) }
fn doa(&self) { println!("FaceA do A {:?}", *self); }
fn dou(&self) { println!("FaceA do U {:?}", *self); }
fn tob(&self) -> &FaceB { unsafe{std::mem::transmute::<&FaceA,&FaceB>(self)} }
}
#[derive(Debug)]
struct FaceB(Underlying);
impl FaceB {
fn dob(&self) { println!("FaceB do B {:?}", *self); }
fn dou(&self) { println!("FaceB do U {:?}", *self); }
fn toa(&self) -> &FaceA { unsafe{std::mem::transmute::<&FaceB,&FaceA>(self)} }
}
fn main() {
let a = FaceA::make();
a.doa();
a.dou();
let b = a.tob();
b.dob();
b.dou();
let aa = b.toa();
aa.doa();
aa.dou();
}
First of all, it seems like you don't understand how ownership works in Rust; you may want to read the Ownership chapter of the Rust Book. Specifically, the way you keep re-aliasing the original FaceA is how you would specifically enable the very thing you say you want to avoid. Also, all the borrows are immutable, so it's not clear how you intend to do any sort of mutation.
As such, I've written a new example from scratch that involves going between two types with disjoint interfaces (view on playpen).
#[derive(Debug)]
pub struct Inner {
pub value: i32,
}
impl Inner {
pub fn new(value: i32) -> Self {
Inner {
value: value,
}
}
}
#[derive(Debug)]
pub struct Upper(Inner);
impl Upper {
pub fn new(inner: Inner) -> Self {
Upper(inner)
}
pub fn into_downer(self) -> Downer {
Downer::new(self.0)
}
pub fn up(&mut self) {
self.0.value += 1;
}
}
#[derive(Debug)]
pub struct Downer(Inner);
impl Downer {
pub fn new(inner: Inner) -> Self {
Downer(inner)
}
pub fn into_upper(self) -> Upper {
Upper::new(self.0)
}
pub fn down(&mut self) {
self.0.value -= 1;
}
}
fn main() {
let mut a = Upper::new(Inner::new(0));
a.up();
let mut b = a.into_downer();
b.down();
b.down();
b.down();
let mut c = b.into_upper();
c.up();
show_i32(c.0.value);
}
#[inline(never)]
fn show_i32(v: i32) {
println!("v: {:?}", v);
}
Here, the into_upper and into_downer methods consume the subject value, preventing anyone from using it afterwards (try accessing a after the call to a.into_downer()).
This should not be particularly inefficient; there is no heap allocation going on here, and Rust is pretty good at moving values around efficiently. If you're curious, this is what the main function compiles down to with optimisations enabled:
mov edi, -1
jmp _ZN8show_i3220h2a10d619fa41d919UdaE
It literally inlines the entire program (save for the show function that I specifically told it not to inline). Unless profiling shows this to be a serious performance problem, I wouldn't worry about it.

Resources