esplugin/
lib.rs

1/*
2 * This file is part of esplugin
3 *
4 * Copyright (C) 2017 Oliver Hamlet
5 *
6 * esplugin is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * esplugin is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with esplugin. If not, see <http://www.gnu.org/licenses/>.
18 */
19// Allow a few clippy pedantic lints.
20#![allow(
21    clippy::doc_markdown,
22    clippy::exhaustive_enums,
23    clippy::must_use_candidate,
24    clippy::missing_errors_doc
25)]
26#![cfg_attr(
27    test,
28    allow(
29        clippy::assertions_on_result_states,
30        clippy::indexing_slicing,
31        clippy::missing_asserts_for_indexing,
32        clippy::panic,
33        clippy::unwrap_used,
34    )
35)]
36
37pub use crate::error::{Error, MoreDataNeeded, ParsingErrorKind};
38pub use crate::game_id::GameId;
39pub use crate::plugin::{plugins_metadata, ParseOptions, Plugin, PluginMetadata};
40
41mod error;
42mod game_id;
43mod group;
44mod plugin;
45mod record;
46mod record_id;
47mod subrecord;
48
49// No point recording any details of the error because it's not reported.
50struct SliceTooSmallError;
51
52fn le_slice_to_u32(input: &[u8]) -> Result<u32, SliceTooSmallError> {
53    const ARRAY_SIZE: usize = std::mem::size_of::<u32>();
54
55    subarray::<ARRAY_SIZE>(input, 0).map(u32::from_le_bytes)
56}
57
58fn le_slice_to_f32(input: &[u8]) -> Result<f32, SliceTooSmallError> {
59    const ARRAY_SIZE: usize = std::mem::size_of::<f32>();
60
61    subarray::<ARRAY_SIZE>(input, 0).map(f32::from_le_bytes)
62}
63
64fn subarray<const SIZE: usize>(
65    bytes: &[u8],
66    start_index: usize,
67) -> Result<[u8; SIZE], SliceTooSmallError> {
68    let stop_index = start_index + SIZE;
69
70    let bytes = bytes
71        .get(start_index..stop_index)
72        .ok_or(SliceTooSmallError)?;
73
74    <[u8; SIZE]>::try_from(bytes).map_err(|_e| SliceTooSmallError)
75}
76
77#[expect(
78    clippy::as_conversions,
79    reason = "A compile-time assertion ensures that this conversion will be lossless on all relevant target platforms"
80)]
81const fn u32_to_usize(input: u32) -> usize {
82    // Error at compile time if this conversion isn't lossless.
83    const _: () = assert!(u32::BITS <= usize::BITS, "cannot fit a u32 into a usize!");
84    input as usize
85}