| 1 | use config::{BincodeByteOrder, Options};
|
| 2 | use std::io::Read;
|
| 3 |
|
| 4 | use self::read::{BincodeRead, IoReader, SliceReader};
|
| 5 | use byteorder::ReadBytesExt;
|
| 6 | use config::{IntEncoding, SizeLimit};
|
| 7 | use serde;
|
| 8 | use serde::de::Error as DeError;
|
| 9 | use serde::de::IntoDeserializer;
|
| 10 | use {Error, ErrorKind, Result};
|
| 11 |
|
| 12 | /// Specialized ways to read data into bincode.
|
| 13 | pub mod read;
|
| 14 |
|
| 15 | /// A Deserializer that reads bytes from a buffer.
|
| 16 | ///
|
| 17 | /// This struct should rarely be used.
|
| 18 | /// In most cases, prefer the `deserialize_from` function.
|
| 19 | ///
|
| 20 | /// The ByteOrder that is chosen will impact the endianness that
|
| 21 | /// is used to read integers out of the reader.
|
| 22 | ///
|
| 23 | /// ```ignore
|
| 24 | /// let d = Deserializer::new(&mut some_reader, SizeLimit::new());
|
| 25 | /// serde::Deserialize::deserialize(&mut deserializer);
|
| 26 | /// let bytes_read = d.bytes_read();
|
| 27 | /// ```
|
| 28 | pub struct Deserializer<R, O: Options> {
|
| 29 | pub(crate) reader: R,
|
| 30 | options: O,
|
| 31 | }
|
| 32 |
|
| 33 | macro_rules! impl_deserialize_literal {
|
| 34 | ($name:ident : $ty:ty = $read:ident()) => {
|
| 35 | #[inline]
|
| 36 | pub(crate) fn $name(&mut self) -> Result<$ty> {
|
| 37 | self.read_literal_type::<$ty>()?;
|
| 38 | self.reader
|
| 39 | .$read::<<O::Endian as BincodeByteOrder>::Endian>()
|
| 40 | .map_err(Into::into)
|
| 41 | }
|
| 42 | };
|
| 43 | }
|
| 44 |
|
| 45 | impl<'de, IR: Read, O: Options> Deserializer<IoReader<IR>, O> {
|
| 46 | /// Creates a new Deserializer with a given `Read`er and options.
|
| 47 | pub fn with_reader(r: IR, options: O) -> Self {
|
| 48 | Deserializer {
|
| 49 | reader: IoReader::new(r),
|
| 50 | options,
|
| 51 | }
|
| 52 | }
|
| 53 | }
|
| 54 |
|
| 55 | impl<'de, O: Options> Deserializer<SliceReader<'de>, O> {
|
| 56 | /// Creates a new Deserializer that will read from the given slice.
|
| 57 | pub fn from_slice(slice: &'de [u8], options: O) -> Self {
|
| 58 | Deserializer {
|
| 59 | reader: SliceReader::new(bytes:slice),
|
| 60 | options,
|
| 61 | }
|
| 62 | }
|
| 63 | }
|
| 64 |
|
| 65 | impl<'de, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
|
| 66 | /// Creates a new Deserializer with the given `BincodeRead`er
|
| 67 | pub fn with_bincode_read(r: R, options: O) -> Deserializer<R, O> {
|
| 68 | Deserializer { reader: r, options }
|
| 69 | }
|
| 70 |
|
| 71 | pub(crate) fn deserialize_byte(&mut self) -> Result<u8> {
|
| 72 | self.read_literal_type::<u8>()?;
|
| 73 | self.reader.read_u8().map_err(Into::into)
|
| 74 | }
|
| 75 |
|
| 76 | impl_deserialize_literal! { deserialize_literal_u16 : u16 = read_u16() }
|
| 77 | impl_deserialize_literal! { deserialize_literal_u32 : u32 = read_u32() }
|
| 78 | impl_deserialize_literal! { deserialize_literal_u64 : u64 = read_u64() }
|
| 79 |
|
| 80 | serde_if_integer128! {
|
| 81 | impl_deserialize_literal! { deserialize_literal_u128 : u128 = read_u128() }
|
| 82 | }
|
| 83 |
|
| 84 | fn read_bytes(&mut self, count: u64) -> Result<()> {
|
| 85 | self.options.limit().add(count)
|
| 86 | }
|
| 87 |
|
| 88 | fn read_literal_type<T>(&mut self) -> Result<()> {
|
| 89 | use std::mem::size_of;
|
| 90 | self.read_bytes(size_of::<T>() as u64)
|
| 91 | }
|
| 92 |
|
| 93 | fn read_vec(&mut self) -> Result<Vec<u8>> {
|
| 94 | let len = O::IntEncoding::deserialize_len(self)?;
|
| 95 | self.read_bytes(len as u64)?;
|
| 96 | self.reader.get_byte_buffer(len)
|
| 97 | }
|
| 98 |
|
| 99 | fn read_string(&mut self) -> Result<String> {
|
| 100 | let vec = self.read_vec()?;
|
| 101 | String::from_utf8(vec).map_err(|e| ErrorKind::InvalidUtf8Encoding(e.utf8_error()).into())
|
| 102 | }
|
| 103 | }
|
| 104 |
|
| 105 | macro_rules! impl_deserialize_int {
|
| 106 | ($name:ident = $visitor_method:ident ($dser_method:ident)) => {
|
| 107 | #[inline]
|
| 108 | fn $name<V>(self, visitor: V) -> Result<V::Value>
|
| 109 | where
|
| 110 | V: serde::de::Visitor<'de>,
|
| 111 | {
|
| 112 | visitor.$visitor_method(O::IntEncoding::$dser_method(self)?)
|
| 113 | }
|
| 114 | };
|
| 115 | }
|
| 116 |
|
| 117 | impl<'de, 'a, R, O> serde::Deserializer<'de> for &'a mut Deserializer<R, O>
|
| 118 | where
|
| 119 | R: BincodeRead<'de>,
|
| 120 | O: Options,
|
| 121 | {
|
| 122 | type Error = Error;
|
| 123 |
|
| 124 | #[inline ]
|
| 125 | fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
|
| 126 | where
|
| 127 | V: serde::de::Visitor<'de>,
|
| 128 | {
|
| 129 | Err(Box::new(ErrorKind::DeserializeAnyNotSupported))
|
| 130 | }
|
| 131 |
|
| 132 | fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
|
| 133 | where
|
| 134 | V: serde::de::Visitor<'de>,
|
| 135 | {
|
| 136 | match self.deserialize_byte()? {
|
| 137 | 1 => visitor.visit_bool(true),
|
| 138 | 0 => visitor.visit_bool(false),
|
| 139 | value => Err(ErrorKind::InvalidBoolEncoding(value).into()),
|
| 140 | }
|
| 141 | }
|
| 142 |
|
| 143 | impl_deserialize_int!(deserialize_u16 = visit_u16(deserialize_u16));
|
| 144 | impl_deserialize_int!(deserialize_u32 = visit_u32(deserialize_u32));
|
| 145 | impl_deserialize_int!(deserialize_u64 = visit_u64(deserialize_u64));
|
| 146 | impl_deserialize_int!(deserialize_i16 = visit_i16(deserialize_i16));
|
| 147 | impl_deserialize_int!(deserialize_i32 = visit_i32(deserialize_i32));
|
| 148 | impl_deserialize_int!(deserialize_i64 = visit_i64(deserialize_i64));
|
| 149 |
|
| 150 | fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
|
| 151 | where
|
| 152 | V: serde::de::Visitor<'de>,
|
| 153 | {
|
| 154 | self.read_literal_type::<f32>()?;
|
| 155 | let value = self
|
| 156 | .reader
|
| 157 | .read_f32::<<O::Endian as BincodeByteOrder>::Endian>()?;
|
| 158 | visitor.visit_f32(value)
|
| 159 | }
|
| 160 |
|
| 161 | fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
|
| 162 | where
|
| 163 | V: serde::de::Visitor<'de>,
|
| 164 | {
|
| 165 | self.read_literal_type::<f64>()?;
|
| 166 | let value = self
|
| 167 | .reader
|
| 168 | .read_f64::<<O::Endian as BincodeByteOrder>::Endian>()?;
|
| 169 | visitor.visit_f64(value)
|
| 170 | }
|
| 171 |
|
| 172 | serde_if_integer128! {
|
| 173 | impl_deserialize_int!(deserialize_u128 = visit_u128(deserialize_u128));
|
| 174 | impl_deserialize_int!(deserialize_i128 = visit_i128(deserialize_i128));
|
| 175 | }
|
| 176 |
|
| 177 | #[inline ]
|
| 178 | fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
|
| 179 | where
|
| 180 | V: serde::de::Visitor<'de>,
|
| 181 | {
|
| 182 | visitor.visit_u8(self.deserialize_byte()? as u8)
|
| 183 | }
|
| 184 |
|
| 185 | #[inline ]
|
| 186 | fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
|
| 187 | where
|
| 188 | V: serde::de::Visitor<'de>,
|
| 189 | {
|
| 190 | visitor.visit_i8(self.deserialize_byte()? as i8)
|
| 191 | }
|
| 192 |
|
| 193 | fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
|
| 194 | where
|
| 195 | V: serde::de::Visitor<'de>,
|
| 196 | {
|
| 197 | visitor.visit_unit()
|
| 198 | }
|
| 199 |
|
| 200 | fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
|
| 201 | where
|
| 202 | V: serde::de::Visitor<'de>,
|
| 203 | {
|
| 204 | use std::str;
|
| 205 |
|
| 206 | let error = || ErrorKind::InvalidCharEncoding.into();
|
| 207 |
|
| 208 | let mut buf = [0u8; 4];
|
| 209 |
|
| 210 | // Look at the first byte to see how many bytes must be read
|
| 211 | self.reader.read_exact(&mut buf[..1])?;
|
| 212 | let width = utf8_char_width(buf[0]);
|
| 213 | if width == 1 {
|
| 214 | return visitor.visit_char(buf[0] as char);
|
| 215 | }
|
| 216 | if width == 0 {
|
| 217 | return Err(error());
|
| 218 | }
|
| 219 |
|
| 220 | if self.reader.read_exact(&mut buf[1..width]).is_err() {
|
| 221 | return Err(error());
|
| 222 | }
|
| 223 |
|
| 224 | let res = str::from_utf8(&buf[..width])
|
| 225 | .ok()
|
| 226 | .and_then(|s| s.chars().next())
|
| 227 | .ok_or_else(error)?;
|
| 228 | visitor.visit_char(res)
|
| 229 | }
|
| 230 |
|
| 231 | fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
|
| 232 | where
|
| 233 | V: serde::de::Visitor<'de>,
|
| 234 | {
|
| 235 | let len = O::IntEncoding::deserialize_len(self)?;
|
| 236 | self.read_bytes(len as u64)?;
|
| 237 | self.reader.forward_read_str(len, visitor)
|
| 238 | }
|
| 239 |
|
| 240 | fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
|
| 241 | where
|
| 242 | V: serde::de::Visitor<'de>,
|
| 243 | {
|
| 244 | visitor.visit_string(self.read_string()?)
|
| 245 | }
|
| 246 |
|
| 247 | fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
|
| 248 | where
|
| 249 | V: serde::de::Visitor<'de>,
|
| 250 | {
|
| 251 | let len = O::IntEncoding::deserialize_len(self)?;
|
| 252 | self.read_bytes(len as u64)?;
|
| 253 | self.reader.forward_read_bytes(len, visitor)
|
| 254 | }
|
| 255 |
|
| 256 | fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
|
| 257 | where
|
| 258 | V: serde::de::Visitor<'de>,
|
| 259 | {
|
| 260 | visitor.visit_byte_buf(self.read_vec()?)
|
| 261 | }
|
| 262 |
|
| 263 | fn deserialize_enum<V>(
|
| 264 | self,
|
| 265 | _enum: &'static str,
|
| 266 | _variants: &'static [&'static str],
|
| 267 | visitor: V,
|
| 268 | ) -> Result<V::Value>
|
| 269 | where
|
| 270 | V: serde::de::Visitor<'de>,
|
| 271 | {
|
| 272 | impl<'de, 'a, R: 'a, O> serde::de::EnumAccess<'de> for &'a mut Deserializer<R, O>
|
| 273 | where
|
| 274 | R: BincodeRead<'de>,
|
| 275 | O: Options,
|
| 276 | {
|
| 277 | type Error = Error;
|
| 278 | type Variant = Self;
|
| 279 |
|
| 280 | fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
|
| 281 | where
|
| 282 | V: serde::de::DeserializeSeed<'de>,
|
| 283 | {
|
| 284 | let idx: u32 = O::IntEncoding::deserialize_u32(self)?;
|
| 285 | let val: Result<_> = seed.deserialize(idx.into_deserializer());
|
| 286 | Ok((val?, self))
|
| 287 | }
|
| 288 | }
|
| 289 |
|
| 290 | visitor.visit_enum(self)
|
| 291 | }
|
| 292 |
|
| 293 | fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value>
|
| 294 | where
|
| 295 | V: serde::de::Visitor<'de>,
|
| 296 | {
|
| 297 | struct Access<'a, R: Read + 'a, O: Options + 'a> {
|
| 298 | deserializer: &'a mut Deserializer<R, O>,
|
| 299 | len: usize,
|
| 300 | }
|
| 301 |
|
| 302 | impl<'de, 'a, 'b: 'a, R: BincodeRead<'de> + 'b, O: Options> serde::de::SeqAccess<'de>
|
| 303 | for Access<'a, R, O>
|
| 304 | {
|
| 305 | type Error = Error;
|
| 306 |
|
| 307 | fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
| 308 | where
|
| 309 | T: serde::de::DeserializeSeed<'de>,
|
| 310 | {
|
| 311 | if self.len > 0 {
|
| 312 | self.len -= 1;
|
| 313 | let value =
|
| 314 | serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
|
| 315 | Ok(Some(value))
|
| 316 | } else {
|
| 317 | Ok(None)
|
| 318 | }
|
| 319 | }
|
| 320 |
|
| 321 | fn size_hint(&self) -> Option<usize> {
|
| 322 | Some(self.len)
|
| 323 | }
|
| 324 | }
|
| 325 |
|
| 326 | visitor.visit_seq(Access {
|
| 327 | deserializer: self,
|
| 328 | len,
|
| 329 | })
|
| 330 | }
|
| 331 |
|
| 332 | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
|
| 333 | where
|
| 334 | V: serde::de::Visitor<'de>,
|
| 335 | {
|
| 336 | let value: u8 = serde::de::Deserialize::deserialize(&mut *self)?;
|
| 337 | match value {
|
| 338 | 0 => visitor.visit_none(),
|
| 339 | 1 => visitor.visit_some(&mut *self),
|
| 340 | v => Err(ErrorKind::InvalidTagEncoding(v as usize).into()),
|
| 341 | }
|
| 342 | }
|
| 343 |
|
| 344 | fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
|
| 345 | where
|
| 346 | V: serde::de::Visitor<'de>,
|
| 347 | {
|
| 348 | let len = O::IntEncoding::deserialize_len(self)?;
|
| 349 |
|
| 350 | self.deserialize_tuple(len, visitor)
|
| 351 | }
|
| 352 |
|
| 353 | fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
|
| 354 | where
|
| 355 | V: serde::de::Visitor<'de>,
|
| 356 | {
|
| 357 | struct Access<'a, R: Read + 'a, O: Options + 'a> {
|
| 358 | deserializer: &'a mut Deserializer<R, O>,
|
| 359 | len: usize,
|
| 360 | }
|
| 361 |
|
| 362 | impl<'de, 'a, 'b: 'a, R: BincodeRead<'de> + 'b, O: Options> serde::de::MapAccess<'de>
|
| 363 | for Access<'a, R, O>
|
| 364 | {
|
| 365 | type Error = Error;
|
| 366 |
|
| 367 | fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
|
| 368 | where
|
| 369 | K: serde::de::DeserializeSeed<'de>,
|
| 370 | {
|
| 371 | if self.len > 0 {
|
| 372 | self.len -= 1;
|
| 373 | let key =
|
| 374 | serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
|
| 375 | Ok(Some(key))
|
| 376 | } else {
|
| 377 | Ok(None)
|
| 378 | }
|
| 379 | }
|
| 380 |
|
| 381 | fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
|
| 382 | where
|
| 383 | V: serde::de::DeserializeSeed<'de>,
|
| 384 | {
|
| 385 | let value = serde::de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?;
|
| 386 | Ok(value)
|
| 387 | }
|
| 388 |
|
| 389 | fn size_hint(&self) -> Option<usize> {
|
| 390 | Some(self.len)
|
| 391 | }
|
| 392 | }
|
| 393 |
|
| 394 | let len = O::IntEncoding::deserialize_len(self)?;
|
| 395 |
|
| 396 | visitor.visit_map(Access {
|
| 397 | deserializer: self,
|
| 398 | len,
|
| 399 | })
|
| 400 | }
|
| 401 |
|
| 402 | fn deserialize_struct<V>(
|
| 403 | self,
|
| 404 | _name: &str,
|
| 405 | fields: &'static [&'static str],
|
| 406 | visitor: V,
|
| 407 | ) -> Result<V::Value>
|
| 408 | where
|
| 409 | V: serde::de::Visitor<'de>,
|
| 410 | {
|
| 411 | self.deserialize_tuple(fields.len(), visitor)
|
| 412 | }
|
| 413 |
|
| 414 | fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value>
|
| 415 | where
|
| 416 | V: serde::de::Visitor<'de>,
|
| 417 | {
|
| 418 | let message = "Bincode does not support Deserializer::deserialize_identifier" ;
|
| 419 | Err(Error::custom(message))
|
| 420 | }
|
| 421 |
|
| 422 | fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
|
| 423 | where
|
| 424 | V: serde::de::Visitor<'de>,
|
| 425 | {
|
| 426 | visitor.visit_newtype_struct(self)
|
| 427 | }
|
| 428 |
|
| 429 | fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
|
| 430 | where
|
| 431 | V: serde::de::Visitor<'de>,
|
| 432 | {
|
| 433 | visitor.visit_unit()
|
| 434 | }
|
| 435 |
|
| 436 | fn deserialize_tuple_struct<V>(
|
| 437 | self,
|
| 438 | _name: &'static str,
|
| 439 | len: usize,
|
| 440 | visitor: V,
|
| 441 | ) -> Result<V::Value>
|
| 442 | where
|
| 443 | V: serde::de::Visitor<'de>,
|
| 444 | {
|
| 445 | self.deserialize_tuple(len, visitor)
|
| 446 | }
|
| 447 |
|
| 448 | fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
|
| 449 | where
|
| 450 | V: serde::de::Visitor<'de>,
|
| 451 | {
|
| 452 | let message = "Bincode does not support Deserializer::deserialize_ignored_any" ;
|
| 453 | Err(Error::custom(message))
|
| 454 | }
|
| 455 |
|
| 456 | fn is_human_readable(&self) -> bool {
|
| 457 | false
|
| 458 | }
|
| 459 | }
|
| 460 |
|
| 461 | impl<'de, 'a, R, O> serde::de::VariantAccess<'de> for &'a mut Deserializer<R, O>
|
| 462 | where
|
| 463 | R: BincodeRead<'de>,
|
| 464 | O: Options,
|
| 465 | {
|
| 466 | type Error = Error;
|
| 467 |
|
| 468 | fn unit_variant(self) -> Result<()> {
|
| 469 | Ok(())
|
| 470 | }
|
| 471 |
|
| 472 | fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
|
| 473 | where
|
| 474 | T: serde::de::DeserializeSeed<'de>,
|
| 475 | {
|
| 476 | serde::de::DeserializeSeed::deserialize(seed, self)
|
| 477 | }
|
| 478 |
|
| 479 | fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
|
| 480 | where
|
| 481 | V: serde::de::Visitor<'de>,
|
| 482 | {
|
| 483 | serde::de::Deserializer::deserialize_tuple(self, len, visitor)
|
| 484 | }
|
| 485 |
|
| 486 | fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
| 487 | where
|
| 488 | V: serde::de::Visitor<'de>,
|
| 489 | {
|
| 490 | serde::de::Deserializer::deserialize_tuple(self, fields.len(), visitor)
|
| 491 | }
|
| 492 | }
|
| 493 | static UTF8_CHAR_WIDTH: [u8; 256] = [
|
| 494 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| 495 | 1, // 0x1F
|
| 496 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| 497 | 1, // 0x3F
|
| 498 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| 499 | 1, // 0x5F
|
| 500 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
| 501 | 1, // 0x7F
|
| 502 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
| 503 | 0, // 0x9F
|
| 504 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
| 505 | 0, // 0xBF
|
| 506 | 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
| 507 | 2, // 0xDF
|
| 508 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
|
| 509 | 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
|
| 510 | ];
|
| 511 |
|
| 512 | // This function is a copy of core::str::utf8_char_width
|
| 513 | fn utf8_char_width(b: u8) -> usize {
|
| 514 | UTF8_CHAR_WIDTH[b as usize] as usize
|
| 515 | }
|
| 516 | |