no_std_strings/lib.rs
1//! **`no_std`** version of crate **[fixedstr](https://crates.io/crates/fixedstr/)**:
2//! strings of fixed maximum lengths that can be copied and
3//! stack-allocated using const generics.
4
5//! The types provided by this crate are **[zstr]** and **`tstr`**. However,
6//! tstr is not directly exported and can only be directly referenced through
7//! the type aliases [str4]-[str256]. Each `zstr<N>` represents a
8//! zero-terminated string of exactly N bytes, accommodating all strings of
9//! lengths up to N-1 bytes. A `tstr<N>` can likewise hold all strings of
10//! up to N-1 bytes, but it stores the length of the string in the first byte.
11//! Thus the const generic parameter `N` cannot exceed 256. Since there is
12//! still no stable way to contrain N at compile time, the tstr type can only
13//! be referenced using the aliases. With few exceptions the tstr type
14//! implement the same functions and traits as [zstr].
15//!
16//! Compared to their counterparts in
17//! [fixedstr](https://docs.rs/fixedstr/latest/fixedstr/), some functions
18//! were omitted to accommodate the `#![no_std]` requirement.
19//!
20//! Optional serde serialization support is enabled by `--features serde`.
21
22
23#![no_std]
24
25#![allow(unused_variables)]
26#![allow(non_snake_case)]
27#![allow(non_camel_case_types)]
28#![allow(unused_parens)]
29#![allow(unused_assignments)]
30#![allow(unused_mut)]
31#![allow(unused_imports)]
32#![allow(dead_code)]
33
34mod zero_terminated;
35pub use zero_terminated::*;
36
37mod tiny_internal;
38use tiny_internal::*;
39
40/// Types for small strings that use a more efficient representation
41/// underneath. A str8 can hold a string of up to 7 bytes (7 ascii chars).
42/// The same functions for [zstr] are provided for these types
43/// so the documentation for the other types also applies.
44/// The size of str8 is 8 bytes.
45///
46/// Example:
47/// ```
48/// use no_std_strings::str8;
49/// let mut s = str8::from("aλc");
50/// assert_eq!(s.capacity(),7);
51/// assert_eq!(s.push("1234567"), "4567");
52/// assert_eq!(s,"aλc123");
53/// assert_eq!(s.charlen(), 6);
54/// assert_eq!(s.len(), 7);
55/// ```
56/// All functions and traits for these types mirror those of [zstr].
57pub type str8 = tstr<8>;
58/// A str16 can hold a string of up to 15 bytes. See docs for [zstr].
59/// The size of str16 is 16 bytes, which is the same as for &str on 64bit
60/// systems.
61pub type str16 = tstr<16>;
62/// A str32 can hold a string of up to 31 bytes. See docs for [zstr]
63pub type str32 = tstr<32>;
64/// A str64 can hold a string of up to 63 bytes. See docs for [zstr]
65pub type str64 = tstr<64>;
66/// A str28 can hold a string of up to 127 bytes. See docs for [zstr]
67pub type str128 = tstr<128>;
68/// Each type strN is represented underneath by a `[u8;N]` with N<=256.
69/// The first byte of the array always holds the length of the string.
70/// Each such type can hold a string of up to N-1 bytes, with max size=255.
71/// <br>
72/// In addition, the str4-str128 types implement [core::ops::Add], allowing for
73/// string concatenation of strings of the same type. For example,
74/// two str8 strings will always concatenate to str16, and similarly for
75/// all other strN types up to str128.
76///```
77/// use no_std_strings::str8;
78/// let c1 = str8::from("abcd");
79/// let c2 = str8::from("xyz");
80/// let c3 = c1 + c2;
81/// assert_eq!(c3,"abcdxyz");
82/// assert_eq!(c3.capacity(),15);
83///```
84pub type str256 = tstr<256>;
85
86/// strings of up to three 8-bit chars, good enough to represent abbreviations
87/// such as those for states and airports. Each str<4> is exactly 32 bits.
88pub type str4 = tstr<4>;
89pub type str12 = tstr<12>;
90pub type str24 = tstr<24>;
91pub type str48 = tstr<48>;
92pub type str96 = tstr<96>;
93pub type str192 = tstr<192>;
94
95
96
97
98#[macro_export]
99/// creates a formated string of given type (by implementing [core::fmt::Write]):
100/// ```ignore
101/// let s = str_format!(str8,"abc{}{}{}",1,2,3);
102/// ```
103/// will truncate if capacity exceeded, without warning.
104macro_rules! str_format {
105 ($ty_size:ty, $($args:tt)*) => {
106 {use core::fmt::Write;
107 let mut fstr0 = <$ty_size>::new();
108 let res=write!(&mut fstr0, $($args)*);
109 fstr0}
110 };
111}
112
113#[macro_export]
114/// version of [str_format]! that returns an Option of the given type.
115/// ```ignore
116/// let s = try_format!(str32,"abcdefg{}","hijklmnop").unwrap();
117/// let s2 = try_format!(str8,"abcdefg{}","hijklmnop");
118/// assert!(s2.is_none());
119/// ```
120macro_rules! try_format {
121 ($ty_size:ty, $($args:tt)*) => {
122 {use core::fmt::Write;
123 let mut fstr0 = <$ty_size>::new();
124 let result = write!(&mut fstr0, $($args)*);
125 if result.is_ok() {Some(fstr0)} else {None}}
126 };
127}
128
129
130#[cfg(feature="serde")]
131mod serde_support {
132 use serde::{Serialize, Deserialize, Serializer, Deserializer, de::Visitor};
133 use super::*;
134 macro_rules! generate_impl {
135 ($ty: ident, $visitor: ident) => {
136 impl<const N: usize> Serialize for $ty<N> {
137 fn serialize<S: Serializer>(&self, serializer:S) -> Result<S::Ok, S::Error> {
138 serializer.serialize_str(self.as_str())
139 }
140 }
141 impl<'de, const N: usize> Deserialize<'de> for $ty<N> {
142 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
143 deserializer.deserialize_str($visitor)
144 }
145 }
146 struct $visitor<const N: usize>;
147 impl<'de, const N: usize> Visitor<'de> for $visitor<N> {
148 type Value = $ty<N>;
149 fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
150 f.write_str("a string")
151 }
152 fn visit_str<E: serde::de::Error>(self, s: &str) -> Result<Self::Value, E> {
153 $ty::try_make(s).map_err(|_| E::custom("string too long"))
154 }
155 }
156 }
157 }
158 generate_impl!(zstr, ZstrVisitor);
159 generate_impl!(tstr, TstrVisitor);
160}
161
162
163
164/*
165fn tests() {
166 let a:str8 = str8::from("abcdef"); //a str8 can hold up to 7 bytes
167 let a2 = a; // copied, not moved
168 let ab = a.substr(1,5); // copies substring to new string
169 assert_eq!(ab, "bcde"); // can compare for equality with &str
170 assert_eq!(ab.len(),4);
171 assert_eq!(&a[..3], "abc"); // impls Index for Range types
172 assert!(a<ab); // and Ord, Hash, Debug, Display, Eq, other common traits
173 let astr:&str = a.to_str(); // convert to &str (zero copy)
174 let azstr:zstr<16> = zstr::from(a); // so is zstr
175 let a32:str32 = a.resize(); // same kind of string but with 31-byte capacity
176 let mut u = str8::from("aλb"); //unicode support
177 assert_eq!(u.nth(1), Some('λ')); // get nth character
178 assert_eq!(u.nth_ascii(3), 'b'); // get nth byte as ascii character
179 assert!(u.set(1,'μ')); // changes a character of the same character class
180 assert!(!u.set(1,'c')); // .set returns false on failure
181 assert!(u.set(2,'c'));
182 assert_eq!(u, "aμc");
183 assert_eq!(u.len(),4); // length in bytes
184 assert_eq!(u.charlen(),3); // length in chars
185 let mut ac:str16 = a.reallocate().unwrap(); //copies to larger capacity type
186 let remainder = ac.push("ghijklmnopq"); //append up to capacity, returns remainder
187 assert_eq!(ac.len(),15);
188 assert_eq!(remainder, "pq");
189 ac.truncate(9); // keep first 9 chars
190 assert_eq!(&ac,"abcdefghi");
191 let (upper,lower) = (str8::make("ABC"), str8::make("abc"));
192 assert_eq!(upper, lower.to_ascii_upper()); // no owned String needed
193
194 let c1 = str8::from("abcd"); // string concatenation with + for strN types
195 let c2 = str8::from("xyz");
196 let c3 = c1 + c2;
197 assert_eq!(c3,"abcdxyz");
198 assert_eq!(c3.capacity(),15); // type of c3 is str16
199
200 let c4 = str_format!(str16,"abc {}{}{}",1,2,3); // impls std::fmt::Write
201 assert_eq!(c4,"abc 123"); //str_format! truncates if capacity exceeded
202 let c5 = try_format!(str8,"abcdef{}","ghijklmn");
203 assert!(c5.is_none()); // try_format! returns None if capacity exceeded
204}//tests
205
206#[cfg(test)]
207mod tests {
208 use super::*;
209
210 #[test]
211 fn it_works() {
212 tests();
213 }
214}
215*/