Reputation: 21
crates involved: toml = "0.5.6" serde = { version = "1.0", features = ["derive"] }
Im attempting to de-serialize toml data generated by saving the output of toml::to_string() to disk. Code compiles but panics at runtime with unhelpful error.
I'm calling init_cfg() with a seemingly valid path to the test file to generate my application configuration.
File Structure:
C:.
├───.vscode
├───res
│ ├───cfg
#cfg.toml here
│ ├───fonts
│ │ └───FiraCode-5.2
│ ├───layout
│ ├───splits
│ └───sys
├───src
cfg.toml:
title = "title"
width = 400
height = 600
code
#[derive(Debug, Serialize, Deserialize)]
pub struct Cfg {
pub title: String,
pub width: u32,
pub height: u32,
}
pub fn init_cfg(cfg_path: &Path) -> Box<Self> {
let mut config = Cfg::default();
// Check to see if config exists
if cfg_path.exists() {
// Load config
config = *Self::read(cfg_path);
// Return heap allocated Cfg instance
return Box::new(config);
} else {
// Write config to disk
match Self::write(cfg_path, &config) {
// Return config
Ok(_count) => Box::new(config),
Err(e) => {
println!("Failed to write default config.");
panic!(e)
},
}
}
}
pub fn read(path: &Path) -> Box<Self> {
// Open file
if path.exists() {
let mut file = match File::open(path) {
Ok(file) => file,
Err(err) => {
println!("Failed to open config file for reading.");
panic!(err)
}
};
// Read file into buffer
let mut buffer = Vec::new();
match file.read(&mut *buffer) {
Ok(_size) => {},
Err(err) => {
print!("Failed to read cfg file into buffer");
panic!(err)
}
};
// Deserialize Cfg
Box::new(match toml::from_slice(&buffer) {
Ok(config) => config,
Err(err) =>
println!("Failed to deserialize user config.");
// Line 81
panic!(err)
}
})
} else {
panic!("No cofig file at given path.")
}
}
cout:
Running `target\debug\picosplit.exe`
Failed to deserialize user config.
thread 'main' panicked at 'Box<Any>', src\cfg.rs:81:21
stack backtrace:
0: backtrace::backtrace::dbghelp::trace
at C:\Users\VssAdministrator\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.46\src\backtrace/dbghelp.> rs:88
1: backtrace::backtrace::trace_unsynchronized
at C:\Users\VssAdministrator\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.46\src\backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src\libstd\sys_common/backtrace.rs:78
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src\libstd\sys_common/backtrace.rs:59
4: core::fmt::write
at src\libcore\fmt/mod.rs:1076
5: std::io::Write::write_fmt
at src\libstd\io/mod.rs:1537
6: std::sys_common::backtrace::_print
at src\libstd\sys_common/backtrace.rs:62
7: std::sys_common::backtrace::print
at src\libstd\sys_common/backtrace.rs:49
8: std::panicking::default_hook::{{closure}}
at src\libstd/panicking.rs:198
9: std::panicking::default_hook
at src\libstd/panicking.rs:217
10: std::panicking::rust_panic_with_hook
at src\libstd/panicking.rs:526
11: std::panicking::begin_panic
at C:\Users\lmpri\scoop\persist\rustup\.rustup\toolchains\nightly-x86_64-pc-windows-gnu\lib/rustlib/src/> rust\src\libstd/panicking.rs:456
12: picosplit::cfg::Cfg::read
at src/cfg.rs:81
13: picosplit::cfg::Cfg::init_cfg
at src/cfg.rs:36
14: picosplit::main
at src/main.rs:18
15: std::rt::lang_start::{{closure}}
at C:\Users\lmpri\scoop\persist\rustup\.rustup\toolchains\nightly-x86_64-pc-windows-gnu\lib/rustlib/src/> rust\src\libstd/rt.rs:67
16: std::rt::lang_start_internal::{{closure}}
at src\libstd/rt.rs:52
17: std::panicking::try::do_call
at src\libstd/panicking.rs:348
18: std::panicking::try
at src\libstd/panicking.rs:325
19: std::panic::catch_unwind
at src\libstd/panic.rs:394
20: std::rt::lang_start_internal
at src\libstd/rt.rs:51
21: std::rt::lang_start
at C:\Users\lmpri\scoop\persist\rustup\.rustup\toolchains\nightly-x86_64-pc-windows-gnu\lib/rustlib/src/rust\src\libstd/rt.rs:67
22: main
23: __tmainCRTStartup
at D:/mingwbuild/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:339
24: mainCRTStartup
at D:/mingwbuild/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:223
25: units_search
26: units_search
Upvotes: 1
Views: 602
Reputation: 21
Data is not being read into the buffer correctly. buffer is an empty vector when reaching line 81 causing de-serialization to fail.
changed
match file.read(&mut *buffer) {...};
to
file.read_to_end(&mut buffer).expect("Failed to read cfg file into buffer");
Apologies, I'm quite new to the language and SO.
Upvotes: 1
Reputation: 42282
Code compiles but panics at runtime with unhelpful error.
That's because you're shoving an arbitrary error type in there, which nets you a Box as documented:
Each thread's panic can be reaped as the Box type, and the single-argument form of the panic! macro will be the value which is transmitted.
Instead of that you could have:
panic!
which works like println!
and would also allow for debug-printing: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b736d75cb04f82789861e5de1df38fa4Can't really help further since you don't provide a runnable reproduction case.
And once you've gotten a useful error message, you may want to take a gander at the project's own bug tracker as there are known issues with round-tripping in some edge cases e.g. https://github.com/alexcrichton/toml-rs/issues/388
Upvotes: 0