1#![allow(clippy::unneeded_field_pattern)]
4
5use sawp::error::{Error, ErrorKind, Result};
6use sawp::parser::{Direction, Parse};
7use sawp::probe::Probe;
8use sawp::protocol::Protocol;
9use serde_json::{Deserializer, Value};
10
11#[derive(Debug)]
12pub struct Json {}
13
14#[derive(Debug, PartialEq, Eq)]
15pub struct Message {
16 pub value: Value,
17}
18
19impl Message {
20 pub fn new(value: Value) -> Self {
21 Self { value }
22 }
23}
24
25impl Protocol<'_> for Json {
26 type Message = Message;
27
28 fn name() -> &'static str {
29 "json"
30 }
31}
32
33impl<'a> Parse<'a> for Json {
34 fn parse(
35 &self,
36 input: &'a [u8],
37 _direction: Direction,
38 ) -> Result<(&'a [u8], Option<Self::Message>)> {
39 let mut stream = Deserializer::from_slice(input).into_iter::<Value>();
40
41 match stream.next() {
42 Some(Ok(value)) => Ok((&input[stream.byte_offset()..], Some(Message::new(value)))),
43 _ => Err(Error::new(ErrorKind::InvalidData)),
44 }
45 }
46}
47
48impl<'a> Probe<'a> for Json {}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use rstest::rstest;
54 use sawp::error::{Error, ErrorKind, Result};
55 use sawp::probe::Status;
56 use serde_json::json;
57
58 #[rstest(
59 input,
60 expected,
61 case::empty(b"", Err(Error::new(ErrorKind::InvalidData))),
62 case::singlequote(b"''", Err(Error::new(ErrorKind::InvalidData))),
63 case::incomplete(b"{\"a\":", Err(Error::new(ErrorKind::InvalidData))),
64
65 case::number(b"1234", Ok((0, Some(Message::new(json!(1234)))))),
67 case::null(b"null", Ok((0, Some(Message::new(json!(null)))))),
68 case::bool_true(b"true", Ok((0, Some(Message::new(json!(true)))))),
69 case::bool_false(b"false", Ok((0, Some(Message::new(json!(false)))))),
70 case::empty_obj(b"{}", Ok((0, Some(Message::new(json!({})))))),
71 case::empty_list(b"[]", Ok((0, Some(Message::new(json!([])))))),
72 case::empty_string(b"\"\"", Ok((0, Some(Message::new(json!("")))))),
73 case::object(b"{\"a\":\"b\"}", Ok((0, Some(Message::new(json!({"a": "b"})))))),
74 case::list(b"[\"a\", \"b\"]", Ok((0, Some(Message::new(json!(["a", "b"])))))),
75 case::whitespace(b"\n\t{\n\r\n\"a\": \t\"b\"\n}", Ok((0, Some(Message::new(json!({"a": "b"})))))),
76 case::multi(b"{}[1]", Ok((3, Some(Message::new(json!({})))))),
77 )]
78 fn test_parse(input: &[u8], expected: Result<(usize, Option<<Json as Protocol>::Message>)>) {
79 let json = Json {};
80 assert_eq!(
81 expected,
82 json.parse(input, Direction::Unknown)
83 .map(|(left, msg)| (left.len(), msg)),
84 );
85 }
86
87 #[rstest(
88 input,
89 expected,
90 case::empty(b"", Status::Unrecognized),
91 case::incomplete(b"{\"a\":", Status::Unrecognized),
92 case::number(b"1234", Status::Recognized)
93 )]
94 fn test_probe(input: &[u8], expected: Status) {
95 let json = Json {};
96 assert_eq!(expected, json.probe(input, Direction::Unknown));
97 }
98}