etcd_txn_parser/
operation.rs

1//! Transactional operations
2
3use elyze::acceptor::Acceptor;
4use elyze::bytes::components::groups::GroupKind;
5use elyze::bytes::primitives::string::DataString;
6use elyze::bytes::primitives::whitespace::OptionalWhitespaces;
7use elyze::bytes::token::Token;
8use elyze::errors::{ParseError, ParseResult};
9use elyze::peek::{peek, UntilEnd};
10use elyze::peeker::Peeker;
11use elyze::scanner::Scanner;
12use elyze::visitor::Visitor;
13
14// ----------------------------------------------------------------------------
15// QuotedString
16// ----------------------------------------------------------------------------
17
18struct QuotedString<'a>(&'a [u8]);
19
20impl<'a> Visitor<'a, u8> for QuotedString<'a> {
21    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
22        let peeked = peek(GroupKind::DoubleQuotes, scanner)?.ok_or(ParseError::UnexpectedToken)?;
23        scanner.bump_by(peeked.end_slice);
24        Ok(QuotedString(peeked.peeked_slice()))
25    }
26}
27
28//----------------------------------------------------------------------------
29// UnquotedString
30//----------------------------------------------------------------------------
31
32struct UnquotedString<'a>(&'a [u8]);
33
34impl<'a> Visitor<'a, u8> for UnquotedString<'a> {
35    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
36        let peeked = {
37            let peeked = Peeker::new(scanner)
38                .add_peekable(Token::Whitespace)
39                .add_peekable(UntilEnd::default())
40                .peek()?
41                .ok_or(ParseError::UnexpectedToken)?;
42            peeked
43        };
44
45        scanner.bump_by(peeked.end_slice);
46        Ok(UnquotedString(peeked.peeked_slice()))
47    }
48}
49
50//----------------------------------------------------------------------------
51// Data
52//----------------------------------------------------------------------------
53
54pub struct Data<'a> {
55    pub(crate) data: &'a [u8],
56}
57
58impl<'a> Visitor<'a, u8> for Data<'a> {
59    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
60        let accepted = Acceptor::new(scanner)
61            .try_or(|x: QuotedString| x.0)?
62            .try_or(|x: UnquotedString| x.0)?
63            .finish()
64            .ok_or(ParseError::UnexpectedToken)?;
65        Ok(Data { data: accepted })
66    }
67}
68
69// ----------------------------------------------------------------------------
70// Put Operation
71// ----------------------------------------------------------------------------
72
73/// A put operation.
74#[derive(Debug, PartialEq)]
75pub struct PutData<'a> {
76    /// The key to put.
77    pub key: &'a [u8],
78    /// The value to put.
79    pub value: &'a [u8],
80}
81
82impl<'a> Visitor<'a, u8> for PutData<'a> {
83    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
84        OptionalWhitespaces::accept(scanner)?;
85        let command = DataString::<&str>::accept(scanner)?.0;
86        if command != "put" {
87            return Err(ParseError::UnexpectedToken);
88        }
89        OptionalWhitespaces::accept(scanner)?;
90        let key = Data::accept(scanner)?.data;
91        OptionalWhitespaces::accept(scanner)?;
92        let value = Data::accept(scanner)?.data;
93        OptionalWhitespaces::accept(scanner)?;
94        Ok(PutData { key, value })
95    }
96}
97
98// ----------------------------------------------------------------------------
99// Delete Operation
100// ----------------------------------------------------------------------------
101
102/// A delete operation.
103#[derive(Debug, PartialEq)]
104pub struct DeleteData<'a> {
105    /// The key to delete.
106    pub key: &'a [u8],
107}
108
109impl<'a> Visitor<'a, u8> for DeleteData<'a> {
110    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
111        OptionalWhitespaces::accept(scanner)?;
112        let command = DataString::<&str>::accept(scanner)?.0;
113        if command != "del" {
114            return Err(ParseError::UnexpectedToken);
115        }
116        OptionalWhitespaces::accept(scanner)?;
117        let until_ln = Peeker::new(scanner)
118            .add_peekable(Token::Ln)
119            .add_peekable(UntilEnd::default())
120            .peek()?
121            .ok_or(ParseError::UnexpectedToken)?;
122        let mut scanner_until_ln = Scanner::new(until_ln.peeked_slice());
123
124        let key = Data::accept(&mut scanner_until_ln)?.data;
125        scanner.bump_by(scanner_until_ln.current_position());
126        OptionalWhitespaces::accept(scanner)?;
127
128        Ok(DeleteData { key })
129    }
130}
131
132// ----------------------------------------------------------------------------
133// Get Operation
134// ----------------------------------------------------------------------------
135
136/// A get operation.
137#[derive(Debug, PartialEq)]
138pub struct GetData<'a> {
139    /// The key to get.
140    pub key: &'a [u8],
141}
142
143impl<'a> Visitor<'a, u8> for GetData<'a> {
144    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
145        OptionalWhitespaces::accept(scanner)?;
146        let command = DataString::<&str>::accept(scanner)?.0;
147        if command != "get" {
148            return Err(ParseError::UnexpectedToken);
149        }
150
151        OptionalWhitespaces::accept(scanner)?;
152
153        let until_ln = Peeker::new(scanner)
154            .add_peekable(Token::Ln)
155            .add_peekable(UntilEnd::default())
156            .peek()?
157            .ok_or(ParseError::UnexpectedToken)?;
158        let mut scanner_until_ln = Scanner::new(until_ln.peeked_slice());
159
160        let key = Data::accept(&mut scanner_until_ln)?.data;
161        scanner.bump_by(scanner_until_ln.current_position());
162        OptionalWhitespaces::accept(scanner)?;
163
164        Ok(GetData { key })
165    }
166}
167
168// ----------------------------------------------------------------------------
169// Operation
170// ----------------------------------------------------------------------------
171
172/// A transactional operation.
173#[derive(Debug, PartialEq)]
174pub enum Operation<'a> {
175    /// A put operation.
176    Put(PutData<'a>),
177    /// A delete operation.
178    Delete(DeleteData<'a>),
179    /// A get operation.
180    Get(GetData<'a>),
181}
182
183impl<'a> Visitor<'a, u8> for Operation<'a> {
184    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
185        let operation = Acceptor::new(scanner)
186            .try_or(Operation::Put)?
187            .try_or(Operation::Delete)?
188            .try_or(Operation::Get)?
189            .finish()
190            .ok_or(ParseError::UnexpectedToken)?;
191        Ok(operation)
192    }
193}
194
195#[cfg(test)]
196mod tests {
197    use crate::operation::GetData;
198    use elyze::visitor::Visitor;
199
200    #[test]
201    fn test_get_data() {
202        let data = b"get \"key\"";
203        let mut scanner = elyze::scanner::Scanner::new(data);
204        let result = super::GetData::accept(&mut scanner);
205        assert!(matches!(result, Ok(GetData { key: b"key" })));
206
207        let data = b"get key";
208        let mut scanner = elyze::scanner::Scanner::new(data);
209        let result = super::GetData::accept(&mut scanner);
210        assert!(matches!(result, Ok(GetData { key: b"key" })));
211    }
212
213    #[test]
214    fn test_delete_data() {
215        let data = b"del \"key\"";
216        let mut scanner = elyze::scanner::Scanner::new(data);
217        let result = super::DeleteData::accept(&mut scanner);
218        assert!(matches!(result, Ok(super::DeleteData { key: b"key" })));
219
220        let data = b"del key";
221        let mut scanner = elyze::scanner::Scanner::new(data);
222        let result = super::DeleteData::accept(&mut scanner);
223        assert!(matches!(result, Ok(super::DeleteData { key: b"key" })));
224    }
225
226    #[test]
227    fn test_put_data() {
228        let data = b"put \"key\" \"value\"";
229        let mut scanner = elyze::scanner::Scanner::new(data);
230        let result = super::PutData::accept(&mut scanner);
231        assert!(matches!(
232            result,
233            Ok(super::PutData {
234                key: b"key",
235                value: b"value"
236            })
237        ));
238
239        let data = b"put key value";
240        let mut scanner = elyze::scanner::Scanner::new(data);
241        let result = super::PutData::accept(&mut scanner);
242
243        if let Ok(result) = &result {
244            println!("{:?}", String::from_utf8_lossy(result.key));
245            println!("{:?}", String::from_utf8_lossy(result.value));
246        }
247
248        assert!(matches!(
249            result,
250            Ok(super::PutData {
251                key: b"key",
252                value: b"value"
253            })
254        ));
255    }
256}