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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// Copyright (c) 2025 R3BL LLC. Licensed under Apache License, Version 2.0.
//! UTF-8 encoding constants for byte-level text parsing.
//!
//! This module provides bit masks, byte ranges, and validation constants used
//! when parsing UTF-8 encoded text from terminal input streams.
//!
//! ## UTF-8 Encoding Structure
//!
//! UTF-8 uses variable-length encoding (1-4 bytes per character):
//!
//! | Bytes | First byte | Continuation bytes | Bit pattern |
//! |:------|:-----------|:-------------------|:-------------------------------------|
//! | 1 | 00-7F | - | 0xxxxxxx |
//! | 2 | C0-DF | 80-BF | 110xxxxx 10xxxxxx |
//! | 3 | E0-EF | 80-BF (x2) | 1110xxxx 10xxxxxx 10xxxxxx |
//! | 4 | F0-F7 | 80-BF (x3) | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
//!
//! ## Continuation Byte Validation
//!
//! All bytes after the first must match the pattern `10xxxxxx` (80-BF hex).
//! This is validated using [`UTF8_CONTINUATION_MASK`] and [`UTF8_CONTINUATION_PATTERN`]:
//!
//! ```rust
//! # use r3bl_tui::{UTF8_CONTINUATION_MASK, UTF8_CONTINUATION_PATTERN};
//! let byte = 0x9F; // Example continuation byte
//! assert_eq!(byte & UTF8_CONTINUATION_MASK, UTF8_CONTINUATION_PATTERN);
//! ```
//!
//! ## Decoding Process
//!
//! 1. Read first byte to determine sequence length (1-4 bytes)
//! 2. Validate all continuation bytes match `10xxxxxx` pattern
//! 3. Extract data bits using the appropriate mask
//! 4. Combine bits to form the Unicode codepoint
//!
//! ## Usage Example
//!
//! ```rust
//! # use r3bl_tui::{UTF8_1BYTE_MAX, UTF8_2BYTE_MIN, UTF8_2BYTE_MAX};
//! let first_byte = 0xC2; // Start of 2-byte sequence
//!
//! // Determine sequence length
//! let is_2byte = (UTF8_2BYTE_MIN..=UTF8_2BYTE_MAX).contains(&first_byte);
//! assert!(is_2byte);
//! ```
// ============================================================================
// UTF-8 Start Byte Ranges (First byte of sequence)
// ============================================================================
/// ASCII range: single-byte UTF-8 (00-7F hex).
///
/// Pattern: `0xxxxxxx`
pub const UTF8_1BYTE_MIN: u8 = 0b0000_0000;
/// ASCII range maximum: single-byte UTF-8 (7F hex).
///
/// Pattern: `0xxxxxxx`
pub const UTF8_1BYTE_MAX: u8 = 0b0111_1111;
/// 2-byte UTF-8 sequence start range minimum (C0 hex).
///
/// Pattern: `110xxxxx 10xxxxxx`
pub const UTF8_2BYTE_MIN: u8 = 0b1100_0000;
/// 2-byte UTF-8 sequence start range maximum (DF hex).
///
/// Pattern: `110xxxxx 10xxxxxx`
pub const UTF8_2BYTE_MAX: u8 = 0b1101_1111;
/// 3-byte UTF-8 sequence start range minimum (E0 hex).
///
/// Pattern: `1110xxxx 10xxxxxx 10xxxxxx`
pub const UTF8_3BYTE_MIN: u8 = 0b1110_0000;
/// 3-byte UTF-8 sequence start range maximum (EF hex).
///
/// Pattern: `1110xxxx 10xxxxxx 10xxxxxx`
pub const UTF8_3BYTE_MAX: u8 = 0b1110_1111;
/// 4-byte UTF-8 sequence start range minimum (F0 hex).
///
/// Pattern: `11110xxx 10xxxxxx 10xxxxxx 10xxxxxx`
pub const UTF8_4BYTE_MIN: u8 = 0b1111_0000;
/// 4-byte UTF-8 sequence start range maximum (F7 hex).
///
/// Pattern: `11110xxx 10xxxxxx 10xxxxxx 10xxxxxx`
pub const UTF8_4BYTE_MAX: u8 = 0b1111_0111;
// ============================================================================
// UTF-8 Continuation Bytes (Second, third, fourth bytes)
// ============================================================================
/// Continuation byte range minimum (80 hex).
///
/// All continuation bytes must match pattern `10xxxxxx` (80-BF hex).
pub const UTF8_CONTINUATION_MIN: u8 = 0b1000_0000;
/// Continuation byte range maximum (BF hex).
///
/// All continuation bytes must match pattern `10xxxxxx` (80-BF hex).
pub const UTF8_CONTINUATION_MAX: u8 = 0b1011_1111;
/// Continuation byte validation mask (C0 hex).
///
/// Used to extract the high 2 bits: `byte & 0b1100_0000` should equal
/// `0b1000_0000` for valid continuation bytes.
///
/// Example:
/// ```rust
/// # use r3bl_tui::{UTF8_CONTINUATION_MASK, UTF8_CONTINUATION_PATTERN};
/// let valid = 0x9F;
/// assert_eq!(valid & UTF8_CONTINUATION_MASK, UTF8_CONTINUATION_PATTERN);
///
/// let invalid = 0x00;
/// assert_ne!(invalid & UTF8_CONTINUATION_MASK, UTF8_CONTINUATION_PATTERN);
/// ```
pub const UTF8_CONTINUATION_MASK: u8 = 0b1100_0000;
/// Continuation byte expected pattern (80 hex).
///
/// After masking with [`UTF8_CONTINUATION_MASK`], valid continuation bytes
/// should equal this value.
pub const UTF8_CONTINUATION_PATTERN: u8 = 0b1000_0000;
// ============================================================================
// UTF-8 Reserved/Invalid Bytes
// ============================================================================
/// Reserved byte range minimum (F8 hex).
///
/// Bytes F8-FF hex are invalid UTF-8 start bytes.
pub const UTF8_RESERVED_MIN: u8 = 0b1111_1000;
/// Reserved byte range maximum (FF hex).
///
/// Bytes F8-FF hex are invalid UTF-8 start bytes.
pub const UTF8_RESERVED_MAX: u8 = 0b1111_1111;
// ============================================================================
// UTF-8 Decoding Bit Masks (Extract data bits from each byte)
// ============================================================================
/// 2-byte sequence: first byte data mask (1F hex).
///
/// Extracts lower 5 bits from first byte: `byte & 0b0001_1111`
///
/// Pattern: `110xxxxx` → extract `xxxxx`
pub const UTF8_2BYTE_FIRST_MASK: u8 = 0b0001_1111;
/// Continuation byte data mask (3F hex).
///
/// Extracts lower 6 bits from continuation bytes: `byte & 0b0011_1111`
///
/// Pattern: `10xxxxxx` → extract `xxxxxx`
pub const UTF8_CONTINUATION_DATA_MASK: u8 = 0b0011_1111;
/// 3-byte sequence: first byte data mask (0F hex).
///
/// Extracts lower 4 bits from first byte: `byte & 0b0000_1111`
///
/// Pattern: `1110xxxx` → extract `xxxx`
pub const UTF8_3BYTE_FIRST_MASK: u8 = 0b0000_1111;
/// 4-byte sequence: first byte data mask (07 hex).
///
/// Extracts lower 3 bits from first byte: `byte & 0b0000_0111`
///
/// Pattern: `11110xxx` → extract `xxx`
pub const UTF8_4BYTE_FIRST_MASK: u8 = 0b0000_0111;
// ============================================================================
// Tests
// ============================================================================