core_json_embedded_io/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3#![deny(missing_docs)]
4#![cfg_attr(not(test), no_std)]
5
6use core::{fmt, cell::RefCell};
7use core_json::BytesLike;
8use embedded_io::{ErrorType, ReadExactError, Read, SeekFrom, Seek};
9
10/// An error from an adapter.
11pub enum Error<E: ErrorType<Error: Copy>> {
12  /// An internal error occurred.
13  InternalError,
14  /// The adapter was bounded and the bound has been reached.
15  Bounded,
16  /// The underlying reader raised an error.
17  Reader(E::Error),
18  /// `read_exact` raised an error.
19  ReadExact(ReadExactError<E::Error>),
20}
21impl<E: ErrorType<Error: Copy>> Clone for Error<E> {
22  fn clone(&self) -> Self {
23    *self
24  }
25}
26impl<E: ErrorType<Error: Copy>> Copy for Error<E> {}
27impl<E: ErrorType<Error: Copy>> fmt::Debug for Error<E> {
28  fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
29    match self {
30      Self::InternalError => fmt.debug_struct("Error::InternalError").finish(),
31      Self::Bounded => fmt.debug_struct("Error::Bounded").finish(),
32      Self::Reader(e) => fmt.debug_struct("Error::Reader").field("0", &e).finish(),
33      Self::ReadExact(e) => fmt.debug_struct("Error::ReadExact").field("0", &e).finish(),
34    }
35  }
36}
37
38/// An adapter from [`embedded_io::Read`] to [`core_json::BytesLike`].
39///
40/// [`SeekAdapter`] SHOULD be preferred as it'll call `Clone` less frequently.
41pub struct ReadAdapter<R: Clone + Read<Error: Copy>> {
42  reader: R,
43  bound: Option<usize>,
44}
45impl<R: Clone + Read<Error: Copy>> fmt::Debug for ReadAdapter<R> {
46  fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
47    fmt.debug_struct("ReadAdapter").finish_non_exhaustive()
48  }
49}
50
51impl<R: Clone + Read<Error: Copy>> From<R> for ReadAdapter<R> {
52  fn from(reader: R) -> Self {
53    Self { reader, bound: None }
54  }
55}
56
57impl<R: Clone + Read<Error: Copy>> BytesLike<'static> for ReadAdapter<R> {
58  type Error = Error<R>;
59
60  type ExternallyTrackedLength = usize;
61
62  fn len(&self, len: Self::ExternallyTrackedLength) -> usize {
63    len
64  }
65
66  fn peek(&self, mut i: usize) -> Result<u8, Self::Error> {
67    let mut peek = self.reader.clone();
68
69    // Seek ahead
70    let mut buf = [0; 8];
71    while i > 0 {
72      let this_iter = i.min(8);
73      peek.read_exact(&mut buf[.. this_iter]).map_err(Error::ReadExact)?;
74      i -= this_iter;
75    }
76
77    // Peek
78    peek.read_exact(&mut buf[.. 1]).map_err(Error::ReadExact)?;
79    Ok(buf[0])
80  }
81
82  fn read_bytes(
83    &mut self,
84    mut bytes: usize,
85  ) -> Result<(Self::ExternallyTrackedLength, Self), Self::Error> {
86    let result = (bytes, Self { reader: self.reader.clone(), bound: Some(bytes) });
87
88    // Skip ahead
89    let mut buf = [0; 8];
90    while bytes > 0 {
91      let this_iter = bytes.min(8);
92      self.reader.read_exact(&mut buf[.. this_iter]).map_err(Error::ReadExact)?;
93      bytes -= this_iter;
94    }
95
96    Ok(result)
97  }
98
99  fn read_into_slice(&mut self, slice: &mut [u8]) -> Result<(), Self::Error> {
100    if let Some(bound) = self.bound.as_mut() {
101      *bound = bound.checked_sub(slice.len()).ok_or(Error::Bounded)?;
102    }
103    self.reader.read_exact(slice).map_err(Error::ReadExact)
104  }
105}
106
107/// An adapter from [`embedded_io::Seek`] to [`core_json::BytesLike`].
108///
109/// This will `Clone` the underlying reader less frequently than `ReadAdapter` due to being able
110/// to use `Seek` to implement `peek`.
111pub struct SeekAdapter<R: Clone + Read<Error: Copy> + Seek> {
112  // This is used for interior mutability within `peek`
113  reader: RefCell<R>,
114  bound: Option<usize>,
115}
116impl<R: Clone + Read<Error: Copy> + Seek> fmt::Debug for SeekAdapter<R> {
117  fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
118    fmt.debug_struct("SeekAdapter").finish_non_exhaustive()
119  }
120}
121
122impl<R: Clone + Read<Error: Copy> + Seek> From<R> for SeekAdapter<R> {
123  fn from(reader: R) -> Self {
124    Self { reader: RefCell::new(reader), bound: None }
125  }
126}
127
128impl<R: Clone + Read<Error: Copy> + Seek> BytesLike<'static> for SeekAdapter<R> {
129  type Error = Error<R>;
130
131  type ExternallyTrackedLength = usize;
132
133  fn len(&self, len: Self::ExternallyTrackedLength) -> usize {
134    len
135  }
136
137  fn peek(&self, i: usize) -> Result<u8, Self::Error> {
138    let i = i64::try_from(i).map_err(|_| Error::InternalError)?;
139
140    let mut reader = self.reader.borrow_mut();
141
142    // Seek ahead
143    reader.seek_relative(i).map_err(Error::Reader)?;
144
145    let mut buf = [0];
146    reader.read_exact(&mut buf).map_err(Error::ReadExact)?;
147
148    // Restore to the original position
149    reader.seek_relative((-i) - 1).map_err(Error::Reader)?;
150
151    Ok(buf[0])
152  }
153
154  fn read_bytes(
155    &mut self,
156    bytes: usize,
157  ) -> Result<(Self::ExternallyTrackedLength, Self), Self::Error> {
158    let result =
159      (bytes, Self { reader: RefCell::new(self.reader.borrow().clone()), bound: Some(bytes) });
160
161    self
162      .reader
163      .borrow_mut()
164      .seek_relative(i64::try_from(bytes).map_err(|_| Error::InternalError)?)
165      .map_err(Error::Reader)?;
166
167    Ok(result)
168  }
169
170  fn read_into_slice(&mut self, slice: &mut [u8]) -> Result<(), Self::Error> {
171    if let Some(bound) = self.bound.as_mut() {
172      *bound = bound.checked_sub(slice.len()).ok_or(Error::Bounded)?;
173    }
174    self.reader.get_mut().read_exact(slice).map_err(Error::ReadExact)
175  }
176}
177
178/// A wrapper which allows cheaply and safely cloning implementors of `Seek`.
179///
180/// This defers ownership of the reader for solely ownership of a reference to it. Each instance
181/// individually tracks their position within the reader, resetting the seek head on each
182/// invocation (as required for each instance to maintain a consistent view).
183pub struct ClonableSeek<'reader, R: Read<Error: Copy> + Seek> {
184  reader: &'reader RefCell<R>,
185  pos: u64,
186}
187
188impl<'reader, R: Read<Error: Copy> + Seek> TryFrom<&'reader RefCell<R>>
189  for ClonableSeek<'reader, R>
190{
191  type Error = R::Error;
192  fn try_from(reader: &'reader RefCell<R>) -> Result<Self, R::Error> {
193    let pos = reader.borrow_mut().stream_position()?;
194    Ok(Self { reader, pos })
195  }
196}
197
198impl<'reader, R: Read<Error: Copy> + Seek> Clone for ClonableSeek<'reader, R> {
199  fn clone(&self) -> Self {
200    Self { reader: self.reader, pos: self.pos }
201  }
202}
203
204impl<'reader, R: Read<Error: Copy> + Seek> ErrorType for ClonableSeek<'reader, R> {
205  type Error = R::Error;
206}
207impl<'reader, R: Read<Error: Copy> + Seek> Read for ClonableSeek<'reader, R> {
208  fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
209    let mut reader = self.reader.borrow_mut();
210    reader.seek(SeekFrom::Start(self.pos))?;
211    let res = reader.read(buf)?;
212    self.pos = reader.stream_position()?;
213    Ok(res)
214  }
215}
216impl<'reader, R: Read<Error: Copy> + Seek> Seek for ClonableSeek<'reader, R> {
217  fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
218    let mut reader = self.reader.borrow_mut();
219    reader.seek(SeekFrom::Start(self.pos))?;
220    self.pos = reader.seek(pos)?;
221    Ok(self.pos)
222  }
223}
224
225#[test]
226fn test_read() {
227  const SERIALIZATION: &[u8] = br#"{ "hello": "goodbye" }"#;
228
229  let reader = ReadAdapter::from(SERIALIZATION);
230  let mut deserializer =
231    core_json::Deserializer::<_, core_json::ConstStack<128>>::new(reader).unwrap();
232  let value = deserializer.value().unwrap();
233  let mut fields = value.fields().unwrap();
234  let field = fields.next().unwrap();
235  let (key, value) = field.unwrap();
236  assert_eq!(key.collect::<Result<String, _>>().unwrap(), "hello");
237  assert_eq!(value.to_str().unwrap().collect::<Result<String, _>>().unwrap(), "goodbye");
238  assert!(fields.next().is_none());
239}
240
241#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap)]
242#[test]
243fn test_seek() {
244  const SERIALIZATION: &[u8] = br#"{ "hello": "goodbye" }"#;
245
246  struct SerializationSeek(usize);
247  impl ErrorType for SerializationSeek {
248    type Error = <&'static [u8] as ErrorType>::Error;
249  }
250  impl Read for SerializationSeek {
251    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
252      let len = (&SERIALIZATION[self.0 ..]).read(buf)?;
253      self.0 += len;
254      Ok(len)
255    }
256  }
257  impl Seek for SerializationSeek {
258    fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
259      match pos {
260        SeekFrom::Start(pos) => self.0 = pos as usize,
261        SeekFrom::End(offset) => self.0 = ((SERIALIZATION.len() as i64) + offset) as usize,
262        SeekFrom::Current(offset) => self.0 = ((self.0 as i64) + offset) as usize,
263      }
264      Ok(self.0 as u64)
265    }
266  }
267
268  let reader = RefCell::new(SerializationSeek(0));
269  let reader = ClonableSeek::<'_, SerializationSeek>::try_from(&reader).unwrap();
270  let reader = SeekAdapter::from(reader);
271  let mut deserializer =
272    core_json::Deserializer::<_, core_json::ConstStack<128>>::new(reader).unwrap();
273  let value = deserializer.value().unwrap();
274  let mut fields = value.fields().unwrap();
275  let field = fields.next().unwrap();
276  let (key, value) = field.unwrap();
277  assert_eq!(key.collect::<Result<String, _>>().unwrap(), "hello");
278  assert_eq!(value.to_str().unwrap().collect::<Result<String, _>>().unwrap(), "goodbye");
279  assert!(fields.next().is_none());
280}