Im trying print out a encoded hex string of some basic data ive inserted as a lesson how to serialize/deserialize data. However todo this im having to implement an iterator for a Struct that has a single element of type Vec. Im getting the below error and don't understand why, I realize my code is incomplete in the next() implementation. I'm fairly new to iterators, any help would be appreciated.
Error:
error[E0599]: no method named `iter_mut` found for struct `MyData` in the current scope
--> src/main.rs:110:22
|
21 | pub(crate) struct MyData {
| ------------------------ method `iter_mut` not found for this struct
...
110 | for v in my_data.iter_mut() {
|
#[derive(Serialize, Deserialize, Debug)]
#[serde(transparent)]
struct MyHex {
#[serde(with = "hex::serde")]
hex: Vec<u8>,
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct MyData {
data: Vec<MyHex>,
}
impl Iterator for MyData {
type Item = usize;
fn next(&mut self) -> Option<Self::Item>;
}
fn main() -> Result<()> {
let data = "
{
\"data\": [\"bbac4013c1ca3482155b584d35dac185\",
\"a08898e81f1ddb6612aa12641b856aa9\",
\"bbac4013c1ca3482155b584d35dac185\"
]
}";
let my_data: MyData = serde_json::from_str(data)?;
for v in my_data.iter_mut() {
println!("{:?}", hex::encode(v));
}
return Ok(());
}
You question is a little fuzzy but let's try to see what we can do:
Iterating over inner field
If you want to do something with the data byte by byte, you can iterate over data itself:
for hex in my_data.data { ... }
Iterating without exposing inner fields
You can also return iterator over data without exposing the field to the rest of the code:
impl MyData {
fn iter_data(&self) -> impl Iterator<Item = &MyHex> {
self.data.iter()
}
}
...
for hex in my_data.iter_data() { ... }
Implementing IntoIterator
If you want MyData work as an iterator, you can implement IntoIterator trait for it:
impl<'a> IntoIterator for &'a MyData {
type Item = &'a MyHex;
type IntoIter = std::slice::Iter<'a, MyHex>;
fn into_iter(self) -> Self::IntoIter {
self.data.iter()
}
}
...
for v in &my_data {
println!("{:?}", v);
}
Playground
Implementing Iterator for MyData
To implement Iterator you need to provide the next method, which on every call will return the next item in the iterator while there are any items left. To do so you would add a field to you MyData that keeps track of the last item that was return, and increment that pointer on every call of next().
But from your code I guess this is not something you actually want. Go rather with one of the previous options.
Related
As a beginner in rust I am trying to implement basic data structures. Here I am trying to implement a stack. Here are the structs I am using
#[derive(Debug, Clone)]
struct Node<T: std::marker::Copy> {
value: T,
next: Option<Box<Node<T>>>,
}
impl<T: std::marker::Copy> Node<T> {
fn new(value: T) -> Node<T> {
Node { value, next: None }
}
}
#[derive(Debug, Clone)]
struct Stack<T: std::marker::Copy> {
first: Option<Box<Node<T>>>,
last: Option<Box<Node<T>>>,
size: usize,
}
Now, in push() function, what I'm trying to do is, if there is no first and last, put the newly created Node as the new first and last. If they exist already, create a new variable temp which holds the current first, put the new Node as the new value in first, and put the previous first's next value as temp. Here is my push().
impl<T: std::marker::Copy> Stack<T> {
fn push(&mut self, elem: T) -> usize {
if self.first.is_none() {
self.first = Some(Box::new(Node::new(elem)));
self.last = Some(Box::new(Node::new(elem)));
} else {
let temp = self.first.take();
self.first = Some(Box::new(Node::new(elem)));
self.first.unwrap().next = Some(Box::new(*temp.unwrap())); //problem in this line
}
self.size += 1;
self.size
}
}
Here when I'm trying to assign the next value, I'm getting the error
cannot move out of `self.first` which is behind a mutable reference
--> src/bin/stack.rs:36:13
|
36 | self.first.unwrap().next = Some(Box::new(*temp.unwrap()));
| ^^^^^^^^^^ move occurs because `self.first` has type `Option<Box<Node<T>>>`, which does not implement the `Copy` trait
|
help: consider borrowing the `Option`'s content
|
36 | self.first.as_ref().unwrap().next = Some(Box::new(*temp.unwrap()));
| +++++++++
Using as_ref() further increases the error as it can't assign data in a refernce. How can I correct this and what am I doing wrong?
You're probably looking for std::mem::replace https://doc.rust-lang.org/std/mem/fn.replace.html
It allows you to replace the data pointed to by a &mut T with a T, and returns the original data as an owned T.
For example:
let mut s = String::from("hello");
let new_str = String::from("new");
let old_str: String = std::mem::replace(&mut s, new_str);
assert_eq!(s, "new");
assert_eq!(old_str, "hello");
P.S why not use a Vec<T> (unless you're using a linked list for learning purposes). It has a simple API, and performance will be significantly better in the vast majority of cases
P.P.S. If you're implementing a linked list for learning purposes, check out https://rust-unofficial.github.io/too-many-lists/
maybe there is a better way but I used a combination of RefCell and std::mem:replace to get around the error, wrapping your fields with RefCell will allow you to get mutable reference that you can then pass to replace to perform the memory change. Here is the code
use std::cell::RefCell;
use std::mem::replace;
#[derive(Debug, Clone)]
struct Node<T: std::marker::Copy> {
value: T,
next: RefCell<Option<Box<Node<T>>>>,
}
impl<T: std::marker::Copy> Node<T> {
fn new(value: T) -> Node<T> {
Node { value, next: RefCell::new(None) }
}
}
#[derive(Debug, Clone)]
struct Stack<T: std::marker::Copy> {
first: RefCell<Option<Box<Node<T>>>>,
last: RefCell<Option<Box<Node<T>>>>,
size: usize,
}
impl<T: std::marker::Copy> Stack<T> {
fn push(&mut self, elem: T) -> usize {
if self.first.borrow().is_none() {
self.first = RefCell::new(Some(Box::new(Node::new(elem))));
self.last = RefCell::new(Some(Box::new(Node::new(elem))));
} else {
let temp =replace(self.first.get_mut(),None);
self.first = RefCell::new(Some(Box::new(Node::new(elem))));
let _=replace(self.first.get_mut(), Some(Box::new(*temp.unwrap())));
}
self.size += 1;
self.size
}
}
I am trying to implement a datastructure to store 'registers' in groups. There is a master list which I am considering the owner of the register data.
I have the following:
use std::collections::hash_map::HashMap;
pub struct Register {
pub name: String,
pub address: u16,
}
// map with references to 'master' list of registers
type RegisterMap<'a> = HashMap<String, &'a Register>;
struct RegisterGroup<'a> {
start_address: u16,
registers: RegisterMap<'a>,
}
struct RegisterGroupIter<'a> {
inner: std::collections::hash_map::Values<'a,String,&'a Register>,
}
impl<'a> Iterator for RegisterGroupIter<'a> {
type Item = &'a Register;
fn next(&mut self) -> Option<&'a Register> {
self.inner.next()
}
}
impl<'a> RegisterGroup<'a> {
// return iterator over references to Register
fn registers(&self) -> RegisterGroupIter {
RegisterGroupIter {
inner: self.registers.values(),
}
}
}
Is this reasonable/idiomatic? If so what is the correct setup for the item type wrt references/lifetimes etc? Otherwise what should I be doing instead?
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:22:9
|
21 | fn next(&mut self) -> Option<&'a Register> {
| -------------------- expected `std::option::Option<&'a Register>` because of return type
22 | self.inner.next()
| ^^^^^^^^^^^^^^^^^ expected struct `Register`, found `&Register`
|
= note: expected enum `std::option::Option<&'a Register>`
found enum `std::option::Option<&&'a Register>`
Since the values iterator of a HashMap yields references to the values type, and the values type is a reference itself in this case, the iterator items are of type &&Register. This means you need to dereference the items before returning them in your iterator. The easiest way to dereference inside an option is to use the copied() method:
impl<'a> Iterator for RegisterGroupIter<'a> {
type Item = &'a Register;
fn next(&mut self) -> Option<&'a Register> {
self.inner.next().copied()
}
}
I'm not sure why you store the name both as the hash map key and inside the Register struct. I'd usually try to normalize the data and only sore the name as the map keys.
You don't really need to implement your own iterator type here. Directly returning the values iterator of the hash map will work just fine:
impl RegisterGroup<'_> {
fn registers(&self) -> impl Iterator<Item = &Register> {
self.registers.values().copied()
}
}
I found this problem when working on a mid-size project. The following snippet is a minimal summary of the problem.
In the following code I try to map a list of enum variants into a Set of different enum variants. I use a closure so I can capture a mutable reference to my_list which is a list of source enum variants. The closure is then kept inside a MyType instance so it can be called later and the result used inside another method.
To keep the closure, I used a FnMut trait inside a Box. I also wrapped that inside an Option so I can set the closure after instance creation.
I based this a bit from the question asked here: structs with boxed vs. unboxed closures
use std::collections::HashSet;
enum Numbers {
One,
Two,
Three,
}
#[derive(Eq, PartialEq, Hash)]
enum Romans {
I,
II,
III,
}
struct MyType<'a> {
func: Option<Box<dyn FnMut() -> HashSet<Romans> + 'a>>,
}
impl<'a> MyType<'a> {
pub fn set_func<F>(&mut self, a_func: F)
where F: FnMut() -> HashSet<Romans> + 'a {
self.func = Some(Box::new(a_func));
}
pub fn run(&mut self) {
let result = (self.func.unwrap())();
if result.contains(&Romans::I) {
println!("Roman one!");
}
}
}
fn main() {
let my_list = vec![Numbers::One, Numbers::Three];
let mut my_type = MyType {
func: None,
};
my_type.set_func(|| -> HashSet<Romans> {
HashSet::from(my_list
.iter()
.map(|item| {
match item {
Numbers::One => Romans::I,
Numbers::Two => Romans::II,
Numbers::Three => Romans::III,
}
})
.collect()
)
});
my_type.run();
}
When I try to compile, I get the following error:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:27:23
|
27 | let result = (self.func.unwrap())();
| ^^^^^^^^^ cannot move out of borrowed content
error: aborting due to previous error
I don't quite understand what is being moved out. Is it a hidden self? The resulting HashSet? or maybe the values inside the set?
What am I doing wrong?
The trouble you're having is that calling unwrap on an Option will consume it--it takes self as an argument. Inside run(), your MyType only has a &mut self reference to itself, so it cannot take ownership of its field.
The solution is to take mutable reference to the stored function instead:
pub fn run(&mut self) {
if let Some(func) = &mut self.func {
let result = func();
if result.contains(&Romans::I) {
println!("Roman one!");
}
}
}
I have structure with a vector of other structures:
pub struct StructB {
value1: u64,
value2: String,
}
pub struct StructA {
array: Vec<StructB>,
}
StructB is constant; during the creation of StructA, an array is filled with the objects that are read from a file and is unlikely to be modified.
I would like to have a function to get element StructB corresponding to an input parameter: get_structB(input: u64) -> &StructB. For the sake of simplicity, let's say that we will just return element with the given index, assuming that someone else is checking boundaries.
I struggle with how to implement that in Rust. I would like to return a kind of "read only" reference or a reference to an object that is immutable but not doing a copy. I cannot figure out the proper way to do that.
impl StructA {
fn get_structB(&self, idx: u64) -> Box<StructB> { // Or should I use here Rc?
// Here I don't want to consume self just return reference wrapped to the idx element
// Should I implement something like as_ref() for the StructA?
self.array[idx] // That of course won't compile
}
}
impl StructA {
fn get_structB(&self, i: usize) -> &StructB {
return &self.array[i];
}
}
This does the trick. However, you may encounter some problem if you write the following:
// `a` is a StructA instance
let bb = a.get_struct_b(0);
println!("{:?}", bb);
drop(a); // move out of `a` occurs here
println!("{:?}", bb); // borrow of `a` is used here
You will have to modify your struct definition and use Rc to write the function. Rc introduces a little performance impact and makes the code more complex, so you may want to use it only when you know that the data will be used after moving StructA.
pub struct StructA {
array: Vec<Rc<StructB>>,
}
impl StructA {
fn get_structB(&self, i: usize) -> Rc<StructB> {
return Rc::clone(self.array[i]);
}
}
I'm trying to do the equivalent of Ruby's Enumerable.collect() in Rust.
I have an Option<Vec<Attachment>> and I want to create a Option<Vec<String>> from it, with String::new() elements in case of None guid.
#[derive(Debug)]
pub struct Attachment {
pub guid: Option<String>,
}
fn main() {
let ov: Option<Vec<Attachment>> =
Some(vec![Attachment { guid: Some("rere34r34r34r34".to_string()) },
Attachment { guid: Some("5345345534rtyr5345".to_string()) }]);
let foo: Option<Vec<String>> = match ov {
Some(x) => {
x.iter()
.map(|&attachment| attachment.guid.unwrap_or(String::new()))
.collect()
}
None => None,
};
}
The error in the compiler is clear:
error[E0277]: the trait bound `std::option::Option<std::vec::Vec<std::string::String>>: std::iter::FromIterator<std::string::String>` is not satisfied
--> src/main.rs:15:18
|
15 | .collect()
| ^^^^^^^ the trait `std::iter::FromIterator<std::string::String>` is not implemented for `std::option::Option<std::vec::Vec<std::string::String>>`
|
= note: a collection of type `std::option::Option<std::vec::Vec<std::string::String>>` cannot be built from an iterator over elements of type `std::string::String`
If I remember what I've read from the documentation so far, I cannot implement traits for struct that I don't own.
How can I do this using iter().map(...).collect() or maybe another way?
You should read and memorize all of the methods on Option (and Result). These are used so pervasively in Rust that knowing what is present will help you immensely.
For example, your match statement is Option::map.
Since you never said you couldn't transfer ownership of the Strings, I'd just do that. This will avoid any extra allocation:
let foo: Option<Vec<_>> =
ov.map(|i| i.into_iter().map(|a| a.guid.unwrap_or_else(String::new)).collect());
Note we don't have to specify the type inside the Vec; it can be inferred.
You can of course introduce functions to make it cleaner:
impl Attachment {
fn into_guid(self) -> String {
self.guid.unwrap_or_else(String::new)
}
}
// ...
let foo: Option<Vec<_>> = ov.map(|i| i.into_iter().map(Attachment::into_guid).collect());
If you don't want to give up ownership of the String, you can do the same concept but with a string slice:
impl Attachment {
fn guid(&self) -> &str {
self.guid.as_ref().map_or("", String::as_str)
}
}
// ...
let foo: Option<Vec<_>> = ov.as_ref().map(|i| i.iter().map(|a| a.guid().to_owned()).collect());
Here, we have to use Option::as_ref to avoid moving the guid out of the Attachment, then convert to a &str with String::as_str, providing a default value. We likewise don't take ownership of the Option of ov, and thus need to iterate over references, and ultimately allocate new Strings with ToOwned.
Here is a solution that works:
#[derive(Debug)]
pub struct Attachment {
pub guid: Option<String>,
}
fn main() {
let ov: Option<Vec<Attachment>> =
Some(vec![Attachment { guid: Some("rere34r34r34r34".to_string()) },
Attachment { guid: Some("5345345534rtyr5345".to_string()) }]);
let foo: Option<Vec<_>> = ov.map(|x|
x.iter().map(|a| a.guid.as_ref().unwrap_or(&String::new()).clone()).collect());
println!("{:?}", foo);
}
One of the issues with the above code is stopping the guid being moved out of the Attachment and into the vector. My example calls clone to move cloned instances into the vector.
This works, but I think it looks nicer wrapped in a trait impl for Option<T>. Perhaps this is a better ... option ...:
trait CloneOr<T, U>
where U: Into<T>,
T: Clone
{
fn clone_or(&self, other: U) -> T;
}
impl<T, U> CloneOr<T, U> for Option<T>
where U: Into<T>,
T: Clone
{
fn clone_or(&self, other: U) -> T {
self.as_ref().unwrap_or(&other.into()).clone()
}
}
#[derive(Debug)]
pub struct Attachment {
pub guid: Option<String>,
}
fn main() {
let ov: Option<Vec<Attachment>> =
Some(vec![Attachment { guid: Some("rere34r34r34r34".to_string()) },
Attachment { guid: Some("5345345534rtyr5345".to_string()) },
Attachment { guid: None }]);
let foo: Option<Vec<_>> =
ov.map(|x| x.iter().map(|a| a.guid.clone_or("")).collect());
println!("{:?}", foo);
}
Essentially the unwrapping and cloning is hidden behind a trait implementation that attaches to Option<T>.
Here it is running on the playground.