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 key = Data::accept(scanner)?.data;
118        OptionalWhitespaces::accept(scanner)?;
119        Ok(DeleteData { key })
120    }
121}
122
123// ----------------------------------------------------------------------------
124// Get Operation
125// ----------------------------------------------------------------------------
126
127/// A get operation.
128#[derive(Debug, PartialEq)]
129pub struct GetData<'a> {
130    /// The key to get.
131    pub key: &'a [u8],
132}
133
134impl<'a> Visitor<'a, u8> for GetData<'a> {
135    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
136        OptionalWhitespaces::accept(scanner)?;
137        let command = DataString::<&str>::accept(scanner)?.0;
138        if command != "get" {
139            return Err(ParseError::UnexpectedToken);
140        }
141        OptionalWhitespaces::accept(scanner)?;
142        let key = Data::accept(scanner)?.data;
143        OptionalWhitespaces::accept(scanner)?;
144        Ok(GetData { key })
145    }
146}
147
148// ----------------------------------------------------------------------------
149// Operation
150// ----------------------------------------------------------------------------
151
152/// A transactional operation.
153#[derive(Debug, PartialEq)]
154pub enum Operation<'a> {
155    /// A put operation.
156    Put(PutData<'a>),
157    /// A delete operation.
158    Delete(DeleteData<'a>),
159    /// A get operation.
160    Get(GetData<'a>),
161}
162
163impl<'a> Visitor<'a, u8> for Operation<'a> {
164    fn accept(scanner: &mut Scanner<'a, u8>) -> ParseResult<Self> {
165        let operation = Acceptor::new(scanner)
166            .try_or(Operation::Put)?
167            .try_or(Operation::Delete)?
168            .try_or(Operation::Get)?
169            .finish()
170            .ok_or(ParseError::UnexpectedToken)?;
171        Ok(operation)
172    }
173}
174
175#[cfg(test)]
176mod tests {
177    use crate::operation::GetData;
178    use elyze::visitor::Visitor;
179
180    #[test]
181    fn test_get_data() {
182        let data = b"get \"key\"";
183        let mut scanner = elyze::scanner::Scanner::new(data);
184        let result = super::GetData::accept(&mut scanner);
185        assert!(matches!(result, Ok(GetData { key: b"key" })));
186
187        let data = b"get key";
188        let mut scanner = elyze::scanner::Scanner::new(data);
189        let result = super::GetData::accept(&mut scanner);
190        assert!(matches!(result, Ok(GetData { key: b"key" })));
191    }
192
193    #[test]
194    fn test_delete_data() {
195        let data = b"del \"key\"";
196        let mut scanner = elyze::scanner::Scanner::new(data);
197        let result = super::DeleteData::accept(&mut scanner);
198        assert!(matches!(result, Ok(super::DeleteData { key: b"key" })));
199
200        let data = b"del key";
201        let mut scanner = elyze::scanner::Scanner::new(data);
202        let result = super::DeleteData::accept(&mut scanner);
203        assert!(matches!(result, Ok(super::DeleteData { key: b"key" })));
204    }
205
206    #[test]
207    fn test_put_data() {
208        let data = b"put \"key\" \"value\"";
209        let mut scanner = elyze::scanner::Scanner::new(data);
210        let result = super::PutData::accept(&mut scanner);
211        assert!(matches!(
212            result,
213            Ok(super::PutData {
214                key: b"key",
215                value: b"value"
216            })
217        ));
218
219        let data = b"put key value";
220        let mut scanner = elyze::scanner::Scanner::new(data);
221        let result = super::PutData::accept(&mut scanner);
222
223        if let Ok(result) = &result {
224            println!("{:?}", String::from_utf8_lossy(result.key));
225            println!("{:?}", String::from_utf8_lossy(result.value));
226        }
227
228        assert!(matches!(
229            result,
230            Ok(super::PutData {
231                key: b"key",
232                value: b"value"
233            })
234        ));
235    }
236}