How can I convert a Vec<String> to a &[&gtk::ToValue]? [duplicate] - vector

This question already has answers here:
Is there any way to return a reference to a variable created in a function?
(5 answers)
Cannot call rusqlite's query because it expects the type &[&rusqlite::types::ToSql]
(1 answer)
Closed 5 years ago.
I've been trying many things from nested loops and sequential duplicated nested loops to this:
pub fn values_to_references<'a>(values_vector: Vec<String>) -> Vec<&'a gtk::ToValue> {
values_vector
.into_iter()
.map(| item: String | &item.to_value() as &ToValue)
.collect()
}
But whatever I try, the compiler always tells me that the lifetime of item is too short:
borrowed value must be valid for the lifetime 'a as defined on the body at 87:89...
borrowed value does not live long enough (does not live long enough)
I need to convert to those references in order to add Strings to a gtk::TreeModel (gtk::TreeStore), which will balk at anything other than that it seems. All examples I could find use references to static strings, which are known at compile time. That's not very useful. My strings come from a JSON file and cannot be known at compile time.
I want to be able to do the following with the gtk::TreeModel:
model.insert_with_values(
None,
None,
&[0, 1, 2, 3],
to_value_items.as_slice());
How can I achieve this?
Example Code
More code from my attempts to add stuff to a gtk::TreeStore or gtk::TreeModel:
pub fn add_to_tree_store(tree_store: &TreeStore, row: Vec<String>) {
tree_store.insert_with_values(
None,
None,
&[0, 1, 2, 3],
VocTreeView::strings_to_ampersand_str(row)
.iter()
.map(|x| x as &ToValue)
.collect());
}
pub fn strings_to_ampersand_str<'res_ref>(values_vector: Vec<String>) -> Vec<&'res_ref str> {
let append_values: Vec<_> = values_vector.iter().map(|x| &x[..]).collect();
append_values
}
This fails at collect():
a collection of type `&[&gtk::ToValue]` cannot be built from an iterator over elements of type `&gtk::ToValue` [E0277]
the trait bound `&[&gtk::ToValue]: std::iter::FromIterator<&gtk::ToValue>` is not satisfied (the trait `std::iter::FromIterator<&gtk::ToValue>` is not implemented for `&[&gtk::ToValue]`) [E0277]
Seems the same problem is again biting me.
Example Code 2
pub fn add_to_tree_store(tree_store: &TreeStore, row: Vec<String>) {
tree_store.insert_with_values(
None,
None,
&[0, 1, 2, 3],
VocTreeView::values_to_references(&row)
.iter()
.map(|x| x as &gtk::ToValue)
.collect());
}
pub fn values_to_references(values_vector: &[String]) -> Vec<&gtk::ToValue> {
values_vector
.into_iter()
.map(|item| item as &gtk::ToValue)
.collect()
}
This runs into an error at x inside map and collect as well:
At x:
required for the cast to the object type `gtk::ToValue` [E0277]
required because of the requirements on the impl of `gtk::ToValue` for `&gtk::ToValue` [E0277]
required because of the requirements on the impl of `glib::value::SetValue` for `&gtk::ToValue` [E0277]
the trait bound `gtk::ToValue: glib::value::SetValue` is not satisfied (the trait `glib::value::SetValue` is not implemented for `gtk::ToValue`) [E0277]
At collect:
a collection of type `&[&gtk::ToValue]` cannot be built from an iterator over elements of type `&gtk::ToValue` [E0277]
the trait bound `&[&gtk::ToValue]: std::iter::FromIterator<&gtk::ToValue>` is not satisfied (the trait `std::iter::FromIterator<&gtk::ToValue>` is not implemented for `&[&gtk::ToValue]`) [E0277]

Related

How to relax implicit Sized bound in Rust with indirection? [duplicate]

This question already has answers here:
How do I store a closure in a struct in Rust?
(2 answers)
Is it possible to have a heterogeneous vector of types that implement Eq?
(1 answer)
Closed 2 years ago.
I've been trying to implement a simple job scheduler. I've got 2 job types async and sync job. They have a property named context which simply is a function. I'm storing a date property too.
So the issue is when I try to write a scheduler it shows the following error
the size for values of type `dyn Fn()` cannot be known at compilation time
the trait `Sized` is not implemented for `dyn Fn()`rustc(E0277)
sync_job.rs(6, 23): required by this bound in `sync_job::SyncJob`
sync_job.rs(6, 23): you could relax the implicit `Sized` bound on `L` if it were used through indirection like `&L` or `Box<L>`
I've created the SyncJob struct like this:
pub struct SyncJob<T, L>
where
T: chrono::Datelike,
L: Fn(),
{
pub scheduled: Option<T>,
pub context: L,
pub repeating: bool,
pub repeating_times: u32
}
Got scheduler like this:
pub struct Scheduler<'a, T>
where
T: Schedule + Sized
{
jobs: Box<Vec<&'a T>>
}
impl<L> Scheduler<'_, SyncJob<NaiveDateTime, L>>
where
L: Fn() + 'static + Sized
{
fn new(jobs:&'static Vec<&SyncJob<NaiveDateTime, L>>) -> Self {
Scheduler {
jobs: Box::new(jobs.clone())
}
}
}
And trying to create it like this:
let scheduler: Scheduler<SyncJob<NaiveDateTime, dyn Fn() + Sized>> = Scheduler::new(vec![]);
What is the problem here? I can create SyncJob and AsyncJob without any hassle but when I try to put them in a vector, it blows ._.

Is it possible to somehow cast Vec<Option<Value>> into Vec<Value> after filtering out None elements in Rust? [duplicate]

This question already has an answer here:
How do I avoid unwrap when converting a vector of Options or Results to only the successful values?
(1 answer)
Closed 4 years ago.
I want some way to have such a cast when writing code like this:
struct Value;
fn remove_missed(uncertain_vector: Vec<Option<Value>>) -> Vec<Value> {
uncertain_vector
.into_iter()
.filter(|element| match element {
Some(val) => true,
None => false,
})
.collect()
}
How can I achieve this? I believe that the type implication mechanism is not smart enough to determine that the resulting collection will contain only Option<Value> where all such objects are the same in terms of their type (Value).
The compiler answers my question partially:
error[E0277]: a collection of type `std::vec::Vec<Value>` cannot be built from an iterator over elements of type `std::option::Option<Value>`
--> src/lib.rs:10:10
|
10 | .collect()
| ^^^^^^^ a collection of type `std::vec::Vec<Value>` cannot be built from `std::iter::Iterator<Item=std::option::Option<Value>>`
|
= help: the trait `std::iter::FromIterator<std::option::Option<Value>>` is not implemented for `std::vec::Vec<Value>`
You can use Iterator::flatten which creates "an iterator that flattens nested structure" – in this case, pulls out Some from Option.
let v = vec![None, None, Some(1), Some(2), None, Some(3)];
let filtered: Vec<_> = v.into_iter().flatten().collect();
Or Iterator::filter_map to filter and map the element in one go – with an equal result.
let filtered: Vec<_> = v.into_iter().filter_map(|e| e).collect();
Playground

How can I index a collection of records by one of their field? [duplicate]

This question already has answers here:
How to use a struct's member as its own key when inserting the struct into a map without duplicating it?
(2 answers)
Closed 4 years ago.
I have a Record type, with a get_key(&self) -> &str method (borrowing the returned str from inside the record). Records may be mutable, but their key is guaranteed not to change.
I want to store a list of records in a collection, and be able to retrieve a record by its key. The first idea is to use a HashMap<String, Record>, but that looks like a waste of space (because the strings in the key position are copies of the record's keys).
I would rather have a HashMap<&str, Record>, but I can't provide a lifetime for the &str keys (since they are borrowed from inside the hashmap). This is the kind of self-reference that crates like rental or owning_ref are designed to handle. However, none of them provide an out-of-the-box solution for this use-case.
I looked for a crate providing this kind of "indexed collection", but to no avail. Am I missing something? (I started hacking a solution of my own, but I'd rather not re-invent the wheel)
If you want a container where the key itself is part of the value, you can use HashSet with a newtype to reimplement the required traits: Hash, Borrow<str>, PartialEq and Eq.
For example (link to playground):
struct HRecord(Record);
impl Hash for HRecord {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.get_key().hash(state);
}
}
impl PartialEq for HRecord {
fn eq(&self, r: &HRecord) -> bool {
self.0.get_key().eq(r.0.get_key())
}
}
impl Eq for HRecord {}
impl Borrow<str> for HRecord {
fn borrow(&self) -> &str {
self.0.get_key()
}
}
And now the HashMap just works:
let mut h = HashSet::new();
h.insert(HRecord(Record { ... }));
let obj = h.get("...").map(|h| &h.0);

Pointer-stashing generics via `mem::transmute()`

I'm attempting to write Rust bindings for a C collection library (Judy Arrays [1]) which only provides itself room to store a pointer-width value. My company has a fair amount of existing code which uses this space to directly store non-pointer values such as pointer-width integers and small structs. I'd like my Rust bindings to allow type-safe access to such collections using generics, but am having trouble getting the pointer-stashing semantics working correctly.
The mem::transmute() function seems like one potential tool for implementing the desired behavior, but attempting to use it on an instance of a parameterized type yield a confusing-to-me compilation error.
Example code:
pub struct Example<T> {
v: usize,
t: PhantomData<T>,
}
impl<T> Example<T> {
pub fn new() -> Example<T> {
Example { v: 0, t: PhantomData }
}
pub fn insert(&mut self, val: T) {
unsafe {
self.v = mem::transmute(val);
}
}
}
Resulting error:
src/lib.rs:95:22: 95:36 error: cannot transmute to or from a type that contains type parameters in its interior [E0139]
src/lib.rs:95 self.v = mem::transmute(val);
^~~~~~~~~~~~~~
Does this mean a type consisting only of a parameter "contains type parameters in its interior" and thus transmute() just won't work here? Any suggestions of the right way to do this?
(Related question, attempting to achieve the same result, but not necessarily via mem::transmute().)
[1] I'm aware of the existing rust-judy project, but it doesn't support the pointer-stashing I want, and I'm writing these new bindings largely as a learning exercise anyway.
Instead of transmuting T to usize directly, you can transmute a &T to &usize:
pub fn insert(&mut self, val: T) {
unsafe {
let usize_ref: &usize = mem::transmute(&val);
self.v = *usize_ref;
}
}
Beware that this may read from an invalid memory location if the size of T is smaller than the size of usize or if the alignment requirements differ. This could cause a segfault. You can add an assertion to prevent this:
assert_eq!(mem::size_of::<T>(), mem::size_of::<usize>());
assert!(mem::align_of::<usize>() <= mem::align_of::<T>());

Rust Vector of Traits: cast each trait

I have a problem casting a vector of traits into a vector of different traits.
Using the approach of Type-casting arrays/vectors in Rust , I basically tried the following:
trait ParentTrait {}
trait ChildTrait: ParentTrait {}
fn main() {
let mut children: Vec<Box<ChildTrait>> = vec![];
let parents = children.iter().map(|&e| e as Box<ParentTrait>);
}
Now this does not compile, it results in
error: the trait `core::kinds::Sized` is not implemented for the type `ChildTrait`
[...]
error: the trait `ParentTrait` is not implemented for the type `ChildTrait`
[...]
(The second errorline is buggy behaviour of the compiler, I guess?)
I tried various other flavors of References / Boxes and could not get it to work.
What am I doing wrong here,
is this even the correct approach with newer versions of rust (0.13)?
Trait objects are very strange beasts.
What is a Box<ChildTrait>? Box<T> is literally a wrapper for a *mut T. Therefore, a Box<ChildTrait> wraps a *mut ChildTrait. Because ChildTrait names a trait, ChildTrait is an object type. A pointer to an object type is represented by a pair of pointers: a pointer to the vtable for that trait and only that trait, and a pointer to the actual value.
When we inherit a trait from another trait, that doesn't mean we can obtain a pointer to the vtable for the first trait from a pointer to the vtable for the second trait. This is why the compiler complains that
the trait `ParentTrait` is not implemented for the type `ChildTrait`
We can, however, manually implement a trait for an object type. Because object types are unsized, we must first allow ParentTrait to be implemented for unsized types:
trait ParentTrait for Sized? {}
Then we can provide an impl of ParentTrait for the ChildTrait object type:
impl<'a> ParentTrait for ChildTrait+'a {}
If we try to compile now, we get different errors:
<anon>:9:40: 9:42 error: cannot move out of dereference of `&`-pointer
<anon>:9 let parents = children.iter().map(|&e| e as Box<ParentTrait>);
^~
<anon>:9:41: 9:42 note: attempting to move value to here
<anon>:9 let parents = children.iter().map(|&e| e as Box<ParentTrait>);
^
<anon>:9:41: 9:42 help: to prevent the move, use `ref e` or `ref mut e` to capture value by reference
<anon>:9 let parents = children.iter().map(|&e| e as Box<ParentTrait>);
We can use into_iter instead of iter to consume the initial Vec:
fn main() {
let mut children: Vec<Box<ChildTrait>> = vec![];
let parents = children.into_iter().map(|e| e as Box<ParentTrait>);
}
But then we get an internal compiler error:
error: internal compiler error: trying to take the sizing type of ChildTrait, an unsized type
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html
note: run with `RUST_BACKTRACE=1` for a backtrace
task 'rustc' panicked at 'Box<Any>', /build/rust-git/src/rust/src/libsyntax/diagnostic.rs:175
The same error also occurs with this code:
fn main() {
let mut children: Vec<Box<ChildTrait>> = vec![];
let parents = children.iter().map(|e| &**e as &ParentTrait);
}
At this point, I don't know if, after fixing the ICE, this would compile successfully or not.

Resources