#![crate_name = "fixed_width"]
#![deny(missing_docs)]
extern crate serde;
#[cfg(test)]
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate serde_bytes;
use std::ops::Range;
use std::result;
pub use de::{
from_bytes, from_bytes_with_fields, from_str, from_str_with_fields, DeserializeError,
Deserializer,
};
pub use error::Error;
pub use reader::{ByteReader, Reader, StringReader};
pub use ser::{to_bytes, to_string, to_writer, to_writer_with_fields, SerializeError, Serializer};
pub use writer::{AsByteSlice, Writer};
mod de;
mod error;
mod reader;
mod ser;
mod writer;
pub type Result<T> = result::Result<T, error::Error>;
pub trait FixedWidth {
fn fields() -> Vec<Field>;
}
#[derive(Debug, Clone, PartialEq)]
pub enum Justify {
Left,
Right,
}
impl From<String> for Justify {
fn from(s: String) -> Self {
match s.to_lowercase().trim() {
"right" => Justify::Right,
_ => Justify::Left,
}
}
}
#[derive(Debug, Clone)]
pub struct Field {
pub name: Option<String>,
pub range: Range<usize>,
pub pad_with: char,
pub justify: Justify,
}
impl Default for Field {
fn default() -> Self {
Self {
name: None,
range: 0..0,
pad_with: ' ',
justify: Justify::Left,
}
}
}
impl Field {
pub fn width(&self) -> usize {
self.range.end - self.range.start
}
pub fn name<T: Into<String>>(mut self, val: Option<T>) -> Self {
self.name = val.map(|val| val.into());
self
}
pub fn range(mut self, val: Range<usize>) -> Self {
self.range = val;
self
}
pub fn pad_with(mut self, val: char) -> Self {
self.pad_with = val;
self
}
pub fn justify<T: Into<Justify>>(mut self, val: T) -> Self {
self.justify = val.into();
self
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum LineBreak {
None,
Newline,
CRLF,
}
impl LineBreak {
pub fn byte_width(&self) -> usize {
match self {
LineBreak::None => 0,
LineBreak::Newline => 1,
LineBreak::CRLF => 2,
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn line_break_byte_width() {
assert_eq!(LineBreak::None.byte_width(), 0);
assert_eq!(LineBreak::Newline.byte_width(), 1);
assert_eq!(LineBreak::CRLF.byte_width(), 2);
}
#[test]
fn field_building() {
let field = Field::default()
.range(0..10)
.name(Some("foo"))
.pad_with('a')
.justify(Justify::Right);
assert_eq!(field.range, 0..10);
assert_eq!(field.name.unwrap(), "foo");
assert_eq!(field.pad_with, 'a');
assert_eq!(field.justify, Justify::Right);
}
#[test]
fn field_width() {
let field = Field::default().range(5..23);
assert_eq!(field.width(), 18);
}
}