Skip to content

Commit

Permalink
Add a special rule for string literals that omits the unwrap call.
Browse files Browse the repository at this point in the history
Using `avr_progmem_string::string_as_bytes` macro, string literals can be
converted into fixed-sized byte arrays allowing to use the
`PmString::from_array` constructor, thus removing the `unwrap`, and
consequently the necessity for the `const_option` Compiler feature.
  • Loading branch information
Cryptjar committed Apr 12, 2022
1 parent 0ca0560 commit 156651d
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 12 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ cfg-if = "1.0"
version = "0.1.0"
optional = true

[dependencies.avr-progmem-string]
# TODO: upgrade to a crates.io version
git = "https://github.com/mutantbob/avr-progmem-string.git"
rev = "2dc98b809a99098f70d38a8d1653d9cc6664e16e"



[dev-dependencies]
panic-halt = "0.2.0"
Expand Down
5 changes: 0 additions & 5 deletions examples/uno-arrays.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
// Define no_std only for AVR
#![cfg_attr(target_arch = "avr", no_std)]
#![cfg_attr(target_arch = "avr", no_main)]
//
// To unwrap the Option in const context
#![feature(const_option)]
//
#![feature(extended_key_value_attributes)]


use avr_progmem::progmem; // The macro
Expand Down
38 changes: 32 additions & 6 deletions src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@
//! Using [`PmString`] directly via the [`progmem`] macro:
//!
//! ```rust
//! #![feature(const_option)]
//!
//! # use std::iter::FromIterator;
//! use avr_progmem::progmem;
//! use avr_progmem::string::LoadedString;
Expand All @@ -95,8 +93,6 @@
//! // A simple Unicode string in progmem, internally stored as fix-sized
//! // byte array, i.e. a `PmString<18>`.
//! static progmem string TEXT = "Hello 大賢者";
//! // text too large to fit in the RAM of a microcontroller
//! static progmem string LOVECRAFT = include_str!("../examples/test_text.txt");
//! }
//!
//! // You can load it all at once (like a `ProgMem`)
Expand Down Expand Up @@ -132,8 +128,6 @@
//! [`progmem_display`]:
//!
//! ```rust
//! #![feature(const_option)]
//!
//! use avr_progmem::progmem_str as F;
//! use avr_progmem::progmem_display as D;
//!
Expand All @@ -159,6 +153,38 @@
//! ufmt::uwrite!(&mut writer, "{}", D!("Hello 大賢者"));
//! ```
//!
//! You can also use arbitrary `&str`-yielding expression, however,
//! then you need Rust's `const_option` feature, because the string size
//! can no longer be determined statically.
//!
//! ```rust
//! #![feature(const_option)]
//!
//! use avr_progmem::progmem;
//! use avr_progmem::progmem_display as D;
//! #
//! # use ufmt::uWrite;
//! # struct MyWriter;
//! # impl uWrite for MyWriter {
//! # type Error = ();
//! # fn write_str(&mut self, _s: &str) -> Result<(),()> {
//! # Ok(()) // ignore input
//! # }
//! # }
//! # let mut writer =
//! # MyWriter
//! # /* SNIP */;
//!
//! progmem! {
//! // Text too large to fit in the RAM of a microcontroller
//! static progmem string LOVECRAFT = include_str!("../examples/test_text.txt");
//! }
//!
//! // In-line a huge string from a file
//! #[cfg(feature = "ufmt")] // requires the `ufmt` crate feature
//! ufmt::uwrite!(&mut writer, "{}", D!(include_str!("../examples/test_text.txt")));
//! ```
//!

use core::convert::TryFrom;
Expand Down
39 changes: 38 additions & 1 deletion src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

use core::convert::TryInto;

// Used in the `progmem` macro
#[doc(hidden)]
pub use avr_progmem_string::string_as_bytes;

use crate::raw::read_value;


Expand Down Expand Up @@ -530,7 +534,40 @@ macro_rules! progmem {
#[doc(hidden)]
#[macro_export]
macro_rules! progmem_internal {
// The string rule creating the progmem string static via `PmString`
// A string rule creating the progmem string static from a string literal
// using `string_as_bytes`, so no `unwrap` is required
{
$( #[ $attr:meta ] )*
$vis:vis static progmem string $name:ident = $value:literal ;
} => {

// PmString must be stored in the progmem or text section!
// The link_section lets us define it:
#[cfg_attr(target_arch = "avr", link_section = ".progmem.data")]

// User attributes
$(#[$attr])*
// The actual static definition
$vis static $name : $crate::string::PmString<{
// This bit runs at compile-time
let s: &str = $value;
s.len()
}> =
unsafe {
// SAFETY: This call is sound, be cause we ensure with the above
// link_section attribute that this value is indeed in the
// progmem section.
$crate::string::PmString::from_array(
// Using `avr_progmem_string::string_as_bytes` macro to get
// a fixed size array, so there is no need for an `unwrap`
// anymore.
$crate::wrapper::string_as_bytes!( $value )
)
};
};

// The string rule creating the progmem string static from an arbitrary
// string expression, thus a unwrap is needed.
{
$( #[ $attr:meta ] )*
$vis:vis static progmem string $name:ident = $value:expr ;
Expand Down

0 comments on commit 156651d

Please sign in to comment.