extern crate chrono;
pub mod error;
mod o5m;
mod xml;
use self::error::*;
use self::o5m::O5mWriter;
use self::xml::XmlWriter;
use crate::osm_io::o5m::O5mReader;
use crate::osm_io::xml::XmlReader;
use crate::Osm;
use std::convert::{TryFrom, TryInto};
use std::io::{BufRead, Write};
use std::path::Path;
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum FileFormat {
Xml,
O5m,
}
pub trait OsmWriter<W: Write> {
fn write(&mut self, osm: &Osm) -> std::result::Result<(), ErrorKind>;
fn into_inner(self: Box<Self>) -> W;
}
pub trait OsmReader {
fn read(&mut self) -> std::result::Result<Osm, Error>;
}
pub fn create_writer<'a, W: Write + 'a>(
writer: W,
format: FileFormat,
) -> Box<dyn OsmWriter<W> + 'a> {
match format {
FileFormat::O5m => Box::new(O5mWriter::new(writer)),
FileFormat::Xml => Box::new(XmlWriter::new(writer)),
}
}
pub fn create_reader<'a, R: BufRead + 'a>(
reader: R,
format: FileFormat,
) -> Box<dyn OsmReader + 'a> {
match format {
FileFormat::Xml => Box::new(XmlReader::new(reader)),
FileFormat::O5m => Box::new(O5mReader::new(reader)),
}
}
impl FileFormat {
pub fn from(s: &str) -> Option<Self> {
match s {
"osm" => Some(FileFormat::Xml),
"o5m" => Some(FileFormat::O5m),
_ => None,
}
}
}
impl TryFrom<&str> for FileFormat {
type Error = String;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
if let Some(format) = FileFormat::from(&value) {
Ok(format)
} else {
Err(format!("'{:?}' is not a valid osm file format", value))
}
}
}
impl TryFrom<&String> for FileFormat {
type Error = String;
fn try_from(value: &String) -> std::result::Result<Self, Self::Error> {
(value[..]).try_into()
}
}
impl TryFrom<&Path> for FileFormat {
type Error = String;
fn try_from(path: &Path) -> std::result::Result<Self, Self::Error> {
if let Some(ext) = path.extension() {
if let Some(str) = ext.to_str() {
return str.try_into();
}
}
Err(format!("Unknown file format of '{:?}'", path.to_str()))
}
}
#[cfg(test)]
mod tests {
use crate::osm_io::FileFormat;
use std::convert::TryInto;
use std::path::Path;
#[test]
fn file_format_from_path() {
let path = Path::new("test.o5m");
let format = path.try_into();
assert_eq!(format, Ok(FileFormat::O5m));
let path = Path::new("test.osm");
let format = path.try_into();
assert_eq!(format, Ok(FileFormat::Xml));
}
#[test]
fn file_format_from_str() {
let format = "o5m".try_into();
assert_eq!(format, Ok(FileFormat::O5m));
let format = "osm".try_into();
assert_eq!(format, Ok(FileFormat::Xml));
}
#[test]
fn file_format_from_string() {
let format = (&"o5m".to_owned()).try_into();
assert_eq!(format, Ok(FileFormat::O5m));
let format = (&"osm".to_owned()).try_into();
assert_eq!(format, Ok(FileFormat::Xml));
}
}