external_memory_tools/
lib.rs1#![no_std]
5#![deny(unused_crate_dependencies)]
6
7#[cfg(not(feature = "std"))]
8extern crate core;
9
10#[cfg(not(feature = "std"))]
11#[macro_use]
12extern crate alloc;
13
14#[cfg(feature = "std")]
15#[macro_use]
16extern crate std;
17
18#[cfg(not(feature = "std"))]
19use core::fmt::{Debug, Display, Formatter, Result as FmtResult};
20
21#[cfg(not(feature = "std"))]
22use alloc::string::String;
23
24#[cfg(feature = "std")]
25use std::{
26 error::Error,
27 fmt::{Debug, Display, Formatter, Result as FmtResult},
28 string::String,
29};
30
31pub trait ExternalMemory: Debug {
33 type ExternalMemoryError: Debug + Display + Eq + PartialEq;
35}
36
37impl ExternalMemory for () {
39 type ExternalMemoryError = NoEntries;
40}
41
42#[derive(Debug, Eq, PartialEq)]
44pub enum NoEntries {}
45
46impl Display for NoEntries {
47 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
48 write!(f, "")
49 }
50}
51
52pub trait AddressableBuffer<E: ExternalMemory>: Sized {
57 type ReadBuffer: AsRef<[u8]>;
59
60 fn total_len(&self) -> usize;
62
63 fn read_slice(
68 &self,
69 ext_memory: &mut E,
70 position: usize,
71 slice_len: usize,
72 ) -> Result<Self::ReadBuffer, BufferError<E>>;
73
74 fn read_byte(&self, ext_memory: &mut E, position: usize) -> Result<u8, BufferError<E>> {
76 let byte_slice = self.read_slice(ext_memory, position, 1)?;
77 Ok(byte_slice.as_ref()[0])
78 }
79
80 fn limit_length(&self, new_len: usize) -> Result<Self, BufferError<E>>;
82}
83
84impl<'a, E: ExternalMemory> AddressableBuffer<E> for &'a [u8] {
86 type ReadBuffer = &'a [u8];
87 fn total_len(&self) -> usize {
88 self.len()
89 }
90 fn read_slice(
91 &self,
92 _ext_memory: &mut E,
93 position: usize,
94 slice_len: usize,
95 ) -> Result<Self::ReadBuffer, BufferError<E>> {
96 if self.len() < position {
97 return Err(BufferError::OutOfRange {
98 position,
99 total_length: self.len(),
100 });
101 }
102 match self.get(position..position + slice_len) {
103 Some(a) => Ok(a),
104 None => Err(BufferError::DataTooShort {
105 position,
106 minimal_length: slice_len,
107 }),
108 }
109 }
110 fn limit_length(&self, new_len: usize) -> Result<Self, BufferError<E>> {
111 self.get(..new_len).ok_or(BufferError::DataTooShort {
112 position: 0,
113 minimal_length: new_len,
114 })
115 }
116}
117
118#[derive(Debug, Eq, PartialEq)]
120pub enum BufferError<E: ExternalMemory> {
121 DataTooShort {
122 position: usize,
123 minimal_length: usize,
124 },
125 External(E::ExternalMemoryError),
126 OutOfRange {
127 position: usize,
128 total_length: usize,
129 },
130}
131
132impl<E: ExternalMemory> BufferError<E> {
133 fn error_text(&self) -> String {
134 match &self {
135 BufferError::DataTooShort { position, minimal_length } => format!("Data is too short for expected content. Expected at least {minimal_length} element(s) after position {position}."),
136 BufferError::External(e) => format!("Error accessing external memory. {e}"),
137 BufferError::OutOfRange { position, total_length } => format!("Position {position} is out of range for data length {total_length}."),
138 }
139 }
140}
141
142impl<E: ExternalMemory> Display for BufferError<E> {
143 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
144 write!(f, "{}", self.error_text())
145 }
146}
147
148#[cfg(feature = "std")]
149impl<E: ExternalMemory> Error for BufferError<E> {
150 fn source(&self) -> Option<&(dyn Error + 'static)> {
151 None
152 }
153}