mesh_loader/utils/
mod.rs
1pub(crate) mod bytes;
2#[cfg(any(feature = "collada", feature = "obj", feature = "stl"))]
3pub mod float;
4#[cfg(feature = "collada")]
5pub(crate) mod hex;
6#[cfg(any(feature = "collada", feature = "obj"))]
7pub mod int;
8#[cfg(feature = "collada")]
9pub(crate) mod xml;
10
11#[cfg(any(feature = "collada", feature = "obj"))]
12pub(crate) mod utf16 {
13 use std::{borrow::Cow, io};
14
15 use crate::error;
16
17 const UTF32BE_BOM: &[u8] = &[0xFF, 0xFE, 00, 00];
18 const UTF32LE_BOM: &[u8] = &[00, 00, 0xFE, 0xFF];
19 const UTF16BE_BOM: &[u8] = &[0xFE, 0xFF];
20 const UTF16LE_BOM: &[u8] = &[0xFF, 0xFE];
21 const UTF8_BOM: &[u8] = &[0xEF, 0xBB, 0xBF];
22
23 #[cfg(feature = "collada")]
25 pub(crate) fn decode_string(bytes: &[u8]) -> io::Result<Cow<'_, str>> {
26 if bytes.starts_with(UTF8_BOM) {
27 std::str::from_utf8(&bytes[UTF8_BOM.len()..])
28 .map(Cow::Borrowed)
29 .map_err(error::invalid_data)
30 } else if bytes.starts_with(UTF32BE_BOM) || bytes.starts_with(UTF32LE_BOM) {
31 return Err(error::invalid_data("utf-32 is not supported"));
32 } else if bytes.starts_with(UTF16BE_BOM) {
33 from_utf16be(&bytes[UTF16BE_BOM.len()..]).map(Into::into)
34 } else if bytes.starts_with(UTF16LE_BOM) {
35 from_utf16le(&bytes[UTF16BE_BOM.len()..]).map(Into::into)
36 } else {
37 std::str::from_utf8(bytes)
39 .map(Cow::Borrowed)
40 .map_err(error::invalid_data)
41 }
42 }
43
44 #[cfg(feature = "obj")]
48 pub(crate) fn decode_bytes(bytes: &[u8]) -> io::Result<Cow<'_, [u8]>> {
49 if bytes.starts_with(UTF8_BOM) {
50 Ok(Cow::Borrowed(&bytes[UTF8_BOM.len()..]))
51 } else if bytes.starts_with(UTF32BE_BOM) || bytes.starts_with(UTF32LE_BOM) {
52 return Err(error::invalid_data("utf-32 is not supported"));
53 } else if bytes.starts_with(UTF16BE_BOM) {
54 from_utf16be(&bytes[UTF16BE_BOM.len()..])
55 .map(String::into_bytes)
56 .map(Into::into)
57 } else if bytes.starts_with(UTF16LE_BOM) {
58 from_utf16le(&bytes[UTF16BE_BOM.len()..])
59 .map(String::into_bytes)
60 .map(Into::into)
61 } else {
62 Ok(Cow::Borrowed(bytes))
63 }
64 }
65
66 #[cold]
67 #[inline(never)]
68 fn from_utf16be(bytes: &[u8]) -> io::Result<String> {
69 if bytes.len() % 2 != 0 {
70 return Err(error::invalid_data("invalid utf-16: lone surrogate found"));
71 }
72 char::decode_utf16(
73 bytes
74 .chunks_exact(2)
75 .map(|b| u16::from_be_bytes(b.try_into().unwrap())),
76 )
77 .collect::<Result<String, _>>()
78 .map_err(error::invalid_data)
79 }
80
81 #[cold]
82 #[inline(never)]
83 fn from_utf16le(bytes: &[u8]) -> io::Result<String> {
84 if bytes.len() % 2 != 0 {
85 return Err(error::invalid_data("invalid utf-16: lone surrogate found"));
86 }
87 char::decode_utf16(
88 bytes
89 .chunks_exact(2)
90 .map(|b| u16::from_le_bytes(b.try_into().unwrap())),
91 )
92 .collect::<Result<String, _>>()
93 .map_err(error::invalid_data)
94 }
95}