How to pass on closures through multiple sctructs and functions - rust

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

Related

How to use the typestate pattern in other struct

I want to use the typestate pattern to define several states that allow some exclusive operations on each of them.
I'm using traits instead of an enum to allow further customizations.
So, I'm able to use this pattern until I try to include it inside a struct (the Session part) that is mutated when files are added, changed or removed.
trait IssueState {}
struct Open;
impl IssueState for Open {}
struct WIP {
elapsed_time: u32,
}
impl IssueState for WIP {}
struct Closed {
elapsed_time: u32,
}
impl IssueState for Closed {}
struct Issue<T: IssueState + ?Sized> {
state: Box<T>,
comments: Vec<String>,
}
impl<T: IssueState> Issue<T> {
pub fn comment<S: Into<String>>(&mut self, comment: S) -> &mut Self {
self.comments.push(comment.into());
self
}
}
impl Issue<Open> {
pub fn new() -> Self {
Self {
state: Box::new(Open),
comments: vec![],
}
}
pub fn start(self) -> Issue<WIP> {
Issue {
state: Box::new(WIP { elapsed_time: 0 }),
comments: self.comments,
}
}
}
impl Issue<WIP> {
pub fn work(&mut self, time: u32) -> &mut Self {
self.state.elapsed_time += time;
self
}
pub fn done(self) -> Issue<Closed> {
let elapsed_time = self.state.elapsed_time;
Issue {
state: Box::new(Closed { elapsed_time }),
comments: self.comments,
}
}
}
impl Issue<Closed> {
pub fn elapsed(&self) -> u32 {
self.state.elapsed_time
}
}
struct Session<T: IssueState> {
user: String,
current_issue: Issue<T>,
}
impl<T: IssueState> Session<T> {
pub fn new<S: Into<String>>(user: S, issue: Issue<T>) -> Self {
Self {
user: user.into(),
current_issue: issue,
}
}
pub fn comment<S: Into<String>>(&mut self, comment: S) {
self.current_issue.comment(comment);
}
}
impl Session<WIP> {
pub fn work(&mut self, time: u32) {
self.current_issue.work(time);
}
}
trait Watcher {
fn watch_file_create(&mut self);
fn watch_file_change(&mut self);
fn watch_file_delete(&mut self);
}
impl<T: IssueState> Watcher for Session<T> {
fn watch_file_create(&mut self) {
self.current_issue = Issue::<Open>::new();
}
fn watch_file_change(&mut self) {}
fn watch_file_delete(&mut self) {}
}
fn main() {
let open = Issue::<Open>::new();
let mut wip = open.start();
wip.work(10).work(30).work(60);
let closed = wip.done();
println!("Elapsed {}", closed.elapsed());
let mut session = Session::new("Reviewer", closed);
session.comment("It is OK");
session.watch_file_create();
}
Rust Playground (original)
Rust Playground (edited)
What can I do to fix the problems?
Is the typestate pattern limited to only some situations that do not depend a lot on external events? I mean, I'm trying to use it for processing events, but is it a dead end?, why?
Your Session has a Issue<dyn IssueState> member, but you want to implement its work method by calling Issue<WIP>'s work method. The compiler complains, because an Issue<dyn IssueState> is not (necessarily) a Issue<WIP> and so does not implement that method.

Value referencing data owned by the current function

Here's my code:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
impl Default for AnotherThing {
fn default() -> Self {
Self {
val: 2,
}
}
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
another: &AnotherThing::default(),
}
}
}
fn main() {
let _ = Something::new(1);
}
It doesn't compile because:
Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:24:9
|
24 | / Self {
25 | | val,
26 | | another: &AnotherThing::default(),
| | ----------------------- temporary value created here
27 | | }
| |_________^ returns a value referencing data owned by the current function
I understand the problem but I don't know how to fix it. If it's not possible to use the Default trait for this case, how can I deal with the function ownership. Below a simpler example:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
let at = AnotherThing { val : 2 };
Self {
val,
another: &at,
}
}
}
fn main() {
let _ = Something::new(1);
}
If I had another: &AnotherThing { val : 2 } instead of another: &at it would work. If I want the another attribute to be a reference and get the value from a function, how can I do it?
You can do like this
#[derive(Default)]
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
impl<'a> Default for &'a AnotherThing {
fn default() -> &'a AnotherThing {
&AnotherThing {
val: 3,
}
}
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
..Default::default()
}
}
}
Another option is to create a const item, of which you can create a reference with 'static lifetime, thus binding to any 'a:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
const ANOTHER_THING_DEFAULT: AnotherThing = AnotherThing { val: 3 };
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
another: &ANOTHER_THING_DEFAULT,
}
}
}

macro_rules!() error: Fix for "the usage of `my_macro!` is likely invalid in impl item context"?

Playground link
I have several different structs grouped together in an enum:
pub enum Ty {
A(AStruct),
B(BStruct)
}
pub struct AStruct {
base: BaseStruct
}
impl AStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
pub struct BStruct {
base: BaseStruct
}
impl BStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
All of these types will share a base struct that is common to them all. This base struct will have a lot of methods that I don't want to duplicate for each supertype.
pub struct BaseStruct {
x: i32
}
impl BaseStruct {
pub fn new(x: i32) -> Self {
Self {
x
}
}
pub fn get_x(&self) -> i32 {
self.x
}
}
#[macro_export]
macro_rules! base_struct_passthrough_impls {
() => {
pub fn get_x(&self) -> i32 {
self.base.get_x()
};
}
}
However, trying to use this code results in the following error:
error: macro expansion ignores token `;` and any following
--> src/main.rs:37:10
|
37 | };
| ^
...
46 | base_struct_passthrough_impls!();
| --------------------------------- caused by the macro expansion here
|
= note: the usage of `base_struct_passthrough_impls!` is likely invalid in impl item context
It seems like macro_rules!() is not usable in the impl item context. Is this correct, and if so is there anyway around this restriction? Would a proc macro work here, or would doing something like this work better?
The issue isn't the macro usage, but the definition. You included a trailing semicolon after the function definition created by the macro, which is what causes the error. If you remove it, everything works fine - here's the code:
fn main() {
let types = vec![Ty::A(AStruct::new(32)), Ty::B(BStruct::new(64))];
types.iter().for_each(|item| {
dbg!(match item {
Ty::A(a_struct) => a_struct.get_x(),
Ty::B(b_struct) => b_struct.get_x(),
});
})
}
pub enum Ty {
A(AStruct),
B(BStruct)
}
pub struct BaseStruct {
x: i32
}
impl BaseStruct {
pub fn new(x: i32) -> Self {
Self {
x
}
}
pub fn get_x(&self) -> i32 {
self.x
}
}
#[macro_export]
macro_rules! base_struct_passthrough_impls {
() => {
pub fn get_x(&self) -> i32 {
self.base.get_x()
} // there was an illegal semicolon here
}
}
pub struct AStruct {
base: BaseStruct
}
impl AStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}
pub struct BStruct {
base: BaseStruct
}
impl BStruct {
base_struct_passthrough_impls!();
pub fn new(x: i32) -> Self {
Self {
base: BaseStruct::new(x)
}
}
}

How do I properly insert into a Rust AVL Tree?

I'm very new to rust and I'm trying to creating an AVL Tree. I used Rc because I want every node to be owned by nodes above it and RefCell to have it mutable internally.
I've started to build the "insert" method, but it isn't inserting a new node in the correct place, rather its replace the "root" node with the new node and I'm having trouble understanding why. I believe that this may be an ownership issue but I'm not sure.
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;
#[derive(Debug)]
pub struct BaseNode {
pub key: u32,
pub left: AvlTree,
pub right: AvlTree,
}
pub type AvlNode = Rc<RefCell<BaseNode>>;
pub type AvlTree = Option<AvlNode>;
impl BaseNode {
fn new(key: u32) -> Self {
Self {
key: key,
left: None,
right: None,
}
}
}
trait AvlNodeTrait {
fn new_node(key: u32) -> Self;
}
impl AvlNodeTrait for AvlNode {
fn new_node(key: u32) -> Self {
Rc::new(RefCell::new(BaseNode::new(key)))
}
}
pub trait AvlTreeTrait {
fn new() -> Self;
fn left(&self) -> Self;
fn right(&self) -> Self;
fn insert(&mut self, key: u32);
fn dupe(&self) -> Self;
fn set(&mut self, node: AvlNode);
}
impl AvlTreeTrait for AvlTree {
fn new() -> Self {
None
}
fn left(&self) -> Self {
if let Some(node) = self {
return node.borrow().right.dupe();
}
panic!("Trying to get Left of None!")
}
fn right(&self) -> Self {
if let Some(node) = self {
return node.borrow().right.dupe();
}
panic!("Trying to get right of None!")
}
fn dupe(&self) -> Self {
match self {
Some(node) => Some(Rc::clone(&node)),
None => None,
}
}
fn set(&mut self, node: AvlNode) {
*self = Some(Rc::clone(&node));
}
fn insert(&mut self, key: u32) {
let node = AvlNode::new_node(key);
let mut curr_tree = self;
let mut curr_key = 0;
while !curr_tree.is_none() {
if let Some(node) = &curr_tree {
curr_key = node.borrow().key;
if key > curr_key {
*curr_tree = curr_tree.left()
} else if key < curr_key {
*curr_tree = curr_tree.right()
} else {
return;
}
}
}
*curr_tree = Some(Rc::clone(&node));
}
}
fn main() {
let mut tree = AvlTree::new();
println!("{:?}", tree); // None
tree.insert(5);
println!("{:?}", tree); // Some(RefCell { value: BaseNode { key: 5, left: None, right: None } })
tree.insert(56);
println!("{:?}", tree); // Some(RefCell { value: BaseNode { key: 2, left: None, right: None } })
}
I would say the use of RefCell is quite unnecessary and potentially unsafe in this context. RefCell hands over the ownership/borrow checking to the runtime instead of doing them during compile time. This can lead to your program to panic in case it violates any of the borrowing rules.
I would prefer a "recursive" type looking something like this:
struct AVLTree<T> {
val: T,
left: Option<Box<AVLTree<T>>>,
right: Option<Box<AVLTree<T>>>
}
This will of course introduce some overhead due to memory allocation.

How can I construct a PlasmaContainsRequest if I don't know how to get a WIPOffset object?

How can I construct a PlasmaContainsRequest object, since I don't know how to get a WIPOffset object to construct a PlasmaContainsRequestArgs object?
I used flatc 1.10.0 to generate this Rust code:
impl<'a> PlasmaContainsRequest<'a> {
#[inline]
pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
PlasmaContainsRequest { _tab: table }
}
#[allow(unused_mut)]
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
args: &'args PlasmaContainsRequestArgs<'args>,
) -> flatbuffers::WIPOffset<PlasmaContainsRequest<'bldr>> {
let mut builder = PlasmaContainsRequestBuilder::new(_fbb);
if let Some(x) = args.object_id {
builder.add_object_id(x);
}
builder.finish()
}
pub const VT_OBJECT_ID: flatbuffers::VOffsetT = 4;
#[inline]
pub fn object_id(&self) -> Option<&'a str> {
self._tab
.get::<flatbuffers::ForwardsUOffset<&str>>(PlasmaContainsRequest::VT_OBJECT_ID, None)
}
}
pub struct PlasmaContainsRequestArgs<'a> {
pub object_id: Option<flatbuffers::WIPOffset<&'a str>>,
}
impl<'a> Default for PlasmaContainsRequestArgs<'a> {
#[inline]
fn default() -> Self {
PlasmaContainsRequestArgs { object_id: None }
}
}

Resources