extern crate xdr_codec as xdr;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate nom;
#[macro_use]
extern crate bitflags;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::io::{Read, Write};
use std::fmt::Display;
use std::env;
use std::result;
use xdr::Result;
mod spec;
use spec::{Emit, Emitpack, Symtab};
fn result_option<T, E>(resopt: result::Result<Option<T>, E>) -> Option<result::Result<T, E>> {
match resopt {
Ok(None) => None,
Ok(Some(v)) => Some(Ok(v)),
Err(e) => Some(Err(e)),
}
}
pub fn generate<In, Out>(infile: &str, mut input: In, mut output: Out) -> Result<()>
where
In: Read,
Out: Write,
{
let mut source = String::new();
input.read_to_string(&mut source)?;
let xdr = match spec::specification(&source) {
Ok(defns) => Symtab::new(&defns),
Err(e) => return Err(xdr::Error::from(format!("parse error: {}", e))),
};
let xdr = xdr;
let res: Vec<_> = {
let consts = xdr.constants()
.filter_map(|(c, &(v, ref scope))| if scope.is_none() {
Some(spec::Const(c.clone(), v))
} else {
None
})
.map(|c| c.define(&xdr));
let typespecs = xdr.typespecs()
.map(|(n, ty)| spec::Typespec(n.clone(), ty.clone()))
.map(|c| c.define(&xdr));
let typesyns = xdr.typesyns()
.map(|(n, ty)| spec::Typesyn(n.clone(), ty.clone()))
.map(|c| c.define(&xdr));
let packers = xdr.typespecs()
.map(|(n, ty)| spec::Typespec(n.clone(), ty.clone()))
.filter_map(|c| result_option(c.pack(&xdr)));
let unpackers = xdr.typespecs()
.map(|(n, ty)| spec::Typespec(n.clone(), ty.clone()))
.filter_map(|c| result_option(c.unpack(&xdr)));
consts
.chain(typespecs)
.chain(typesyns)
.chain(packers)
.chain(unpackers)
.collect::<Result<Vec<_>>>()?
};
let _ = writeln!(
output,
r#"
// GENERATED CODE
//
// Generated from {} by xdrgen.
//
// DO NOT EDIT
"#,
infile
);
for it in res {
let _ = writeln!(output, "{}\n", it.as_str());
}
Ok(())
}
pub fn compile<P>(infile: P) -> Result<()>
where
P: AsRef<Path> + Display,
{
let input = File::open(&infile)?;
let mut outdir = PathBuf::from(env::var("OUT_DIR").unwrap_or(String::from(".")));
let outfile = PathBuf::from(infile.as_ref())
.file_stem()
.unwrap()
.to_owned()
.into_string()
.unwrap()
.replace("-", "_");
outdir.push(&format!("{}_xdr.rs", outfile));
let output = File::create(outdir)?;
generate(
infile.as_ref().as_os_str().to_str().unwrap_or("<unknown>"),
input,
output,
)
}