1
+ //! String utilities
2
+ //!
3
+ //! This module offers further utilities base on [`ProgMem`] to make working
4
+ //! with strings in progmem more convenient.
5
+ //!
6
+ //! The difficulty with strings is that normally they are either heap allocated
7
+ //! (as with the std Rust `String`) or dynamically sized (as with `str`).
8
+ //! To store a string in progmem, one needs first of all a fixed-sized storage
9
+ //! variant of a `str`.
10
+ //! One option is to use byte string literals (e.g. `b"foobar"`), however,
11
+ //! for some reason those only accept ASCII and no Unicode.
12
+ //! At some day, one might be able to to convert arbitrary string literals to
13
+ //! byte arrays like this:
14
+ //!
15
+ //! ```ignore
16
+ //! # use std::convert::TryInto;
17
+ //! // Dose not compile as of 1.51, because `try_into` is not a const fn
18
+ //! static WIKIPEDIA: [u8; 12] = "维基百科".as_bytes().try_into().unwrap();
19
+ //! ```
20
+ //!
21
+ //! As a convenient workaround, this module offers:
22
+ //! * [`LoadedString`] a simple UTF-8 encoded sized byte array
23
+ //! * [`PmString`] a UTF-8 encoded sized byte array in progmem similar to [`ProgMem`].
24
+ //!
25
+ //! Also the [`progmem`](crate::progmem) macro offers a special syntax for
26
+ //! converting a normal string literal into a [`PmString`]:
27
+ //!
28
+ //! ```rust
29
+ //! // TODO: code
30
+ //! ```
31
+ //!
32
+
33
+
1
34
use core:: convert:: TryFrom ;
2
35
use core:: fmt;
3
36
use core:: ops:: Deref ;
@@ -175,10 +208,19 @@ impl<const N: usize> ufmt::uDisplay for LoadedString<N> {
175
208
/// A byte string in progmem
176
209
///
177
210
/// Not to be confused with a [`LoadedString`].
178
- /// A `LoadedString` is just a wrapper around a byte array (`[u8;N]`) that can
179
- /// be put into a [`ProgMem`].
180
- /// A `PmString` on the other hand, is a wrapper around a
181
- /// `ProgMem<[u8;N]>`.
211
+ /// A `LoadedString` is a simple wrapper around a byte array (`[u8;N]`) that
212
+ /// derefs to `str`, and should be used in RAM.
213
+ /// A `PmString` on the other hand, is a wrapper around a byte array in progmem
214
+ /// aka around a `ProgMem<[u8;N]>`, and thus must always be progmem.
215
+ /// Similar to `ProgMem`, `PmString` offers a [`load`](PmString::load) method to
216
+ /// load its entire content into RAM.
217
+ /// The loaded content will be a `LoadedString`, hence the name.
218
+ ///
219
+ /// Besides loading the entire string at once into RAM, `PmString` also offers
220
+ /// a lazy [`chars`](PmString::chars) iterator method, that will load just one
221
+ /// char at a time.
222
+ /// This allows `chars` to be used on very large strings that do not fit into
223
+ /// the RAM as whole.
182
224
///
183
225
/// # Safety
184
226
///
@@ -208,6 +250,8 @@ impl<const N: usize> PmString<N> {
208
250
/// This function is only sound to call, if the value is
209
251
/// stored in a static that is for instance attributed with
210
252
/// `#[link_section = ".progmem.data"]`.
253
+ ///
254
+ /// You are encouraged to use the [`progmem`] macro instead.
211
255
pub const unsafe fn new ( s : & str ) -> Option < Self > {
212
256
Self :: from_bytes ( s. as_bytes ( ) )
213
257
}
@@ -267,6 +311,18 @@ impl<const N: usize> PmString<N> {
267
311
}
268
312
269
313
/// Loads the entire string into RAM
314
+ ///
315
+ /// # Panics
316
+ ///
317
+ /// This method panics, if the size of the value (i.e. `N`) is beyond 255
318
+ /// bytes.
319
+ /// However, this is currently just a implementation limitation, which may
320
+ /// be lifted in the future.
321
+ ///
322
+ /// If you have a very large string, consider using the lazy
323
+ /// [`chars`](Self::chars) iterator that accesses the string by one char at
324
+ /// a time and thus does not have such a limitation.
325
+ ///
270
326
pub fn load ( & self ) -> LoadedString < N > {
271
327
let array = self . load_bytes ( ) ;
272
328
@@ -279,6 +335,17 @@ impl<const N: usize> PmString<N> {
279
335
}
280
336
281
337
/// Loads the entire string as byte array into RAM
338
+ ///
339
+ /// # Panics
340
+ ///
341
+ /// This method panics, if the size of the value (i.e. `[u8; N]`) is beyond
342
+ /// 255 bytes.
343
+ /// However, this is currently just a implementation limitation, which may
344
+ /// be lifted in the future.
345
+ ///
346
+ /// If you have a very large string, consider using the lazy
347
+ /// [`chars`](Self::chars) iterator or the respective byte iterator
348
+ /// (via `as_bytes().iter()`).
282
349
pub fn load_bytes ( & self ) -> [ u8 ; N ] {
283
350
self . as_bytes ( ) . load ( )
284
351
}
@@ -290,8 +357,9 @@ impl<const N: usize> PmString<N> {
290
357
291
358
/// Lazily iterate over the `char`s of the string.
292
359
///
293
- /// This function is analog to [`ProgMem::iter`], except it is over the
294
- /// `char`s of this string.
360
+ /// This function is analog to [`ProgMem::iter`], except it performs UTF-8
361
+ /// parsing and returns the `char`s of this string, thus it is more similar
362
+ /// to [`str::chars`].
295
363
pub fn chars ( & self ) -> PmChars < N > {
296
364
PmChars :: new ( self )
297
365
}
0 commit comments