#![cfg_attr(not(feature = "std"), no_std)]
#![warn(
// Turn on extra language lints.
future_incompatible,
missing_abi,
nonstandard_style,
rust_2018_idioms,
// Disabled due to <https://github.com/rust-lang/rust/issues/69952>.
// single_use_lifetimes,
trivial_casts,
trivial_numeric_casts,
unused,
unused_crate_dependencies,
unused_import_braces,
unused_lifetimes,
unused_qualifications,
// Turn on extra Rustdoc lints.
rustdoc::all,
// Turn on extra Clippy lints.
clippy::cargo,
clippy::pedantic,
)]
#![allow(clippy::option_if_let_else)]
#![allow(clippy::tabs_in_doc_comments)]
#[cfg(feature = "alloc")]
extern crate alloc;
pub mod error;
pub mod fluid;
pub mod inventory;
pub mod map_decoder;
pub mod sides;
use minicbor::Decode;
pub trait Lockable<'invoker, 'buffer, B: oc_wasm_futures::invoke::Buffer> {
type Locked;
#[must_use = "This function is only useful for its return value"]
fn lock(
&self,
invoker: &'invoker mut oc_wasm_safe::component::Invoker,
buffer: &'buffer mut B,
) -> Self::Locked;
}
#[cfg(feature = "alloc")]
pub fn decode_one_based_map_as_vector<
'buffer,
Context,
DecodedType: Decode<'buffer, Context>,
ResultType: From<DecodedType>,
>(
d: &mut minicbor::Decoder<'buffer>,
context: &mut Context,
) -> Result<alloc::vec::Vec<ResultType>, minicbor::decode::Error> {
use alloc::vec;
use alloc::vec::Vec;
struct PartialArray<T> {
storage: Vec<T>,
initialized: Vec<bool>,
}
impl<T> PartialArray<T> {
pub fn new(len: usize) -> Self {
Self {
storage: Vec::with_capacity(len),
initialized: vec![false; len],
}
}
pub fn set(&mut self, index: usize, value: T) -> bool {
if core::mem::replace(&mut self.initialized[index], true) {
false
} else {
unsafe { self.storage.as_mut_ptr().add(index).write(value) };
true
}
}
pub fn finish(mut self) -> Option<Vec<T>> {
if self.initialized.iter().all(|&x| x) {
let mut storage = core::mem::take(&mut self.storage);
unsafe { storage.set_len(storage.capacity()) };
Some(storage)
} else {
None
}
}
}
impl<T> Drop for PartialArray<T> {
fn drop(&mut self) {
for i in 0..self.storage.capacity() {
if self.initialized[i] {
unsafe { self.storage.as_mut_ptr().add(i).read() };
}
}
}
}
let len = d.map()?;
#[allow(clippy::cast_possible_truncation)]
let len = len.ok_or_else(|| {
minicbor::decode::Error::message("indefinite-length maps are not supported")
})? as usize;
let mut data = PartialArray::<ResultType>::new(len);
for _ in 0..len {
let index = d.u32()? as usize;
if index == 0 || index > len {
return Err(minicbor::decode::Error::message("invalid map index"));
}
let value = d.decode_with::<Context, DecodedType>(context)?;
if !data.set(index - 1, value.into()) {
return Err(minicbor::decode::Error::message("duplicate map key"));
}
}
if let Some(data) = data.finish() {
Ok(data)
} else {
Err(minicbor::decode::Error::message("missing map key"))
}
}