2 unstable releases
0.2.0 | Feb 18, 2024 |
---|---|
0.1.0 | Nov 1, 2023 |
#1839 in Encoding
84KB
2K
SLoC
nml
Serialize and deserialize Fortran namelist input in Rust using the serde framework.
Usage
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct Particle {
index: i32,
position: [f32; 3],
velocity: [f32; 3]
}
fn main() -> Result<(), nml::NamelistError>{
let s = r#"
&particle
index = 0,
position = 0.0, 0.0, 0.0,
velocity = 1.0, 0.0, 0.0,
/"#;
let particle: Particle = nml::group_from_str(s)?.1;
println!("{:#?}", particle);
Ok(())
}
lib.rs
:
A serde library for Fortran Namelist inputs.
Namelists are a Fortran 90 feature for input and output of groups of variables in a key-value assignment format.
&particle
timestep = 0,
mass = 1.0
position = 1.0, 1.0, 1.0,
velocity = -1.0, 0.0, 0.0
/
This namelist group assignes an integer variable timestep
, a floating
point/real variable masss
and two arrays of reals position
and
velocity
.
Further data types supported by the namelist input format are bool/logical
values (assinged with .TRUE.
or .FALSE.
) and strings (denoted by either
single quotes 'hello'
, or double quotes "hello"
)
Usage
To serialize and deserialize a Rust struct (or map) as a Namelist group,
you can use the group_from_str
and group_to_string
methods:
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Particle {
timestep: i32,
mass: f32,
position: [f32; 3],
velocity: [f32; 3]
}
fn main() -> Result<(), nml::NamelistError> {
let p = Particle {
timestep: 0,
mass: 1.0,
position: [0.0, 0.0, 0.0],
velocity: [-1.0, 0.0, 0.0]
};
let serialized = nml::group_to_string(p)?;
let deserialized = nml::group_from_str(&serialized)?;
assert_eq!(p, deserialized);
Ok(())
}
To deserialize multiple Namelist groups (with the same or different group
name) from a single input into Rust structs or maps, you can use the
NamelistInput
type:
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct Simulation {
start_time: i32,
timesteps: i32
}
#[derive(Deserialize, Debug)]
struct Particle {
index: i32,
position: [f32; 3],
velocity: [f32; 3]
}
fn main() -> Result<(), nml::NamelistError>{
let s = r#"
&simulation
start_time: 0,
timesteps: 10,
/
&particle
index = 0,
position = 0.0, 0.0, 0.0,
velocity = 1.0, 0.0, 0.0,
/
&particle
index = 1,
position = 1.0, 0.0, 0.0,
velocity = -1.0, 0.0, 0.0,
/"#;
let input = NamelistInput::try_from_str(s)?;
let mut simulation = None;
let mut particles = Vec::new();
for group in &input {
if group.name() == "particle" {
let particle = Particle::deserialize(group)?;
particles.push(particle);
} else if group.name() == "simulation" {
simulation = Some(Simulation::deserialize(group)?);
}
}
Ok(())
}
As you can see, the NamelistInput
type can parse multiple namelist
groups and can be transformed into an iterator which yields one instance of
GroupRefDeserializer
for each namelist group in the input.
This type can be used to deserialize the namelist group into Rust structs
or maps.
Supported Namelist Syntax
Supported:
- All basic data types, integer, logical, string, real
- Arrays: Both Assigning sequences and individual elements using subscripts
- Derived types
Not Supported:
- Anything involving the slice operator
:
, for example:var(1:3) = 1, 2, 3,
- Assignments of sequences to subscripted variables, i.e.
var(1) = 1, 2, 3
Dependencies
~100–335KB