tiny_v1/
lib.rs

1mod error;
2
3use crate::error::TinyV1Error;
4
5pub struct Header<'a> {
6    pub namespace_a: &'a str,
7    pub namespace_b: &'a str,
8    pub namespaces: Vec<&'a str>,
9}
10
11impl<'a> Header<'a> {
12    fn from_str<'b>(s: &'a str) -> Result<Self, TinyV1Error<'b>> {
13        let mut header = s.split('\t');
14        if header.next().ok_or(TinyV1Error("Empty Header"))? != "v1" {
15            return Err(TinyV1Error("Wrong Format"));
16        }
17
18        let namespace_a = header.next().ok_or(TinyV1Error("Namespace a not found"))?;
19        let namespace_b = header.next().ok_or(TinyV1Error("Namespace b not found"))?;
20        let namespaces: Vec<&'a str> = header.collect();
21        Ok(Self {
22            namespace_a,
23            namespace_b,
24            namespaces,
25        })
26    }
27}
28
29pub struct Content<'a> {
30    pub mapping_entries: Vec<MappingEntry<'a>>,
31}
32
33pub enum MappingEntry<'a> {
34    CLASS {
35        class_names: Vec<&'a str>,
36    },
37    FIELD {
38        parent_class_name_a: &'a str,
39        field_desc_a: &'a str,
40        field_name_a: &'a str,
41        field_name_b: &'a str,
42        extra_ns_field_names: Vec<&'a str>,
43    },
44    METHOD {
45        parent_class_name_a: &'a str,
46        method_desc_a: &'a str,
47        method_name_a: &'a str,
48        method_name_b: &'a str,
49        extra_ns_method_names: Vec<&'a str>,
50    },
51}
52
53impl<'a> MappingEntry<'a> {
54    fn from_str<'b>(s: &'a str) -> Result<Self, TinyV1Error<'b>> {
55        let mut mapping_entry = s.split('\t');
56        match mapping_entry.next() {
57            Some("CLASS") => {
58                let class_names: Vec<_> = mapping_entry.collect();
59                Ok(Self::CLASS { class_names })
60            }
61            Some("FIELD") => {
62                let parent_class_name_a = mapping_entry
63                    .next()
64                    .ok_or(TinyV1Error("Parent class not found"))?;
65                let field_desc_a = mapping_entry
66                    .next()
67                    .ok_or(TinyV1Error("Method desc not found"))?;
68                let field_name_a = mapping_entry
69                    .next()
70                    .ok_or(TinyV1Error("Method name a not found"))?;
71                let field_name_b = mapping_entry
72                    .next()
73                    .ok_or(TinyV1Error("Method name b not found"))?;
74                let extra_ns_field_names: Vec<_> = mapping_entry.collect();
75                Ok(Self::FIELD {
76                    parent_class_name_a,
77                    field_desc_a,
78                    field_name_a,
79                    field_name_b,
80                    extra_ns_field_names,
81                })
82            }
83            Some("METHOD") => {
84                let parent_class_name_a = mapping_entry
85                    .next()
86                    .ok_or(TinyV1Error("Parent class not found"))?;
87                let method_desc_a = mapping_entry
88                    .next()
89                    .ok_or(TinyV1Error("Method desc not found"))?;
90                let method_name_a = mapping_entry
91                    .next()
92                    .ok_or(TinyV1Error("Method name a not found"))?;
93                let method_name_b = mapping_entry
94                    .next()
95                    .ok_or(TinyV1Error("Method name b not found"))?;
96                let extra_ns_method_names: Vec<_> = mapping_entry.collect();
97                Ok(Self::METHOD {
98                    parent_class_name_a,
99                    method_desc_a,
100                    method_name_a,
101                    method_name_b,
102                    extra_ns_method_names,
103                })
104            }
105            None => Err(TinyV1Error("Line can not be empty")),
106            _ => Err(TinyV1Error("Invalid Identifier")),
107        }
108    }
109}
110
111impl<'a> Content<'a> {
112    fn from_str<'b>(s: &'a str) -> Result<Self, TinyV1Error<'b>> {
113        let mapping_entries: Result<Vec<_>, _> = s
114            .lines()
115            .map(|mapping_entry| MappingEntry::from_str(mapping_entry))
116            .collect();
117        let mapping_entries = mapping_entries?;
118        Ok(Self { mapping_entries })
119    }
120}
121
122pub struct File<'a> {
123    pub header: Header<'a>,
124    pub content: Content<'a>,
125}
126
127impl<'a> File<'a> {
128    pub fn from_str<'b>(s: &'a str) -> Result<Self, TinyV1Error<'b>> {
129        let (header_str, content_str) = s
130            .split_once('\n')
131            .ok_or(TinyV1Error("There is no line break"))?;
132        let header = Header::from_str(header_str)?;
133        let content = Content::from_str(content_str)?;
134        Ok(Self { header, content })
135    }
136}
137
138pub fn from_str<'b>(s: &str) -> Result<File<'_>, TinyV1Error<'b>> {
139    File::from_str(s)
140}