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}