I have the following code, that I think is pretty self-explanatory. The problem I'm facing is in the render function:
fn render(&self) -> &'static str {
self.view.value
}
Where the compiler complains:
attempted access of field `view` on type `&Self`, but no field with that name was found`
Full code:
struct View1 {
value: &'static str,
}
struct View2 {
value: &'static str,
another_value: &'static str,
}
struct Pattern<T> {
view: T,
}
trait Renderable {
fn render(&self) -> &'static str {
self.view.value
}
}
impl <T> Renderable for Pattern <T> {}
fn patterns() -> Vec<Box<Renderable>> {
vec![
Box::new(Pattern { view: View1 { value: "x" } }),
Box::new(Pattern { view: View1 { value: "y" } }),
]
}
fn main() {
let p = patterns();
for x in p.iter() {
println!("{}", x.render());
}
}
Yes, traits do not have access to the fields of their implementors. You need to provide accessor methods. These are small and should be optimized away:
trait View {
fn value(&self) -> &'static str;
}
struct View1 {
value: &'static str,
}
impl View for View1 {
fn value(&self) -> &'static str { self.value }
}
struct View2 {
value: &'static str,
another_value: &'static str,
}
impl View for View2 {
fn value(&self) -> &'static str { self.value }
}
trait Renderable {
fn view(&self) -> &View;
fn render(&self) -> &'static str {
self.view().value()
}
}
struct Pattern<T>
where T: View
{
view: T,
}
impl<T> Renderable for Pattern<T>
where T: View
{
fn view(&self) -> &View {
&self.view
}
}
fn patterns() -> Vec<Box<Renderable>> {
vec![
Box::new(Pattern { view: View1 { value: "x" } }),
Box::new(Pattern { view: View2 { value: "y", another_value: "z" } }),
]
}
fn main() {
let p = patterns();
for x in p.iter() {
println!("{}", x.render());
}
}
Basically, traits are contracts that objects must adhere to, and the language of those contracts is the function names, the argument types, and the return types. If a trait needs to be able to get a view or a value, then that needs to be a part of the trait.
Note that implementations of traits do have access to the fields of the struct they are implementing the trait on. Since the implementation is specialized for one type, that guarantees that you have access to the appropriate fields.
Related
I'd like to use Factory to build an object from the String and have multiple impls: 1) actual building and 2) caching (stores in-memory in HashMap). The problem is that in case #1 it have to pass the ownership and in case #2 HashMap owns the value and a reference can be returned only.
use std::collections::HashMap;
// product interface
pub trait TProduct {
fn get_title(&self) -> &String;
}
// and concrete impls
pub struct ConcreteProduct1 {
}
impl TProduct for ConcreteProduct1 {
// ...
}
pub struct ConcreteProduct2 {
}
impl TProduct for ConcreteProduct2 {
// ...
}
// factory interface
pub trait TProductFactory {
fn product_from_text(&mut self, text: String) -> Box<dyn TProduct>;
// QUESTION: should it be Box (required for ProductFactory) or &Box (required for ProductCachingProxy)?
}
// actual building factory
pub struct ProductFactory {
}
impl TProductFactory for ProductFactory {
fn product_from_text(&mut self, text: String) -> Box<dyn TProduct> {
//...
// depending on some conditions
Box::new(ConcreteProduct1::from_text(text)); // has to pass the ownership
// or
Box::new(ConcreteProduct2::from_text(text)); // has to pass the ownership
//...
}
}
// caching proxy
trait TProductCache {
fn put(&mut self, text: &String, product: Box<dyn TProduct>);
fn get(&self, text: &String) -> Option<&Box<dyn TProduct>>;
fn clear(&mut self);
}
struct InMemoryProductCache {
map: HashMap<String, Box<dyn TProduct>>
}
impl InMemoryProductCache {
fn new() -> Self {
return InMemoryProductCache {
map: HashMap::new()
}
}
}
impl TProductCache for InMemoryProductCache {
fn put(&mut self, text: &String, product: Box<dyn TProduct>) {
self.map.insert(text.to_string(), product);
}
fn get(&self, text: &String) -> Option<&Box<dyn TProduct>> {
return match self.map.get(text) {
Some(boxed_product) => Some(boxed_product), // have to pass a reference to let it still own the value
None => None
}
}
fn clear(&mut self) {
self.map.clear();
}
}
struct ProductCachingProxy {
product_factory: Box<dyn TProductFactory>,
cache: Box<dyn TProductCache>
}
impl ProductCachingProxy {
fn new_for_factory(product_factory: Box<dyn TProductFactory>, cache: Box<dyn TProductCache>) -> Self {
return ProductCachingProxy {
product_factory,
cache
}
}
}
impl TProductFactory for ProductCachingProxy {
fn product_from_text(&mut self, text: String) -> &Box<dyn TProduct> { // can't pass ownership
let boxed_product = match self.cache.get(&text) {
Some(found_boxed_product) => found_boxed_product,
_ => {
// delegate creation to wrapped TProductFactory impl (`product_factory`)
let boxed_product = self.product_factory.product_from_text(text.clone());
// ... and put to the cache
self.cache.put(&text, boxed_product);
&boxed_product
}
};
return boxed_product;
}
}
// QUESTION: should it be Box (required for ProductFactory) or &Box (required for ProductCachingProxy) to be returned from TProductFactory.fn product_from_text(&mut self, text: String) -> Box<dyn TProduct>; ?
If caching proxy to return a Box, how can it be created from a reference without copying/cloning (TProductCache.get(..))?
Replace Box with Rc (or Arc if you use threads). It provides shared ownership and suites both your cases with single signature. Another option is to use Cow that is a enum of owned and borrowed states.
I'm making a functional builder that configures an object such as:
struct Person
{
name: String,
position: String
}
The builder itself keeps a list of boxed closures to be applied to the object when it needs to be constructed:
struct FunctionalBuilder<TSubject>
where TSubject : Default
{
actions: Vec<Box<dyn Fn(&mut TSubject) -> ()>>
}
impl<TSubject> FunctionalBuilder<TSubject>
where TSubject : Default
{
fn build(self) -> TSubject
{
let mut subj = TSubject::default();
for action in self.actions
{
(*action)(&mut subj);
}
subj
}
}
The idea being that one can aggregate this builder and then customize it for an object such as Person. Now, let's say I want to have a builder method called() that takes a name and saves the assignment of the name in the closure. I implement it as follows:
impl PersonBuilder
{
pub fn called(mut self, name: &str) -> PersonBuilder
{
let value = name.to_string();
self.builder.actions.push(Box::new(move |x| {
x.name = value.clone();
}));
self
}
}
Is this the right way of doing things? Is there a better way that avoids the temporary variable and clone() call?
Complete working example:
#[derive(Debug, Default)]
struct Person {
name: String,
position: String,
}
struct FunctionalBuilder<TSubject>
where
TSubject: Default,
{
actions: Vec<Box<dyn Fn(&mut TSubject) -> ()>>,
}
impl<TSubject> FunctionalBuilder<TSubject>
where
TSubject: Default,
{
fn build(self) -> TSubject {
let mut subj = TSubject::default();
for action in self.actions {
(*action)(&mut subj);
}
subj
}
fn new() -> FunctionalBuilder<TSubject> {
Self {
actions: Vec::new(),
}
}
}
struct PersonBuilder {
builder: FunctionalBuilder<Person>,
}
impl PersonBuilder {
pub fn new() -> Self {
PersonBuilder {
builder: FunctionalBuilder::<Person>::new(),
}
}
pub fn called(mut self, name: &str) -> PersonBuilder {
let value = name.to_string();
self.builder.actions.push(Box::new(move |x| {
x.name = value;
}));
self
}
pub fn build(self) -> Person {
self.builder.build()
}
}
pub fn main() {
let builder = PersonBuilder::new();
let me = builder.called("Dmitri").build();
println!("{:?}", me);
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=27eb6283836a478d5c68aa025aa4698d
You already do it, value is owned by your closure, the problem is that you require the Fn trait. This mean that action (the function) need to be able to be called many times. This mean value need to be cloned to keep it valid inside the closure. The closure can't give away its ownership.
One way would be to use FnOnce, which would make it possible to remove the clone, but this means that the builder can only be used once. To do this, use actions: Vec<Box<dyn FnOnce(&mut TSubject) -> ()>>, and action(&mut subj);.
More:
"cannot move a value of type FnOnce" when moving a boxed function
Fn* closure traits implemented for Box<dyn Fn*>
use std::cell::RefCell;
use std::collections::VecDeque;
// minimum reproducible example for stack overflow question
// which is essentially the whole thing b/c all of these types
// depend on each other
// this is an implementation of Monopoly Deal (see http://monopolydealrules.com/)
// but the only relevant part to the question is in main(), around line 400
// card.rs
pub trait Card {
fn value(&self) -> i32;
fn kind(&self) -> CardKind;
}
pub enum CardKind {
Money,
Action,
Property,
Building,
}
// property.rs
pub struct PropertySet {
color: Color,
properties: Vec<Property>,
house: bool,
hotel: bool,
}
impl PropertySet {
pub fn rent(&self) -> i32 {
unimplemented!() // stub
}
pub fn color(&self) -> Color {
self.color
}
pub fn properties(&self) -> &Vec<Property> {
&self.properties
}
pub fn is_full(&self) -> bool {
self.properties().len() == self.color.set_size() as usize
}
pub fn is_empty(&self) -> bool {
self.properties().len() == 0
}
pub fn add(&mut self, property: Property) -> Result<(), PropertySetAddError> {
if !property.matches(self.color) {
return Err(PropertySetAddError {
property,
kind: PropertySetAddErrorKind::WrongColor,
});
}
if self.properties.len() + 1 < self.color.set_size() as usize {
self.properties.push(property);
Ok(())
} else {
Err(PropertySetAddError {
property,
kind: PropertySetAddErrorKind::SetFull,
})
}
}
fn remove(&mut self, index: usize) -> Property {
self.properties.remove(index)
}
}
pub struct PropertySetAddError {
property: Property,
kind: PropertySetAddErrorKind,
}
pub enum PropertySetAddErrorKind {
WrongColor,
SetFull,
}
pub enum Property {
Basic { name: String, color: Color },
Wild { colors: [Color; 2], value: i32 },
Any,
}
impl Card for Property {
fn value(&self) -> i32 {
unimplemented!() // stub
}
fn kind(&self) -> CardKind {
CardKind::Property
}
}
impl Property {
pub fn matches(&self, color: Color) -> bool {
unimplemented!() // stub
}
}
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
pub enum Color {
Red,
Orange,
Yellow,
Green,
LightBlue,
DarkBlue,
Magenta,
Brown,
Utility,
Railroad,
}
impl Color {
pub fn set_size(&self) -> i32 {
unimplemented!() // stub
}
}
// money.rs
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Money(pub i32);
impl Card for Money {
fn value(&self) -> i32 {
self.0
}
fn kind(&self) -> CardKind {
CardKind::Money
}
}
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct Id(pub usize);
pub struct Possessions {
bank: Vec<Money>,
hand: Vec<Box<dyn Card>>,
properties: Vec<PropertySet>,
}
// brain.rs
pub trait Brain {
fn act(&self, state: &GameState, possessions: &mut Possessions) -> Vec<Effect>;
fn react(
&self,
state: &GameState,
possessions: &mut Possessions,
effect: &Effect,
) -> Vec<Effect>;
}
pub struct Human {}
impl Human {
pub fn new() -> Human {
Human {}
}
}
impl Brain for Human {
fn act(&self, state: &GameState, possessions: &mut Possessions) -> Vec<Effect> {
unimplemented!()
}
fn react(
&self,
state: &GameState,
possessions: &mut Possessions,
effect: &Effect,
) -> Vec<Effect> {
unimplemented!()
}
}
// action.rs
pub enum Action {
Rent { colors: [Color; 2] },
AnyRent,
DoubleRent,
DealBreaker,
DebtCollector,
Birthday,
SayNo,
PassGo,
SlyDeal,
ForcedDeal,
}
impl Card for Action {
fn value(&self) -> i32 {
unimplemented!() // stub
}
fn kind(&self) -> CardKind {
CardKind::Action
}
}
impl Action {
pub fn effect<'a>(
&self,
source: Id,
target: ActionTarget<'a>,
) -> Result<Effect<'a>, EffectError> {
unimplemented!() // stub
}
}
pub enum ActionTarget<'a> {
None,
Player {
player: Id,
},
Set {
/// The player that this action is targeted against
player: Id,
/// Can be a set that player owns, such as in the case of Deal Breaker, or it
/// can be a set that the source owns, such as in the case of rent cards
set: &'a PropertySet,
},
Property {
player: Id,
property: (&'a PropertySet, usize),
},
Swap {
player: Id,
take: (&'a PropertySet, usize),
give: (&'a PropertySet, usize),
},
}
// effect.rs
#[derive(Clone)]
pub enum Effect<'a> {
// swaps properties with another player
Swap {
source: Id,
target: Id,
give: (&'a PropertySet, usize),
take: (&'a PropertySet, usize),
},
// steals properties from another player
Steal {
source: Id,
target: Id,
set: &'a PropertySet,
indices: Vec<usize>,
},
// charges another player
Charge {
source: Id,
target: Option<Id>,
amount: i32,
reason: ChargeReason,
},
// cancels prior effect
Cancel {
source: Id,
target: Id,
},
// pass Go, credit $2M
Go {
source: Id,
},
}
#[derive(Clone)]
pub enum ChargeReason {
Rent,
Birthday,
DebtCollector,
}
pub enum EffectError {
/// The target supplied was not valid for this action.
InvalidTarget,
/// You tried to charge rent for a color, but the specified set isn't that color
NoProperty,
}
// player.rs
pub struct Player {
pub id: Id,
pub name: String,
pub possessions: Possessions,
pub brain: Box<dyn Brain>,
}
impl Player {
pub fn new(id: Id, name: String, brain: Box<dyn Brain>) -> Player {
Player {
id,
possessions: Possessions {
bank: vec![],
hand: vec![],
properties: vec![],
},
name,
brain,
}
}
pub fn id(&self) -> Id {
self.id
}
pub fn bank(&self) -> &Vec<Money> {
&self.possessions.bank
}
pub fn properties(&self) -> &Vec<PropertySet> {
&self.possessions.properties
}
pub fn name(&self) -> &str {
&self.name
}
pub fn brain(&self) -> &Box<dyn Brain> {
&self.brain
}
pub fn act(&mut self, state: &GameState) -> Vec<Effect> {
self.brain.act(state, &mut self.possessions)
}
pub fn react(&mut self, state: &GameState, effect: &Effect) -> Vec<Effect> {
self.brain.react(state, &mut self.possessions, effect)
}
}
// state.rs
pub struct GameState {
pub players: Vec<RefCell<Player>>,
pub current: Id,
pub stack: Vec<Box<dyn Card>>,
}
impl GameState {
pub fn next(&mut self) {
self.current = Id((self.current.0 + 1) % self.players.len())
}
pub fn current_player(&self) -> &RefCell<Player> {
self.players.get(self.current.0).unwrap()
}
pub fn get_player(&self, id: Id) -> Option<&RefCell<Player>> {
self.players.get(id.0)
}
}
// deck.rs
pub fn create_deck() -> Vec<Box<dyn Card>> {
vec![
// ...
]
}
// main.rs
pub fn main() {
let brain = Human::new(); // Human implements Brain
let me = Player::new(Id(0), "Ibi".to_owned(), Box::new(brain));
let current = me.id();
let players = vec![RefCell::new(me)];
let stack = create_deck(); // returns Vec<Box<dyn Card>>
let mut state = GameState {
players,
stack,
current,
};
while !state.players.iter().any(|player| {
player
.borrow()
.properties()
.iter()
.filter(|&set| set.is_full())
.count()
>= 3
}) {
// ...
let mut effects = VecDeque::new();
{
let mut current_player = state.current_player().borrow_mut();
let action = current_player.act(&state);
effects.extend(action);
}
// let all other players react to effects until no more reactions are generated
while !effects.is_empty() {
let effect = effects.pop_front().unwrap();
// ...
}
}
}
I can't get this code to compile; it says that current_player does not live long enough and complains that it is dropped at the end of the block. Why does current_player need to survive beyond the end of the block? My understanding is that it returns a Vec<Effect> which my method now owns, and then that vector is consumed by extend() and the values it contained are now owned by effects, so why is current_player still necessary?
I'm trying to have a collection of objects that implement a particular trait.
If I use a trait that returns a value, this works
use std::collections::BTreeMap;
struct World {
entities: Vec<usize>,
database: BTreeMap<usize, Box<ReadValue>>,
//database : BTreeMap<usize,Box<ReadEcs>>, // Doesn't work
}
struct SourceInputGateway {
entity_id: usize,
}
trait ReadValue {
fn read(&self) -> f32;
}
impl ReadValue for SourceInputGateway {
fn read(&self) -> f32 {
0.0
}
}
But if I want to return Self as a value then this doesn't work, either as a method template param or associated type
trait ReadEcs {
type T;
fn read(&self) -> &Self::T;
}
impl ReadEcs for SourceInputGateway {
type T = SourceInputGateway;
fn read(&self) -> &Self::T {
self
}
}
What I would like to do is have a map of types that implement ReadEcs, the concrete type of which is not important.
Further clarification edit
If I expand the example by adding
// Different sized type
struct ComputeCalculator {
entity_id : usize,
name : String,
}
impl ReadValue for ComputeCalculator {
fn read(&self) -> f32 {
1230.0
}
}
then I can do this
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_write() {
let mut world = World::new();
world.database.insert(0,Box::new(SourceInputGateway{ entity_id : 1}));
world.database.insert(2,Box::new(ComputeCalculator{ entity_id : 2 , name : "foo".into() }));
for (k,ref v) in world.database {
let item : &Box<ReadValue> = v;
item.read();
}
}
}
but if I change or add a trait method that returns Self, I can't do this.
I'd like to understand a way to get around it without unsafe pointers.
I thought about this a little more and I think it's possible to solve this while retaining all the advantages of type safety and contiguous storage.
Defining a entity manager with pointers to storage
struct Entities {
entities: Vec<usize>,
containers: Vec<Box<Storage>>,
}
The components themselves that store data related to behaviour
struct Position {
entity_id: usize,
position: f32,
}
struct Velocity {
entity_id: usize,
velocity: f32,
}
We will have many instances of components, so we need a contiguous memory store, accessed by an index.
struct PositionStore {
storage: Vec<Position>,
}
struct VelocityStore {
storage: Vec<Velocity>,
}
trait Storage {
// Create and delete instances of the component
fn allocate(&mut self, entity_id: usize) -> usize;
// Interface methods that would correspond to a base class in C++
fn do_this(&self);
// fn do_that(&self);
}
The trait for the store implements an arena style storage plus the methods it would pass to to the components. This would likely be in the "System" part of an ECS but is left as an exercise for later.
I would like a hint as to how to pass a Fn() that constructs a custom object to the allocate() method. I've not figured that out yet.
impl Storage for PositionStore {
fn allocate(&mut self, entity_id: usize) -> usize {
self.storage.push(Position {
entity_id,
position: 0.0,
});
self.storage.len() - 1
}
fn run(&self) {
self.storage.iter().for_each(|item| { println!("{}",item.position); });
}
}
impl Storage for VelocityStore {
fn allocate(&mut self, entity_id: usize) -> usize {
self.storage.push(Velocity {
entity_id,
velocity: 0.0,
});
self.storage.len() - 1
}
fn do_this(&self) {
self.storage.iter().for_each(|item| { println!("{}",item.velocity); });
}
}
Some boiler plate.
impl Default for PositionStore {
fn default() -> PositionStore {
PositionStore {
storage: Vec::new(),
}
}
}
impl Default for VelocityStore {
fn default() -> VelocityStore {
VelocityStore {
storage: Vec::new(),
}
}
}
I think this could be thought about a little more. It stores the relationship between the storage of the components and their position
Instead of T::default(), you may want to pass a lambda function that has a specific initialisation for each of your components
impl Entities {
fn register<T>(&mut self) -> usize
where
T: Storage + Default + 'static,
{
self.containers.push(Box::new(T::default()));
self.containers.len() - 1
}
fn create<T>(&mut self, entity_id: usize, id: usize) -> usize {
self.containers[id].allocate(entity_id)
}
fn run_loop(&self) {
self.containers.iter().for_each(|x| x.do_this());
}
}
A test case to see if this works
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arbitary() {
let mut entities = Entities {
entities: Vec::new(),
containers: Vec::new(),
};
let velocity_store_id = entities.register::<VelocityStore>();
let position_store_id = entities.register::<PositionStore>();
let _ = entities.create::<Velocity>(123, velocity_store_id);
let _ = entities.create::<Velocity>(234, velocity_store_id);
let _ = entities.create::<Position>(234, position_store_id);
let _ = entities.create::<Position>(567, position_store_id);
entities.run_loop();
}
}
I have some nested structs and cannot create a back reference to the parent struct. An example:
struct Foo<'a> {
parent: &'a Bar<'a>,
}
impl<'a> Foo<'a> {
fn new(parent: &'a Bar) -> Self {
Foo { parent: parent }
}
fn hello_world(&self) -> String {
self.parent.hello().to_owned() + " world"
}
}
struct Bar<'b> {
child: Option<Foo<'b>>,
data: &'static str,
}
impl<'b> Bar<'b> {
fn new() -> Self {
Bar {
child: None,
data: "hello",
}
}
fn hello(&self) -> &str {
self.data
}
fn get_foo(&self) -> Option<&Foo> {
self.child.as_ref()
}
}
fn main() {
let bar = Bar::new();
assert_eq!("hello", bar.hello());
match bar.get_foo() {
Some(foo) => assert_eq!("hello world", foo.hello_world()),
None => (),
}
}
How can I replace None with Some<Foo> with a reference to Bar? So far I'm not sure that it is possible.
It's not exactly a drop-in solution for your example, but I believe you can create "circular references" as you specify using Arc and RwLock. The API is not exactly the same (e.g., parent is an optional field), I renamed some objects, and it is definitely more verbose, but your tests pass!
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
struct Child {
parent: Option<Arc<RwLock<Parent>>>
}
impl Child {
fn new() -> Self {
Child {
parent: None
}
}
fn hello_world(&self) -> String {
let x = self.parent.as_ref().unwrap().clone();
let y = x.read().unwrap();
y.hello().to_owned() + " world"
}
}
#[derive(Debug, Clone)]
struct Parent {
child: Option<Arc<RwLock<Child>>>,
data: &'static str
}
impl Parent {
fn new() -> Self {
Parent {
child: None,
data: "hello"
}
}
fn hello(&self) -> &str {
self.data
}
fn get_child(&self) -> Option<Arc<RwLock<Child>>> {
self.child.as_ref().map(|x| x.clone() )
}
}
fn main() {
let parent = Arc::new(RwLock::new(Parent::new()));
let child = Arc::new(RwLock::new(Child::new()));
parent.write().unwrap().child = Some(child.clone());
child.write().unwrap().parent = Some(parent.clone());
assert_eq!("hello", parent.read().unwrap().hello());
{
let x = parent.read().unwrap();
match x.get_child() {
Some(child) => { assert_eq!("hello world", child.read().unwrap().hello_world()); }
None => {},
}
}
}
I have a similar problem, and am not entirely satisfied with the proposed solutions.
If your structure is really nested (i.e. you have a notion of "parent" and "child", with a unique parent for each child), then it seems natural that the parent should own the child(ren). So using Rc/Arc (which are designed to allow for multiple owners) does not look like the right solution -- all the less so because, as #Shepmaster points out, it "encourages" (or at least allows) the creation of cyclic references.
My idea was to have each child hold a raw pointer to its parent:
pub struct Node {
parent: *mut Node,
// ...
}
Since a node is owned by its parent, it can only be borrowed (resp. mutably borrowed) while its parent is being borrowed (resp. mutably borrowed). So in that context, it should be safe to cast self.parent to a &Node (resp. &mut Node, if self is mutable).
impl Node {
pub fn get_parent(&self) -> Option<&Node> {
unsafe { self.parent.as_ref() }
}
pub fn get_mut_parent(&mut self) -> Option<&mut Node> {
unsafe { self.parent.as_mut() }
}
}
However, this requires that the address of the parent node never changes (i.e. the parent is never moved). This can be achieved by only ever handling boxed nodes.
pub struct Node {
parent: *mut Node,
children: Vec<Box<Node>>,
// ..
}
impl Node {
pub fn new(data: &str) -> Box<Node> {
Box::new(Node {
parent: std::ptr::null_mut(),
children: vec![],
// ..
})
}
pub fn append_child(&mut self, mut child: Box<Node>) -> usize {
child.parent = self;
self.children.push(child);
self.children.len() - 1
}
}
I implemented a full-fledged example in the playground.