cardparse/
lib.rs

1#[macro_use] extern crate failure;
2pub use cardparse_derive::*;
3
4#[derive(Debug,Fail)]
5pub enum ParseError {
6    #[fail(display = "Field '{}' could not be parsed from '{}' because the source was too short", field, source_line)]
7    SourceTooShort{field: String, start: usize, end: Option<usize>, line: usize, source_line: String},
8}
9
10/// The `CardParse` trait should be derived for structs as `#[derive(CardParse)]`
11/// struct fields are then tagged with attributes like `#[location(line=2,start=6,end=24)]`.
12/// **Values to the field attributes are by index not offset (start at one) and
13/// always inclusive.**
14/// 
15/// ```
16/// use cardparse::prelude::*;
17/// #[derive(CardParse,Debug)]
18/// struct FirstNoEnd {
19///     #[location(line=1,start=1)]
20///     field_one: String,
21///     #[location(line=2,start=6,max=24)]
22///     field_two: String,
23///     #[location(line=2,start=1,end=5)]
24///     field_three: String,
25/// }
26/// ```
27/// 
28/// CardpParse protects against overlapping attributes at compile time
29/// 
30/// ```compile_fail
31/// use cardparse::prelude::*;
32/// #[derive(CardParse,Debug)]
33/// struct FirstNoEnd {
34///     #[location(line=1,start=1.end=4)]
35///     field_one: String,
36///     #[location(line=1,start=2,end=6)]
37///     field_two: String,
38/// }
39/// ```
40
41pub trait CardParse {
42    fn cardparse(s: &str) -> Result<Self, ParseError> where Self: Sized;
43}
44
45pub mod prelude {
46    pub use crate::{CardParse, ParseError};
47}
48
49#[cfg(test)]
50mod test {
51    use super::prelude::*;
52
53    #[derive(CardParse,Debug)]
54    struct Simple {
55        #[location(line=1,start=1,end=12)]
56        field_one: String,
57        #[location(line=2,start=6,end=12)]
58        field_two: String,
59    }
60
61    #[derive(CardParse,Debug)]
62    struct FirstNoEnd {
63        #[location(line=1,start=1)]
64        field_one: String,
65        #[location(line=2,start=6,max=24)]
66        field_two: String,
67        #[location(line=2,start=1,end=5)]
68        field_three: String,
69    }
70
71    #[test]
72    fn simple_test() {
73        let simple = Simple::cardparse("Some String it is\nAnd also some other string");
74        assert!(simple.is_ok());
75        let simple = simple.unwrap();
76        assert_eq!(simple.field_one, "Some String ");
77        assert_eq!(simple.field_two, "lso som");
78        
79    }
80
81    #[test]
82    fn first_no_end_test() {
83        let first_no_end = FirstNoEnd::cardparse("Some String it is\nAnd also some other string");
84        assert!(first_no_end.is_ok());
85        let first_no_end = first_no_end.unwrap();
86        assert_eq!(first_no_end.field_one, "Some String it is");
87        assert_eq!(first_no_end.field_two, "lso some other stri");
88        assert_eq!(first_no_end.field_three, "And a");
89    }
90
91     #[test]
92    fn first_no_end_failure_test() {
93        let first_no_end = FirstNoEnd::cardparse("Some String it is\nAnd");
94        assert!(first_no_end.is_err());
95        assert_eq!(
96            format!("{}", first_no_end.unwrap_err()), 
97            "Field 'field_two' could not be parsed from 'Some String it is\nAnd' because the source was too short"
98        );
99    }
100}