1use std::fmt::{Debug, Formatter};
2
3use crate::internal::unwrap_indent;
4
5#[derive(Clone, Copy, PartialEq, Eq)]
6pub enum ByteType {
7 None,
8 Ascii(u8),
9 One(u8),
10 Two(u8),
11 Three(u8),
12 FourOrMore(u8),
13 Continuation(u8),
14}
15
16impl ByteType {
17 pub fn new(byte: u8) -> ByteType {
18 if byte < 127 {
19 ByteType::Ascii(byte)
20 } else {
21 match byte.leading_ones() {
22 0 => ByteType::One(byte),
23 1 => ByteType::Continuation(byte),
24 2 => ByteType::Two(byte),
25 3 => ByteType::Three(byte),
26 _ => ByteType::FourOrMore(byte),
27 }
28 }
29 }
30
31 pub fn name(&self) -> &'static str {
32 match self {
33 ByteType::None => "None",
34 ByteType::Ascii(_) => "Ascii",
35 ByteType::One(_) => "One",
36 ByteType::Two(_) => "Two",
37 ByteType::Three(_) => "Three",
38 ByteType::FourOrMore(_) => "FourOrMore",
39 ByteType::Continuation(_) => "Continuation",
40 }
41 }
42
43 pub fn byte(&self) -> u8 {
44 match self {
45 ByteType::None => u8::default(),
46 ByteType::Ascii(byte) => *byte,
47 ByteType::One(byte) => *byte,
48 ByteType::Two(byte) => *byte,
49 ByteType::Three(byte) => *byte,
50 ByteType::FourOrMore(byte) => *byte,
51 ByteType::Continuation(byte) => *byte,
52 }
53 }
54
55 pub fn len(&self) -> usize {
56 match self {
57 ByteType::Continuation(_) | ByteType::Ascii(_) => 1,
58 _ => (self.byte().leading_ones()) as usize,
59 }
60 }
61
62 pub fn is_ascii(&self) -> bool {
63 match self {
64 ByteType::Ascii(_) => true,
65 _ => false,
66 }
67 }
68
69 pub fn is_continuation(&self) -> bool {
70 match self {
71 ByteType::Continuation(_) => true,
72 _ => false,
73 }
74 }
75
76 pub fn has_rune_delta(&self) -> bool {
77 match self {
78 ByteType::None => false,
79 ByteType::Ascii(_) => false,
80 ByteType::Continuation(_) => false,
81 _ => true,
82 }
83 }
84
85 fn as_debug(&self, indent: Option<usize>) -> String {
86 let indent = unwrap_indent(indent);
87 format!(
88 "{}::{}{{\n{}\n}})",
89 "ByteType",
90 self.name(),
91 [
92 format!(
93 "byte: 0x{:02x},{}",
94 self.byte(),
95 if let Ok(c) = std::str::from_utf8(&[self.byte()]) {
96 format!(" // \"{c}\"")
97 } else {
98 String::new()
99 }
100 ),
101 format!("len: {},", self.len()),
102 ]
103 .iter()
104 .map(|c| {
105 let padding = " ".repeat(indent);
106 format!("{padding}{c}")
107 })
108 .collect::<Vec<String>>()
109 .join("\n")
110 )
111 }
112}
113impl From<u8> for ByteType {
114 fn from(byte: u8) -> ByteType {
115 ByteType::new(byte)
116 }
117}
118impl From<&u8> for ByteType {
119 fn from(byte: &u8) -> ByteType {
120 ByteType::new(*byte)
121 }
122}
123impl From<u16> for ByteType {
124 fn from(bytes: u16) -> ByteType {
125 ByteType::from(bytes.to_le_bytes()[0])
126 }
127}
128impl From<u32> for ByteType {
129 fn from(bytes: u32) -> ByteType {
130 ByteType::from(bytes.to_le_bytes()[0])
131 }
132}
133impl From<u64> for ByteType {
134 fn from(bytes: u64) -> ByteType {
135 ByteType::from(bytes.to_le_bytes()[0])
136 }
137}
138impl From<usize> for ByteType {
139 fn from(bytes: usize) -> ByteType {
140 ByteType::from(bytes.to_le_bytes()[0])
141 }
142}
143
144impl Debug for ByteType {
145 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
146 write!(f, "{}", self.as_debug(None))
147 }
148}