etcd_txn_parser/
operation.rs

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