1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
//! `no_std` friendly interface for conversion to str //! //! ``` //! type Buffer = to_str::Buffer64; //! //! let mut buf = String::new(); //! let _ = buf.push_str(Buffer::fmt(5usize).as_str()); //! assert_eq!(buf, "5"); //! //! buf.push_str(Buffer::fmt(0usize).as_str()); //! assert_eq!(buf, "50"); //! buf.push_str(Buffer::fmt(&5usize).as_str()); //! assert_eq!(buf, "505"); //! buf.push_str(Buffer::fmt(&mut 0usize).as_str()); //! assert_eq!(buf, "5050"); //! ``` #![warn(missing_docs)] #![cfg_attr(feature = "cargo-clippy", allow(clippy::style))] #![no_std] mod buffer; mod numeric; pub use buffer::Buffer; ///Alias to buffer that can be used to write `128` bit integers pub type Buffer128 = Buffer<[u8; i128::TEXT_SIZE]>; ///Alias to buffer that can be used to write `64` bit integers pub type Buffer64 = Buffer<[u8; i64::TEXT_SIZE]>; ///Alias to buffer that can be used to write `32` bit integers pub type Buffer32 = Buffer<[u8; i32::TEXT_SIZE]>; ///Alias to buffer that can be used to write `isize` bit integers pub type BufferSized = Buffer<[u8; isize::TEXT_SIZE]>; ///Describes conversion to string /// ///This trait is unsafe due to following requirements: /// ///- Implementation must never read buffer, unless it was already written by it; ///- It writes from the end of buffer (necessary only when you use `Buffer`). pub unsafe trait ToStr { ///Max size in bytes to hold the string /// ///Implementation MUST guarantee that this size of buffer is enough to fit any possible textual ///representation const TEXT_SIZE: usize; ///Writes textual representation to the buffer /// ///Returns `str` stored in the provided `buffer` /// ///Can panic, if buffer is not sufficient. ///Or write only partially /// ///Implementation is allowed to write any part of the buffer. ///It is not allowed to read it, unless it was written already. /// ///# Safety: /// ///Debug builds must never invoke UB when calling this function. /// ///UB in release mode is fine if one wants to write efficient code. fn to_str<'a>(&self, buffer: &'a mut [u8]) -> &'a str; #[inline] ///Performs textual conversion by writing to the buffer, if possible. /// ///If not possible MUST return `None` /// ///By default returns `None` if buffer size is below `TEXT_SIZE` ///Otherwise calls `to_str()` while passing buffer as it is fn to_str_if<'a>(&self, buffer: &'a mut [u8]) -> Option<&'a str> { if buffer.len() < Self::TEXT_SIZE { None } else { Some(self.to_str(buffer)) } } } unsafe impl<'a, T: ?Sized + ToStr> ToStr for &'a T { const TEXT_SIZE: usize = T::TEXT_SIZE; #[inline(always)] fn to_str<'b>(&self, buffer: &'b mut [u8]) -> &'b str { (&**self).to_str(buffer) } } unsafe impl<'a, T: ?Sized + ToStr> ToStr for &'a mut T { const TEXT_SIZE: usize = T::TEXT_SIZE; #[inline(always)] fn to_str<'b>(&self, buffer: &'b mut [u8]) -> &'b str { (&**self).to_str(buffer) } }