batchcensor/
transcript.rs1use crate::{Range, Replace};
2
3#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
5pub struct Transcript {
6 pub text: String,
7 pub replace: Vec<Replace>,
8 pub missing: Vec<String>,
10}
11
12impl Transcript {
13 pub fn parse(text: &str) -> Result<Transcript, failure::Error> {
14 let mut it = text.chars();
15
16 let mut replace = Vec::new();
17 let mut missing = Vec::new();
18
19 while let Some(c) = it.next() {
20 match c {
21 '[' => {
22 let (word, range) = Self::parse_replace(&mut it)?;
23
24 match range {
25 Some(range) => {
26 replace.push(Replace { word, range });
27 }
28 None => {
29 missing.push(word);
30 }
31 }
32 }
33 _ => {}
34 }
35 }
36
37 Ok(Transcript {
38 text: text.to_string(),
39 replace,
40 missing,
41 })
42 }
43
44 pub fn parse_replace(
46 it: &mut impl Iterator<Item = char>,
47 ) -> Result<(String, Option<Range>), failure::Error> {
48 let mut word = None;
49 let mut buffer = String::new();
50
51 while let Some(c) = it.next() {
52 match c {
53 ']' => {
54 word = Some(buffer);
55 break;
56 }
57 c => {
58 buffer.push(c);
59 }
60 }
61 }
62
63 let word = match word {
64 Some(word) => word,
65 None => {
66 failure::bail!("missing word");
67 }
68 };
69
70 let open = it.next();
71
72 if open != Some('{') {
73 return Ok((word, None));
74 }
75
76 let mut range = None;
77 let mut buffer = String::new();
78
79 while let Some(c) = it.next() {
80 match c {
81 '}' => {
82 range = Some(buffer);
83 break;
84 }
85 c => {
86 buffer.push(c);
87 }
88 }
89 }
90
91 let range = match range {
92 Some(range) => range,
93 None => {
94 failure::bail!("missing range");
95 }
96 };
97
98 let range = Range::parse(&range).ok_or_else(|| failure::format_err!("bad range"))?;
99
100 Ok((word, Some(range)))
101 }
102}
103
104impl<'de> serde::Deserialize<'de> for Transcript {
105 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
106 where
107 D: serde::Deserializer<'de>,
108 {
109 let s: String = String::deserialize(deserializer)?;
110 Transcript::parse(&s).map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
111 }
112}
113
114impl serde::Serialize for Transcript {
115 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
116 where
117 S: serde::Serializer,
118 {
119 serializer.serialize_str(&self.text)
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::Transcript;
126 use crate::{Range, Replace};
127
128 #[test]
129 pub fn test() -> Result<(), failure::Error> {
130 let transcript = Transcript::parse("foo [bar]{01.123-$} [baz]{^-$}")?;
131
132 let a = Replace {
133 word: String::from("bar"),
134 range: Range::parse("01.123-$").expect("valid range"),
135 };
136
137 assert_eq!(a, transcript.replace[0]);
138
139 let b = Replace {
140 word: String::from("baz"),
141 range: Range::parse("^-$").expect("valid range"),
142 };
143
144 assert_eq!(b, transcript.replace[1]);
145 Ok(())
146 }
147}