Rc<T> handling question

I've impl From<&str> for MyStruct to parse the str and put it in some linked and nested MyStructs (like a special tree/leaves thing). For this I use a root Rc<MyStruct>. But because I reference this root as parent in nested things the RcCounter as well the WeakCounter are above 1 and I can't get back MyStruct to return it from this impl From.

More or less I pass parents like MyStruct::new(parent: Option<Rc<Self>>).

As a workaround I've nested the real root in a pseudo-root I can return here. But I've this not very useful 1st level I've to step over when accessing MyStruct.

The best would be to impl From<&str> for Rc<MyStruct> if this would be possible.
So of course I could create a fn MyStruct::parse_from_str(s: &str) -> Rc<Self>.

But do you know the idiomatic Rust way this is mostly done?
I am also asking, because it feels very verbose to use Rc and RefCell to build up these linked stuff.

How about this: struct MyWrappedStruct(Rc<MyStruct>);. Then you can do impl From<&str> for MyWrappedStruct { ... }.

I had a case where I hid the Rc by making a wrapper type just like in @RedDocMD's suggestion. This wasn't for the purpose of being able to implement From, but to keep implementation details private to the module.

I'm not sure how to solve your problem, bit I did note a few interesting things.

The idiomatic way to do this is with FromStr and parse.

Also note that From is usually reserved for straightforward type transformations. If you have to build a complicated tree structure inside the implementation of From, I would say it's probably the wrong choice.

2 Likes

I think about it...
MyStruct is in reality little bit more complex, it is also a trait object. Although the parser returns only MyStruct.
So the Wrapper would need to impl the trait also and pass it on to the MyStruct implementations or is it possible to deref the Wrapper "automagically" on method calls to the inner MyStruct?

Do you need to implement a trait at all here? What's wrong with just creating your own parse_from_str method? What you're doing sounds complex enough that it doesn't fit within any of the normal traits.

To clarify the trait usage...
Would you say that parsing "0,1,2,3,4,5" to a Vec of the numbers (if this would be possible/just for simplification) wouldn't be a case for the From/FromStr traits?
I'm doing byte/bits stuff, and for testing it has been convenient to have the From-trait implemented to pass in string formated data in the unit tests.

The standard library doesn't provide such an implementation, so I would say no. Instead, it would be more idiomatic to compose that task from smaller tasks, e.g.

let parsed: Vec<i32> = "0,1,2,3,4,5".split(",").map(str::parse).collect()?;

Edit: corrected example to compile.

Like all design questions, the answer is it depends. Does it make your life as a developer too hard? Does it make the life of the user too hard? Do you care about any of these (sometimes you may not)? Maybe you have a very tight deadline and so need whatever works.
The point is that there is no correct answer. It is a design problem. Use whatever suits your needs and "feels" right.
PS: What "feels" right will change from time to time - but is often the only good metric you have.

:+1:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.