So i'm currently stumped on initializing a struct
by loading a Yaml
file into heap memory:
extern crate yaml_rust;
use std::io::prelude::*;
use std::fs;
use yaml_rust::{Yaml, YamlLoader};
struct Petrovich {
middlename: Yaml,
firstname: Yaml,
lastname: Yaml
}
impl Petrovich {
fn new() -> Petrovich {
// Open Rules File (Panics on error)
let mut f = fs::File::open("./src/rules.yml").unwrap();
// Create String Buffer and Read to it
let mut buffer = String::new();
f.read_to_string(&mut buffer).unwrap();
// Pass Buffer to Yaml and unwrap
let rules: &Yaml = &YamlLoader::load_from_str(&buffer).unwrap()[0];
// Return Petrovich with preloaded rules
Petrovich {
middlename: rules["middlename"],
firstname: rules["firstname"],
lastname: rules["lastname"]
}
}
}
However i get a cannot move out of indexed content
error. How do i tackle this?
EDIT: I am using yaml-rust
for this and have a file rules.yml
with firstname
, lastname
and middlename
fields included within ./src
Source can be found here: https://github.com/Latrasis/petrovich-rs
You are trying to move out of a borrowed pointer (because rules[str]
returns a &Yaml
), but that's not legal. We need to use functions that allow us to move a value out of the main Yaml
object. This will alter the main Yaml
object, but that's OK here, since we will discard it by the end of the function.
First, we need to understand what indexing with a string does. The implementation only returns a significant value if the value is a hash and gets to the underlying value by constructing a Yaml::String
value to index the hash.
The Yaml::Hash
variant wraps a BTreeMap<Yaml, Yaml>
. The library provides the as_hash
convenience method to access it, but this only gives an immutable pointer. We need to use pattern matching to get a mutable pointer.
Next, we'll use the remove
method on the BTreeMap
to extract the value associated with the keys that interest us.
Here's the result:
impl Petrovich {
fn new() -> Petrovich {
use yaml_rust::yaml::Hash as YamlHash;
// Open Rules File (Panics on error)
let mut f = fs::File::open("./src/rules.yml").unwrap();
// Create String Buffer and Read to it
let mut buffer = String::new();
f.read_to_string(&mut buffer).unwrap();
// Pass Buffer to Yaml and unwrap
let rules: &mut Yaml = &mut YamlLoader::load_from_str(&buffer).unwrap()[0];
let rules: &mut YamlHash = match *rules {
Yaml::Hash(ref mut hash) => hash,
_ => panic!("not a hash"),
};
// Return Petrovich with preloaded rules
Petrovich {
middlename: rules.remove(&Yaml::String("middlename".into())).unwrap(),
firstname: rules.remove(&Yaml::String("firstname".into())).unwrap(),
lastname: rules.remove(&Yaml::String("lastname".into())).unwrap(),
}
}
}
Note that this code will panic in situations in which your original code (if it worked) wouldn't, as you would get BadValue
s instead. I'll leave it to you to handle errors as you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With