local_fmt/message/
refer.rs1use std::fmt::Display;
2
3use crate::{const_i128_to_str, const_u128_to_str, UtilBufWrapper};
4
5use super::CreateMessageError;
6
7#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
8pub enum RefMessageFormat<'a> {
9 RefText(&'a str),
10 UNumber(u128),
11 INumber(i128),
12 Placeholder(usize),
13}
14
15impl Display for RefMessageFormat<'_> {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 match self {
18 RefMessageFormat::RefText(text) => write!(f, "{}", text),
19 RefMessageFormat::UNumber(n) => write!(f, "{}", n),
20 RefMessageFormat::INumber(n) => write!(f, "{}", n),
21 RefMessageFormat::Placeholder(n) => write!(f, "{{{}}}", n),
22 }
23 }
24}
25
26pub type StaticMessage<const N: usize> = RefMessage<'static, N>;
27
28#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
29pub struct RefMessage<'a, const N: usize> {
30 formats: &'a [RefMessageFormat<'a>],
31}
32
33impl<'a, const N: usize> RefMessage<'a, N> {
34 pub const unsafe fn new_unchecked(formats: &'a [RefMessageFormat<'a>]) -> Self {
37 Self { formats }
38 }
39
40 pub const fn new(formats: &'a [RefMessageFormat<'a>]) -> Result<Self, CreateMessageError> {
41 let mut numbers = [false; N];
42
43 let mut current = 0;
44
45 while formats.len() > current {
46 if let RefMessageFormat::Placeholder(n) = formats[current] {
47 if n >= N {
48 return Err(CreateMessageError::InvalidNumber { number: n, n: N });
49 }
50 numbers[n] = true;
51 }
52 current += 1;
53 }
54
55 let mut current = 0;
56
57 while numbers.len() > current {
58 if !numbers[current] {
59 return Err(CreateMessageError::WithoutNumber {
60 number: current,
61 n: N,
62 });
63 }
64 current += 1;
65 }
66
67 Ok(Self { formats })
68 }
69
70 #[track_caller]
71 pub const fn new_panic(formats: &'a [RefMessageFormat<'a>]) -> Self {
72 match Self::new(formats) {
73 Ok(message) => message,
74 Err(error) => error.panic(),
75 }
76 }
77
78 pub fn format(&self, args: &[&str; N]) -> String {
79 let mut result = String::new();
80
81 for format in self.formats {
82 match format {
83 RefMessageFormat::RefText(text) => result.push_str(text),
84 RefMessageFormat::UNumber(n) => result.push_str(&n.to_string()),
85 RefMessageFormat::INumber(n) => result.push_str(&n.to_string()),
86 RefMessageFormat::Placeholder(n) => result.push_str(args[*n]),
87 }
88 }
89
90 result
91 }
92
93 pub const fn len(&self) -> usize {
94 self.formats.len()
95 }
96
97 pub const fn is_empty(&self) -> bool {
98 self.formats.is_empty()
99 }
100
101 pub const fn formats(&self) -> &'a [RefMessageFormat<'a>] {
102 self.formats
103 }
104}
105
106impl<const N: usize> StaticMessage<N> {
107 pub const unsafe fn const_format<const SIZE: usize>(
134 &self,
135 args: &[&[u8]; N],
136 ) -> UtilBufWrapper<SIZE> {
137 let mut buf = [0u8; SIZE];
138 let mut total = 0;
139
140 let mut i = 0;
141 while i < self.formats.len() {
142 macro_rules! process {
143 ($bytes:expr) => {
144 match $bytes {
145 bytes => {
146 let len = bytes.len();
147 let mut j = 0;
148 while j < len {
149 buf[total] = bytes[j];
150 total += 1;
151 j += 1;
152 }
153 i += 1;
154 }
155 }
156 };
157 }
158 match &self.formats[i] {
159 RefMessageFormat::RefText(text) => process!(text.as_bytes()),
160 RefMessageFormat::UNumber(n) => process!(const_u128_to_str(*n).buffer()),
161 RefMessageFormat::INumber(n) => process!(const_i128_to_str(*n).buffer()),
162 RefMessageFormat::Placeholder(n) => process!(args[*n]),
163 }
164 }
165
166 UtilBufWrapper::new(buf, total)
167 }
168}
169
170impl<const N: usize> Display for RefMessage<'_, N> {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 for format in self.formats {
173 write!(f, "{}", format)?;
174 }
175
176 Ok(())
177 }
178}