Implement Iterator in Rust - rust

I'm making an iterator in rust. In the next() method I want to extract next_element as current_element which will be returned, and create new Term instance and set it as next_element:
pub struct Term {
pub coefficient: f64,
pub index: i32,
pub exponent: f64,
}
pub struct SeriesIterator {
next_element: Term,
}
impl Iterator for SeriesIterator {
type Item = Term;
fn next(&mut self) -> Option<Self::Item> {
let current_element = self.next_element;
self.next_element = Term {
coefficient: 1.0,
index: current_element.index + 1,
exponent: f64::from(current_element.index + 1),
};
Some(current_element)
}
}
How to move ownership of next_element into current_element which will finally be moved outside with the return of next()?
cannot move out of `self.next_element` which is behind a mutable reference
|
| let current_element = self.next_element;
| ^^^^^^^^^^^^^^^^

Using std::mem::replace, try this:
fn next(&mut self) -> Option<Self::Item> {
let index = self.next_element.index + 1;
Some(std::mem::replace(
&mut self.next_element,
Term {
coefficient: 1.0,
index: index,
exponent: f64::from(index),
},
))
}
Using #[derive(Clone, Copy)]:
fn next(&mut self) -> Option<Self::Item> {
let current_element = self.next_element; // copy
self.next_element.coefficient = 1.0;
self.next_element.index += 1;
self.next_element.exponent = f64::from(self.next_element.index);
Some(current_element)
}
Try this working example:
#[derive(Clone, Copy)]
pub struct Term {
pub coefficient: f64,
pub index: i32,
pub exponent: f64,
}
pub struct SeriesIterator {
next_element: Term,
}
impl Iterator for SeriesIterator {
type Item = Term;
fn next(&mut self) -> Option<Self::Item> {
let current_element = self.next_element; // copy
self.next_element.coefficient = 1.0;
self.next_element.index += 1;
self.next_element.exponent = f64::from(self.next_element.index);
Some(current_element)
}
}
fn main() {
let mut t = SeriesIterator {
next_element: Term {
coefficient: 1.0,
index: 0,
exponent: 1.0,
},
};
let next = t.next().unwrap();
println!("{}", next.index); // 0
println!("{}", t.next_element.index); // 1
let next = t.next().unwrap();
println!("{}", next.index); // 1
println!("{}", t.next_element.index); // 2
}
Output:
0
1
1
2

Related

Rust fast stack implementation without unnecessary memset?

I need a fast stack in Rust. Millions of these need to be created/destroyed per second and each of them need only a fixed depth. I'm trying to squeeze as much speed as I can. I came up with the following (basically textbook stack implementation):
const L: usize = 1024;
pub struct Stack {
xs: [(u64, u64, u64, u64); L],
sz: usize
}
impl Stack {
pub fn new() -> Self {
Self { xs: [(0, 0 ,0, 0); L], sz: 0 }
}
pub fn push(&mut self, item: (u64, u64, u64, u64)) -> bool {
if (self.sz + 1) <= L {
self.xs[self.sz] = item;
self.sz += 1;
true
} else {
false
}
}
pub fn pop(&mut self) -> Option<(u64, u64, u64, u64)> {
(self.sz > 0).then(|| {
self.sz -= 1;
self.xs[self.sz]
})
}
}
The problem is memset, which is unnecessary. So I tried to get rid of it:
pub fn new2() -> Self {
let xs = std::array::from_fn(|_| unsafe { MaybeUninit::uninit().assume_init() });
Self { xs, sz: 0 }
}
This gets rid of the memset, but now I have a warning:
|
18 | let xs = std::array::from_fn(|_| unsafe { MaybeUninit::uninit().assume_init() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: integers must not be uninitialized
= note: `#[warn(invalid_value)]` on by default
If uninitialized integers cause undefined behavior, is it not possible to create this kind of stack, where the logic of the stack guarantees proper behavior and I avoid unnecessary memory operations?
You need to use MaybeUninit all the way through. Change your array to an array of MaybeUninits:
use std::mem::MaybeUninit;
const L: usize = 1024;
pub struct Stack {
xs: [MaybeUninit<(u64, u64, u64, u64)>; L],
sz: usize
}
// From standard library
// https://doc.rust-lang.org/stable/src/core/mem/maybe_uninit.rs.html#350-353
#[must_use]
#[inline(always)]
pub const fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] {
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
}
impl Stack {
pub fn new() -> Self {
Self { xs: uninit_array(), sz: 0 }
}
pub fn push(&mut self, item: (u64, u64, u64, u64)) -> bool {
if (self.sz + 1) <= L {
self.xs[self.sz].write(item);
self.sz += 1;
true
} else {
false
}
}
pub fn pop(&mut self) -> Option<(u64, u64, u64, u64)> {
(self.sz > 0).then(|| {
self.sz -= 1;
// Safety: The value has been initialized
unsafe {
self.xs[self.sz].assume_init()
}
})
}
}

How to pass on closures through multiple sctructs and functions

I have a hierarchy of structs where I need to call a method in the topmost struct from an Iterator::next implementation at the lowest level.
Current implementation is as follows:
Functional abstract:
pub struct TopLevel {
answer: usize,
}
pub struct MidLevelIter<'mli> {
count: usize,
top_level: &'mli TopLevel,
}
pub struct MidLevel<'ml> {
top_level: &'ml TopLevel,
}
pub struct LowestLevelIter<'lli> {
count: usize,
top_level: &'lli TopLevel,
}
impl TopLevel {
pub fn new() -> Self {
Self { answer: 42 }
}
pub fn iter(&self) -> MidLevelIter<'_> {
MidLevelIter {
count: 1,
top_level: self,
}
}
fn calculate(&self, _: usize) -> &usize {
&self.answer
}
}
impl<'mli> Iterator for MidLevelIter<'mli> {
type Item = MidLevel<'mli>;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 2 {
self.count = 2;
Some(MidLevel {
top_level: self.top_level,
})
} else {
None
}
}
}
impl<'lli> Iterator for LowestLevelIter<'lli> {
type Item = &'lli usize;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 2 {
self.count = 2;
Some(self.top_level.calculate(self.count))
} else {
None
}
}
}
impl<'ml> MidLevel<'ml> {
pub fn iter(&self) -> LowestLevelIter<'ml> {
LowestLevelIter {
count: 1,
top_level: self.top_level,
}
}
}
fn main() {
let collector = TopLevel::new();
for pc in collector.iter() {
for sc in pc.iter() {
println!("SC={}", sc);
}
}
}
This works fine, but it kind of bothers me that I have to pass a reference to TopLevel through all these structs.
So, my idea was to pass only the required method as a closure. That way, the lower levels need not to know anything about the TopLevel construct.
the following approach, however, fails because of "cannot move out of self.mapper which is behind a mutable reference".
pub struct TopLevel {
answer: usize,
}
pub struct MidLevelIter<'mli> {
count: usize,
mapper: Box<dyn Fn(usize) -> &'mli usize + 'mli>,
}
pub struct MidLevel<'ml> {
mapper: Box<dyn Fn(usize) -> &'ml usize + 'ml>,
}
pub struct LowestLevelIter<'lli> {
count: usize,
mapper: Box<dyn Fn(usize) -> &'lli usize + 'lli>,
}
impl TopLevel {
pub fn new() -> Self {
Self { answer: 42 }
}
pub fn iter(&self) -> MidLevelIter<'_> {
MidLevelIter {
count: 1,
mapper: Box::new(self.mapper()),
}
}
fn calculate(&self, _: usize) -> &usize {
&self.answer
}
fn mapper<'m>(&'m self) -> impl Fn(usize) -> &'m usize {
move |secondary_index| self.calculate(secondary_index)
}
}
impl<'mli> Iterator for MidLevelIter<'mli> {
type Item = MidLevel<'mli>;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 2 {
self.count = 2;
Some(MidLevel {
mapper: self.mapper,
})
} else {
None
}
}
}
impl<'lli> Iterator for LowestLevelIter<'lli> {
type Item = &'lli usize;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 2 {
self.count = 2;
Some((self.mapper)(self.count))
} else {
None
}
}
}
impl<'ml> MidLevel<'ml> {
pub fn iter(&self) -> LowestLevelIter<'ml> {
LowestLevelIter {
count: 1,
mapper: self.mapper,
}
}
}
fn main() {
let collector = TopLevel::new();
for pc in collector.iter() {
for sc in pc.iter() {
println!("SC={}", sc);
}
}
}
Although I can understand what the compiler tells me there, I don't see how to circumvent it.
Traits are the answer to my problem.
Basically, on the lowest level I just wanted to perform a transformation of some sort on the items of the iteration. Although closures looked suitable for that, Rust provides another feature to accomplish this: Traits.
On the lowest level, I want to convert a numerical index to a key reference. So make a trait for it:
trait IndexToKey {
fn calculate(&self, _: usize) -> &usize;
}
This trait can now be passed on, e.g.:
pub struct MidLevelIter<'mli> {
count: usize,
mapper: &'mli dyn IndexToKey,
}
Originally, my TopLevel struct provided the logic, so let's implement the trait:
impl IndexToKey for TopLevel {
fn calculate(&self, _ix: usize) -> &usize {
&self.answer
}
}
Now we can pass a reference to trait implementation down to the lowest level, which now simply performs the conversion:
impl<'lli> Iterator for LowestLevelIter<'lli> {
type Item = &'lli usize;
fn next(&mut self) -> Option<Self::Item> {
if self.count < 2 {
self.count = 2;
Some(self.mapper.calculate(self.count))
} else {
None
}
}
}
No lifetime issues, no disclosure or dependency on implementation details of the TopLevel structs at the other levels.
Implementation on the Rust playground

how to solve cyclic-dependency & Iterator lifetime problem?

Rustaceans. when I start to write a BloomFilter example in rust. I found I have serveral problems have to solve. I struggle to solve them but no progress in a day. I need help, any suggestion will help me a lot, Thanks.
Problems
How to solve lifetime when pass a Iterator into another function?
// let bits = self.hash(value); // how to solve such lifetime error without use 'static storage?
// Below is a workaround code but need to computed in advanced.
let bits = Box::new(self.hash(value).collect::<Vec<u64>>().into_iter());
self.0.set(bits);
How to solve cyclic-dependency between struts without modify lower layer code, e.g: bloom_filter ?
// cyclic-dependency:
// RedisCache -> BloomFilter -> Storage
// | ^
// ------------<impl>------------
//
// v--- cache ownership has moved here
let filter = BloomFilter::by(Box::new(cache));
cache.1.replace(filter);
Since rust does not have null value, How can I solve the cyclic-dependency initialization without any stubs?
let mut cache = RedisCache(
Client::open("redis://localhost").unwrap(),
// I found can use Weak::new() to solve it,but need to downgrade a Rc reference.
// v-- need a BloomFilter stub to create RedisCache
RefCell::new(BloomFilter::new()),
);
Code
#![allow(unused)]
mod bloom_filter {
use std::{hash::Hash, marker::PhantomData};
pub type BitsIter = Box<dyn Iterator<Item = u64>>;
pub trait Storage {
fn set(&mut self, bits: BitsIter);
fn contains_all(&self, bits: BitsIter) -> bool;
}
pub struct BloomFilter<T: Hash>(Box<dyn Storage>, PhantomData<T>);
impl<T: Hash> BloomFilter<T> {
pub fn new() -> BloomFilter<T> {
return Self::by(Box::new(ArrayStorage([0; 5000])));
struct ArrayStorage<const N: usize>([u8; N]);
impl<const N: usize> Storage for ArrayStorage<N> {
fn set(&mut self, bits: BitsIter) {
let size = self.0.len() as u64;
bits.map(|bit| (bit % size) as usize)
.for_each(|index| self.0[index] = 1);
}
fn contains_all(&self, bits: BitsIter) -> bool {
let size = self.0.len() as u64;
bits.map(|bit| (bit % size) as usize)
.all(|index| self.0[index] == 1)
}
}
}
pub fn by(storage: Box<dyn Storage>) -> BloomFilter<T> {
BloomFilter(storage, PhantomData)
}
pub fn add(&mut self, value: T) {
// let bits = self.hash(value); // how to solve such lifetime error?
let bits = Box::new(self.hash(value).collect::<Vec<u64>>().into_iter());
self.0.set(bits);
}
pub fn contains(&self, value: T) -> bool {
// lifetime problem same as Self::add(T)
let bits = Box::new(self.hash(value).collect::<Vec<u64>>().into_iter());
self.0.contains_all(bits)
}
fn hash<'a, H: Hash + 'a>(&self, _value: H) -> Box<dyn Iterator<Item = u64> + 'a> {
todo!()
}
}
}
mod spi {
use super::bloom_filter::*;
use redis::{Client, Commands, RedisResult};
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
pub struct RedisCache<'a>(Client, RefCell<BloomFilter<&'a str>>);
impl<'a> RedisCache<'a> {
pub fn new() -> RedisCache<'a> {
let mut cache = RedisCache(
Client::open("redis://localhost").unwrap(),
// v-- need a BloomFilter stub to create RedisCache
RefCell::new(BloomFilter::new()),
);
// v--- cache ownership has moved here
let filter = BloomFilter::by(Box::new(cache));
cache.1.replace(filter);
return cache;
}
pub fn get(&mut self, key: &str, load_value: fn() -> Option<String>) -> Option<String> {
let filter = self.1.borrow();
if filter.contains(key) {
if let Ok(value) = self.0.get::<&str, String>(key) {
return Some(value);
}
if let Some(actual_value) = load_value() {
let _: () = self.0.set(key, &actual_value).unwrap();
return Some(actual_value);
}
}
return None;
}
}
impl<'a> Storage for RedisCache<'a> {
fn set(&mut self, bits: BitsIter) {
todo!()
}
fn contains_all(&self, bits: BitsIter) -> bool {
todo!()
}
}
}
Updated
First, thanks #Colonel Thirty Two give me a lot of information that I haven't mastered and help me fixed the problem of the iterator lifetime.
The cyclic-dependency I have solved by break the responsibility of the Storage into another struct RedisStorage without modify the bloom_filter module, but make the example bloated. Below is their relationships:
RedisCache -> BloomFilter -> Storage <---------------
| |
|-------> redis::Client <- RedisStorage ---<impl>---
I realized the ownership & lifetime system is not only used by borrow checker, but also Rustaceans need a bigger front design to obey the rules than in a GC language, e.g: java. Am I right?
Final Code
mod bloom_filter {
use std::{
hash::{Hash, Hasher},
marker::PhantomData,
};
pub type BitsIter<'a> = Box<dyn Iterator<Item = u64> + 'a>;
pub trait Storage {
fn set(&mut self, bits: BitsIter);
fn contains_all(&self, bits: BitsIter) -> bool;
}
pub struct BloomFilter<T: Hash>(Box<dyn Storage>, PhantomData<T>);
impl<T: Hash> BloomFilter<T> {
#[allow(unused)]
pub fn new() -> BloomFilter<T> {
return Self::by(Box::new(ArrayStorage([0; 5000])));
struct ArrayStorage<const N: usize>([u8; N]);
impl<const N: usize> Storage for ArrayStorage<N> {
fn set(&mut self, bits: BitsIter) {
let size = self.0.len() as u64;
bits.map(|bit| (bit % size) as usize)
.for_each(|index| self.0[index] = 1);
}
fn contains_all(&self, bits: BitsIter) -> bool {
let size = self.0.len() as u64;
bits.map(|bit| (bit % size) as usize)
.all(|index| self.0[index] == 1)
}
}
}
pub fn by(storage: Box<dyn Storage>) -> BloomFilter<T> {
BloomFilter(storage, PhantomData)
}
pub fn add(&mut self, value: T) {
self.0.set(self.hash(value));
}
pub fn contains(&self, value: T) -> bool {
self.0.contains_all(self.hash(value))
}
fn hash<'a, H: Hash + 'a>(&self, value: H) -> BitsIter<'a> {
Box::new(
[3, 11, 31, 71, 131]
.into_iter()
.map(|salt| SimpleHasher(0, salt))
.map(move |mut hasher| hasher.hash(&value)),
)
}
}
struct SimpleHasher(u64, u64);
impl SimpleHasher {
fn hash<H: Hash>(&mut self, value: &H) -> u64 {
value.hash(self);
self.finish()
}
}
impl Hasher for SimpleHasher {
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, bytes: &[u8]) {
self.0 += bytes.iter().fold(0u64, |acc, k| acc * self.1 + *k as u64)
}
}
}
mod spi {
use super::bloom_filter::*;
use redis::{Client, Commands};
use std::{cell::RefCell, rc::Rc};
pub struct RedisCache<'a>(Rc<RefCell<Client>>, BloomFilter<&'a str>);
impl<'a> RedisCache<'a> {
pub fn new(client: Rc<RefCell<Client>>, filter: BloomFilter<&'a str>) -> RedisCache<'a> {
RedisCache(client, filter)
}
pub fn get<'f>(
&mut self,
key: &str,
load_value: fn() -> Option<&'f str>,
) -> Option<String> {
if self.1.contains(key) {
let mut redis = self.0.as_ref().borrow_mut();
if let Ok(value) = redis.get::<&str, String>(key) {
return Some(value);
}
if let Some(actual_value) = load_value() {
let _: () = redis.set(key, &actual_value).unwrap();
return Some(actual_value.into());
}
}
return None;
}
}
struct RedisStorage(Rc<RefCell<Client>>);
const BLOOM_FILTER_KEY: &str = "bloom_filter";
impl Storage for RedisStorage {
fn set(&mut self, bits: BitsIter) {
bits.for_each(|slot| {
let _: bool = self
.0
.as_ref()
.borrow_mut()
.setbit(BLOOM_FILTER_KEY, slot as usize, true)
.unwrap();
})
}
fn contains_all(&self, mut bits: BitsIter) -> bool {
bits.all(|slot| {
self.0
.as_ref()
.borrow_mut()
.getbit(BLOOM_FILTER_KEY, slot as usize)
.unwrap()
})
}
}
#[test]
fn prevent_cache_penetration_by_bloom_filter() {
let client = Rc::new(RefCell::new(Client::open("redis://localhost").unwrap()));
redis::cmd("FLUSHDB").execute(&mut *client.as_ref().borrow_mut());
let mut filter: BloomFilter<&str> = BloomFilter::by(Box::new(RedisStorage(client.clone())));
assert!(!filter.contains("Rust"));
filter.add("Rust");
assert!(filter.contains("Rust"));
let mut cache = RedisCache::new(client, filter);
assert_eq!(
cache.get("Rust", || Some("System Language")),
Some("System Language".to_string())
);
assert_eq!(
cache.get("Rust", || panic!("must never be called after cached")),
Some("System Language".to_string())
);
assert_eq!(
cache.get("Go", || panic!("reject to loading `Go` from external storage")),
None
);
}
}
pub type BitsIter = Box<dyn Iterator<Item = u64>>;
In this case, the object in the box must be valid for the 'static lifetime. This isn't the case for the iterator returned by hash - its limited to the lifetime of self.
Try replacing with:
pub type BitsIter<'a> = Box<dyn Iterator<Item = u64> + 'a>;
Or using generics instead of boxed trait objects.
So your RedisClient needs a BloomFilter, but the BloomFilter also needs the RedisClient?
Your BloomFilter should not use the RedisCache that itself uses the BloomFilter - that's a recipe for infinitely recursing calls (how do you know what calls to RedisCache::add should update the bloom filter and which calls are from the bloom filter?).
If you really have to, you need some form of shared ownership, like Rc or Arc. Your BloomFilter will also need to use a weak reference, or else the two objects will refer to each other and will never free.

How to convert a linked list of Option<Box<ListNode>> to a Vec<i32>?

I want to convert the following Option<Box<ListNode>> type to Vec<i32> type:
fn main() {
Some(ListNode {
val: 3,
next: Some(ListNode {
val: 4,
next: Some(ListNode { val: 2, next: None }),
}),
})
}
I want to implement the list_to_vec function:
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>,
}
impl ListNode {
pub fn new(val: i32) -> Self {
ListNode { next: None, val }
}
pub fn vec_to_list(mut value: Vec<i32>) -> Option<Box<ListNode>> {
match value.pop() {
Some(x) => Some(Box::new(ListNode {
val: x,
next: ListNode::vec_to_list(value),
})),
None => None,
}
}
pub fn list_to_vec(mut value: &Option<ListNode>) -> Vec<i32> {
//????????????????????????????
}
}
Desired output
[3, 4, 2]
I have tried:
pub fn list_to_vec(mut value: &Option<ListNode>) -> Vec<i32> {
let mut v = vec![];
match value {
Some(x) => {
&v.push(x.val);
Self::list_to_vec(x.next)
}
None => v,
}
}
let h = ListNode::vec_to_list(vec![2, 4, 3]);
println!("{:#?}", ListNode::list_to_vec(&h));
it has an error:
error[E0308]: mismatched types
--> src\main.rs:27:56
|
27 | Some(x) => {&v.push(x.val);Self::list_to_vec(x.next)},
| ^^^^^^ expected reference, found enum `std::option::Option`
|
= note: expected type `&std::option::Option<ListNode>`
found type `std::option::Option<std::boxed::Box<ListNode>>`
error[E0308]: mismatched types
--> src\main.rs:74:40
|
74 | println!("{:#?}",ListNode::list_to_vec(&h));
| ^^ expected struct `ListNode`, found struct `std::boxed::Box`
|
= note: expected type `&std::option::Option<ListNode>`
found type `&std::option::Option<std::boxed::Box<ListNode>>`
You will blow your stack if you don't do tail recursive function, your vec_to_list() can't handle a medium vector size. For your list_to_vec() you could just implement Iterator and collect it, fast and dirty example:
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>,
}
pub struct ListIter<'a> {
iter: &'a Option<Box<ListNode>>,
}
impl<'a> Iterator for ListIter<'a> {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if let Some(cur) = self.iter {
self.iter = &cur.next;
Some(cur.val)
} else {
None
}
}
}
impl ListNode {
pub fn new(val: i32) -> Self {
ListNode { next: None, val }
}
pub fn vec_to_list<'a>(
value: impl IntoIterator<IntoIter = impl DoubleEndedIterator<Item = &'a i32>, Item = &'a i32>,
) -> Option<Box<ListNode>> {
Self::vec_to_list_aux(value.into_iter().rev().copied(), None)
}
fn vec_to_list_aux(
value: impl Iterator<Item = i32>,
accu: Option<Box<ListNode>>,
) -> Option<Box<ListNode>> {
let mut value = value;
match value.next() {
Some(x) => {
Self::vec_to_list_aux(value, Some(Box::new(ListNode { val: x, next: accu })))
}
None => accu,
}
}
pub fn list_to_vec(list: &Option<Box<ListNode>>) -> Vec<i32> {
Self::iter(list).collect()
}
fn iter(list: &Option<Box<ListNode>>) -> ListIter {
ListIter { iter: &list }
}
}
fn main() {
let list = ListNode::vec_to_list(&[3, 4, 2]);
println!("{:#?}", list);
println!("{:?}", ListNode::list_to_vec(&list));
}
I resolved it.
pub fn list_to_vec(mut value: Option<Box<ListNode>>, mut v_cup: Vec<i32>) -> Vec<i32> {
match value {
Some(x) => {
v_cup.push(x.val);
Self::list_to_vec(x.next, v_cup)
}
None => v_cup,
}
}
let h = ListNode::vec_to_list(vec![2, 4, 3]);
let v_cup = vec![];
println!("{:?}", ListNode::list_to_vec(h, v_cup));
A recursive solution isn't needed here, and is likely to not be as efficient as the iterative solution.
Taking ownership:
pub fn list_to_vec(mut value: Option<Box<ListNode>>) -> Vec<i32> {
let mut v = Vec::new();
while let Some(n) = value {
v.push(n.val);
value = n.next;
}
v
}
By reference:
pub fn list_to_vec(mut value: &Option<Box<ListNode>>) -> Vec<i32> {
let mut v = Vec::new();
while let Some(n) = value {
v.push(n.val);
value = &n.next;
}
v
}

Is there a way to perform an index access to an instance of a struct?

Is there a way to perform an index access to an instance of a struct like this:
struct MyStruct {
// ...
}
impl MyStruct {
// ...
}
fn main() {
let s = MyStruct::new();
s["something"] = 533; // This is what I need
}
You can use the Index and IndexMut traits.
use std::ops::{Index, IndexMut};
struct Foo {
x: i32,
y: i32,
}
impl Index<&'_ str> for Foo {
type Output = i32;
fn index(&self, s: &str) -> &i32 {
match s {
"x" => &self.x,
"y" => &self.y,
_ => panic!("unknown field: {}", s),
}
}
}
impl IndexMut<&'_ str> for Foo {
fn index_mut(&mut self, s: &str) -> &mut i32 {
match s {
"x" => &mut self.x,
"y" => &mut self.y,
_ => panic!("unknown field: {}", s),
}
}
}
fn main() {
let mut foo = Foo { x: 0, y: 0 };
foo["y"] += 2;
println!("x: {}", foo["x"]);
println!("y: {}", foo["y"]);
}
It prints:
x: 0
y: 2
You want to use the Index trait (and its pair IndexMut):
use std::ops::Index;
#[derive(Copy, Clone)]
struct Foo;
struct Bar;
impl Index<Bar> for Foo {
type Output = Foo;
fn index<'a>(&'a self, _index: Bar) -> &'a Foo {
println!("Indexing!");
self
}
}
fn main() {
Foo[Bar];
}

Resources