sozu_command_lib/
parser.rs1use nom::{
2 IResult,
3 bytes::streaming::is_not,
4 character::complete::char,
5 combinator::map_res,
6 error::{ErrorKind, FromExternalError},
7 multi::many0,
8 sequence::terminated,
9};
10
11#[derive(Debug)]
12#[allow(dead_code)]
13pub struct ParseError {
14 kind: ErrorKind,
15 serde_json_error: Option<serde_json::Error>,
16}
17
18impl FromExternalError<&[u8], serde_json::Error> for ParseError {
19 fn from_external_error(
20 _input: &[u8],
21 kind: ErrorKind,
22 serde_json_error: serde_json::Error,
23 ) -> Self {
24 Self {
26 kind,
27 serde_json_error: Some(serde_json_error),
28 }
29 }
30}
31
32impl nom::error::ParseError<&[u8]> for ParseError {
33 fn from_error_kind(_input: &[u8], kind: ErrorKind) -> Self {
34 Self {
37 kind,
38 serde_json_error: None,
39 }
40 }
41
42 fn append(_input: &[u8], _kind: ErrorKind, other: Self) -> Self {
43 other
44 }
45}
46
47pub fn parse_one_request<'a, T>(input: &'a [u8]) -> Result<T, ParseError>
49where
50 T: serde::de::Deserialize<'a>,
51{
52 serde_json::from_slice::<T>(input).map_err(|serde_error| {
53 ParseError::from_external_error(input, ErrorKind::MapRes, serde_error)
54 })
55}
56
57pub fn parse_several_requests<'a, T>(input: &'a [u8]) -> IResult<&'a [u8], Vec<T>>
58where
59 T: serde::de::Deserialize<'a>,
60{
61 many0(nom::combinator::complete(terminated(
63 map_res(is_not("\0"), parse_one_request),
64 char('\0'),
65 )))(input)
66}
67
68#[cfg(test)]
69mod test {
70 use super::*;
71 use crate::proto::command::{Status, SubscribeEvents, WorkerRequest, request::RequestType};
72
73 #[test]
74 fn parse_one_worker_request() {
75 let worker_request = WorkerRequest::new(
76 "Some request".to_string(),
77 RequestType::Status(Status {}).into(),
78 );
79
80 let string = serde_json::ser::to_string(&worker_request).unwrap();
81
82 println!("string to parse: {string}");
83
84 let bytes = &string.as_bytes();
85
86 assert_eq!(
87 parse_one_request::<WorkerRequest>(bytes).unwrap(),
88 worker_request
89 )
90 }
91
92 #[test]
93 fn parse_several_worker_requests() {
94 let requests = vec![
95 WorkerRequest::new(
96 "Some request".to_string(),
97 RequestType::SaveState("/some/path".to_string()).into(),
98 ),
99 WorkerRequest::new(
100 "Some other request".to_string(),
101 RequestType::SubscribeEvents(SubscribeEvents {}).into(),
102 ),
103 WorkerRequest::new(
104 "Yet another request".to_string(),
105 RequestType::Status(Status {}).into(),
106 ),
107 ];
108
109 let mut serialized_requests = String::new();
110
111 for request in requests.iter() {
112 serialized_requests += &serde_json::ser::to_string(&request).unwrap();
113 serialized_requests.push('\0');
114 }
115
116 let bytes_to_parse = &serialized_requests.as_bytes();
117
118 let parsed_requests = parse_several_requests(bytes_to_parse).unwrap();
119
120 println!("parsed commands: {parsed_requests:?}");
121
122 let empty_vec: Vec<u8> = vec![];
123
124 assert_eq!(parsed_requests, (&empty_vec[..], requests))
125 }
126}