23
23
//! * [`PmString`] a UTF-8 encoded sized byte array in progmem similar to [`ProgMem`].
24
24
//!
25
25
//! Also the [`progmem`](crate::progmem) macro offers a special syntax for
26
- //! converting a normal string literal into a [`PmString`]:
26
+ //! converting a normal string literal into a [`PmString`].
27
+ //!
28
+ //!
29
+ //! # Examples
30
+ //!
31
+ //! Using [`PmString`] directly via the [`progmem`] macro:
27
32
//!
28
33
//! ```rust
29
34
//! #![feature(const_option)]
30
35
//!
31
36
//! # use std::iter::FromIterator;
32
37
//! use avr_progmem::progmem;
38
+ //! use avr_progmem::string::LoadedString;
33
39
//!
34
40
//! progmem! {
35
41
//! // A simple Unicode string in progmem, internally stored as fix-sized
36
- //! // byte array.
42
+ //! // byte array, i.e. a `PmString<18>` .
37
43
//! static progmem string TEXT = "Hello 大賢者";
38
44
//! }
39
45
//!
40
46
//! // You can load it all at once (like a `ProgMem`)
41
- //! let buffer = TEXT.load();
47
+ //! let buffer: LoadedString<15> = TEXT.load();
42
48
//! // and use that as `&str`
43
49
//! assert_eq!("Hello 大賢者", &*buffer);
44
50
//!
47
53
//! let chars_iter = TEXT.chars(); // impl Iterator<Item=char>
48
54
//! let exp = ['H', 'e', 'l', 'l', 'o', ' ', '大', '賢', '者'];
49
55
//! assert_eq!(&exp, &*Vec::from_iter(chars_iter));
56
+ //!
57
+ //! // Or you use directly the `Display`/`uDisplay` impl on `PmString`
58
+ //! // which uses the chars-iterator internally
59
+ //! use ufmt::uWrite;
60
+ //! #
61
+ //! # struct MyWriter;
62
+ //! # impl uWrite for MyWriter {
63
+ //! # type Error = ();
64
+ //! # fn write_str(&mut self, _s: &str) -> Result<(),()> {
65
+ //! # Ok(()) // ignore input
66
+ //! # }
67
+ //! # }
68
+ //! let mut writer =
69
+ //! # MyWriter
70
+ //! /* SNIP */;
71
+ //! #[cfg(feature = "ufmt")] // requires the `ufmt` crate feature
72
+ //! ufmt::uwrite!(&mut writer, "{}", TEXT);
73
+ //! ```
74
+ //!
75
+ //! Using the special literal in-line string macros [`progmem_str`] and
76
+ //! [`progmem_display`]:
77
+ //!
78
+ //! ```rust
79
+ //! #![feature(const_option)]
80
+ //!
81
+ //! use avr_progmem::progmem_str as F;
82
+ //! use avr_progmem::progmem_display as D;
83
+ //!
84
+ //! // Or you use directly the `Display`/`uDisplay` impl on `PmString`
85
+ //! // which uses the chars-iterator internally
86
+ //! use ufmt::uWrite;
87
+ //! # struct MyWriter;
88
+ //! # impl uWrite for MyWriter {
89
+ //! # type Error = ();
90
+ //! # fn write_str(&mut self, _s: &str) -> Result<(),()> {
91
+ //! # Ok(()) // ignore input
92
+ //! # }
93
+ //! # }
94
+ //! let mut writer =
95
+ //! # MyWriter
96
+ //! /* SNIP */;
97
+ //!
98
+ //! // In-line string as temporary `&str`
99
+ //! writer.write_str(F!("Hello 大賢者"));
100
+ //!
101
+ //! // In-line string as some `impl Display + uDisplay`
102
+ //! #[cfg(feature = "ufmt")] // requires the `ufmt` crate feature
103
+ //! ufmt::uwrite!(&mut writer, "{}", D!("Hello 大賢者"));
50
104
//! ```
51
105
//!
52
106
@@ -78,28 +132,6 @@ pub struct InvalidLengthError;
78
132
///
79
133
/// This type is particularly useful to store string literals in progmem.
80
134
///
81
- /// # Example
82
- ///
83
- /// ```rust
84
- /// #![feature(const_option)]
85
- ///
86
- /// use avr_progmem::progmem;
87
- /// use avr_progmem::string::PmString;
88
- /// use avr_progmem::string::LoadedString;
89
- ///
90
- /// progmem! {
91
- /// // Stores a string as a byte array, i.e. `[u8;19]`, but makes it usable
92
- /// // as `&str` (via `Deref`)
93
- /// static progmem string TEXT = "dai 大賢者 kenja";
94
- /// }
95
- ///
96
- /// // The static has type `PmString`
97
- /// let text: &PmString<19> = &TEXT;
98
- /// // The loaded RAM string has type `LoadedString`
99
- /// let loaded: LoadedString<19> = text.load();
100
- /// // Which derefs to `&str`
101
- /// assert_eq!("dai 大賢者 kenja", &*loaded)
102
- /// ```
103
135
///
104
136
/// # Safety
105
137
///
@@ -243,6 +275,7 @@ impl<const N: usize> ufmt::uDisplay for LoadedString<N> {
243
275
/// This allows `chars` to be used on very large strings that do not fit into
244
276
/// the RAM as whole.
245
277
///
278
+ ///
246
279
/// # Safety
247
280
///
248
281
/// This type is a wrapper around [`ProgMem`], thus it any value of this type
@@ -252,6 +285,30 @@ impl<const N: usize> ufmt::uDisplay for LoadedString<N> {
252
285
/// Additionally to the [`ProgMem`] contract, the byte array wrapped by this
253
286
/// struct must be valid UTF-8.
254
287
///
288
+ ///
289
+ /// # Example
290
+ ///
291
+ /// ```rust
292
+ /// #![feature(const_option)]
293
+ ///
294
+ /// use avr_progmem::progmem;
295
+ /// use avr_progmem::string::PmString;
296
+ /// use avr_progmem::string::LoadedString;
297
+ ///
298
+ /// progmem! {
299
+ /// // Stores a string as a byte array, i.e. `[u8;19]`, but makes it usable
300
+ /// // as `&str` (via `Deref`)
301
+ /// static progmem string TEXT = "dai 大賢者 kenja";
302
+ /// }
303
+ ///
304
+ /// // The static has type `PmString`
305
+ /// let text: &PmString<19> = &TEXT;
306
+ /// // The loaded RAM string has type `LoadedString`
307
+ /// let loaded: LoadedString<19> = text.load();
308
+ /// // Which derefs to `&str`
309
+ /// assert_eq!("dai 大賢者 kenja", &*loaded)
310
+ /// ```
311
+ ///
255
312
#[ repr( transparent) ]
256
313
#[ non_exhaustive] // SAFETY: this struct must not be publicly constructible
257
314
pub struct PmString < const N : usize > {
@@ -450,7 +507,7 @@ impl<'a, const N: usize> Iterator for PmChars<'a, N> {
450
507
451
508
452
509
453
- /// Define a string in progmem
510
+ /// Define a string in progmem usable as temporary `&str`
454
511
///
455
512
/// This is a short-cut macro to create an ad-hoc static storing the given
456
513
/// string literal as by [`LoadedString`] and load it here from progmem into a
@@ -460,36 +517,106 @@ impl<'a, const N: usize> Iterator for PmChars<'a, N> {
460
517
/// Similar to the C marco, this will load the full string into RAM at once
461
518
/// and thus the string should be of limited size, to not exceed the space
462
519
/// available in RAM.
520
+ /// Also see the [progmem_display] macro which does not have this limitation.
463
521
///
464
- /// This macro allows to conveniently put literal string into progmem exactly,
465
- /// where they are used. However, since they are directly loaded into a
466
- /// temporary you don't get a `&'static str` back, and must use the `&str`
467
- /// immediately (i.e. pass it as a function parameter).
522
+ /// This macro allows to conveniently put a literal string into progmem
523
+ /// right where it is used.
524
+ /// However, since they are directly loaded into a temporary you don't get a
525
+ /// `&'static str` back, and must use the `&str` immediately (i.e. pass it as a
526
+ /// function parameter).
468
527
/// You can't even store the returned `&str` in a local `let` assignment.
469
528
///
470
529
///
471
530
/// # Example
472
531
///
473
532
/// ```rust
474
533
/// #![feature(const_option)]
475
- ///
476
534
/// use avr_progmem::progmem_str as F;
535
+ /// use ufmt::uWrite;
477
536
///
478
- /// fn print(s: &str) {
479
- /// // -- snip --
480
- /// # assert_eq!(s, "dai 大賢者 kenja")
481
- /// }
537
+ /// # struct MyWriter;
538
+ /// # impl uWrite for MyWriter {
539
+ /// # type Error = ();
540
+ /// # fn write_str(&mut self, _s: &str) -> Result<(),()> {
541
+ /// # Ok(()) // ignore input
542
+ /// # }
543
+ /// # }
544
+ /// #
545
+ /// let mut writer = // impl uWrite
546
+ /// # MyWriter;
547
+ /// /* SNIP */;
482
548
///
483
549
/// // Put the literal `str` into progmem and load it here as `&str`
484
- /// print (F!("dai 大賢者 kenja"));
550
+ /// writer.write_str (F!("dai 大賢者 kenja"));
485
551
/// ```
486
552
///
487
553
#[ macro_export]
488
554
macro_rules! progmem_str {
489
- ( $text: literal ) => { {
555
+ ( $text: expr ) => { {
490
556
$crate:: progmem! {
491
557
static progmem string TEXT = $text;
492
558
}
493
559
& * TEXT . load( )
494
560
} } ;
495
561
}
562
+
563
+
564
+ /// Define a string in progmem usable as `impl Display + uDisplay`
565
+ ///
566
+ /// This is a short-cut macro to create an ad-hoc static storing the given
567
+ /// string literal as a [`PmString`] and return it.
568
+ /// This is somewhat similar to the `F` macro available in Arduino IDE, but
569
+ /// different.
570
+ /// For a macro more in line with the `F` macro, see [progmem_str].
571
+ ///
572
+ /// Unlike the `F` macro, this macro neither loads the string here, nor, can
573
+ /// it be use as a `&str`.
574
+ /// However, the returned value implements [Display](fmt::Display) as well as
575
+ /// [ufmt::uDisplay] (if the `ufmt` crate feature is enabled).
576
+ ///
577
+ /// This macro allows to conveniently put a literal string into progmem
578
+ /// right where it is used.
579
+ /// However, since it is not loaded (yet) into RAM it is not a `&str`, it only
580
+ /// exposes a [Display](fmt::Display) and [ufmt::uDisplay] (if the `ufmt` crate
581
+ /// feature is enabled) implementation,
582
+ /// which will load it char-by-char when used, thus limiting the RAM usage,
583
+ /// and allowing arbitrarily large strings to be wrapped.
584
+ ///
585
+ ///
586
+ /// # Example
587
+ ///
588
+ /// ```rust
589
+ /// #![feature(const_option)]
590
+ /// use avr_progmem::progmem_display as D;
591
+ /// use ufmt::uWrite;
592
+ ///
593
+ /// # struct MyWriter;
594
+ /// # impl uWrite for MyWriter {
595
+ /// # type Error = ();
596
+ /// # fn write_str(&mut self, _s: &str) -> Result<(),()> {
597
+ /// # Ok(()) // ignore input
598
+ /// # }
599
+ /// # }
600
+ /// #
601
+ /// let mut writer = // impl uWrite
602
+ /// # MyWriter;
603
+ /// /* SNIP */;
604
+ ///
605
+ /// // Put the literal `str` into progmem and use it as `impl uDisplay`
606
+ /// #[cfg(feature = "ufmt")] // requires the `ufmt` crate feature
607
+ /// ufmt::uwrite!(&mut writer, "{}", D!("dai 大賢者 kenja"));
608
+ ///
609
+ /// // Huge strings are fine
610
+ /// #[cfg(feature = "ufmt")] // requires the `ufmt` crate feature
611
+ /// ufmt::uwrite!(&mut writer, "{}", D!(include_str!("../examples/test_text.txt")));
612
+ /// ```
613
+ ///
614
+ #[ macro_export]
615
+ macro_rules! progmem_display {
616
+ ( $text: expr) => { {
617
+ $crate:: progmem! {
618
+ static progmem string TEXT = $text;
619
+ }
620
+ & TEXT
621
+ } } ;
622
+ }
0 commit comments