python_json_read_adapter/
lib.rs1use std::io::{self, Read};
34use std::fmt;
35
36#[cfg(feature = "serde")]
37mod serde_impl;
38#[cfg(feature = "serde")]
39pub use self::serde_impl::*;
40
41#[derive(Copy, Clone)]
42enum State {
43 Initial,
44 Quoted,
45 QuotedEscape,
46 NaN0,
47 NaN1,
48 Infinity0,
49 Infinity1,
50 Infinity2,
51 Infinity3,
52 Infinity4,
53 Infinity5,
54 Infinity6,
55}
56
57pub struct JsonCompatRead<R> {
59 reader: R,
60 state: State,
61}
62
63impl<R: Read> fmt::Debug for JsonCompatRead<R> {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 f.debug_struct("JsonCompatRead").finish()
66 }
67}
68
69impl<R: Read> JsonCompatRead<R> {
70 pub fn wrap(reader: R) -> JsonCompatRead<R> {
72 JsonCompatRead { reader, state: State::Initial }
73 }
74}
75
76impl<R: Read> Read for JsonCompatRead<R> {
77 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
78 let read = io::Read::read(&mut self.reader, buf)?;
79 self.state = translate_slice_impl(&mut buf[..read], self.state);
80 Ok(read)
81 }
82}
83
84fn translate_slice_impl(bytes: &mut [u8], mut state: State) -> State {
85 for c in bytes {
86 let rv = match (state, *c) {
87 (State::Initial, b'N') => (State::NaN0, b'0'),
88 (State::NaN0, b'a') => (State::NaN1, b'.'),
89 (State::NaN1, b'N') => (State::Initial, b'0'),
90 (State::Initial, b'I') => (State::Infinity0, b'0'),
91 (State::Infinity0, b'n') => (State::Infinity1, b'.'),
92 (State::Infinity1, b'f') => (State::Infinity2, b'0'),
93 (State::Infinity2, b'i') => (State::Infinity3, b' '),
94 (State::Infinity3, b'n') => (State::Infinity4, b' '),
95 (State::Infinity4, b'i') => (State::Infinity5, b' '),
96 (State::Infinity5, b't') => (State::Infinity6, b' '),
97 (State::Infinity6, b'y') => (State::Initial, b' '),
98 (State::Initial, b'"') => (State::Quoted, b'"'),
99 (State::Quoted, b'\\') => (State::QuotedEscape, b'\\'),
100 (State::QuotedEscape, c) => (State::Quoted, c),
101 (State::Quoted, b'"') => (State::Initial, b'"'),
102 (state, c) => (state, c),
103 };
104 state = rv.0;
105 *c = rv.1;
106 }
107 state
108}
109
110pub fn translate_slice(bytes: &mut [u8]) {
115 translate_slice_impl(bytes, State::Initial);
116}
117
118#[test]
119fn test_reader_simple() {
120 let json = r#"{"nan":0.0,"inf":Infinity,"-inf":-Infinity}"#;
121 assert_eq!(json.len(), 43);
122 let mut rdr = JsonCompatRead::wrap(json.as_bytes());
123 let mut rv = String::new();
124 let read = rdr.read_to_string(&mut rv).unwrap();
125 assert_eq!(read, 43);
126 assert_eq!(rv, "{\"nan\":0.0,\"inf\":0.0 ,\"-inf\":-0.0 }");
127}
128
129#[test]
130fn test_reader_string() {
131 let json = r#"{"nan":"nan","Infinity":"-Infinity","other":NaN}"#;
132 assert_eq!(json.len(), 48);
133 let mut rdr = JsonCompatRead::wrap(json.as_bytes());
134 let mut rv = String::new();
135 let read = rdr.read_to_string(&mut rv).unwrap();
136 assert_eq!(read, 48);
137 assert_eq!(rv, "{\"nan\":\"nan\",\"Infinity\":\"-Infinity\",\"other\":0.0}");
138}
139
140#[test]
141fn test_reader_string_escaping() {
142 let json = r#""NaN\"NaN\"NaN""#;
143 assert_eq!(json.len(), 15);
144 let mut rdr = JsonCompatRead::wrap(json.as_bytes());
145 let mut rv = String::new();
146 let read = rdr.read_to_string(&mut rv).unwrap();
147 assert_eq!(read, 15);
148 assert_eq!(rv, r#""NaN\"NaN\"NaN""#);
149}
150
151#[test]
152fn test_translate_slice() {
153 let mut json = br#"{"nan":"nan","Infinity":"-Infinity","other":NaN}"#.to_vec();
154 translate_slice(&mut json[..]);
155 assert_eq!(&json[..], &b"{\"nan\":\"nan\",\"Infinity\":\"-Infinity\",\"other\":0.0}"[..]);
156}