#![warn(missing_docs)]
#![cfg_attr(doc, allow(unknown_lints))]
#![deny(rustdoc::all)]
use serde::{de::DeserializeSeed, Deserializer};
macro_rules! pub_use {
() => {
pub use crate::{asset::*, cid::*, handle::*, io::*, network_handle::*, server::*};
pub use anyhow;
pub use bones_schema::prelude::*;
pub use dashmap;
pub use path_absolutize::Absolutize;
pub use semver::Version;
};
}
pub_use!();
pub mod prelude {
pub_use!();
pub use super::{Maybe, Maybe::*};
}
mod asset;
mod cid;
mod handle;
mod io;
mod network_handle;
mod parse;
mod server;
#[derive(HasSchema, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Debug)]
#[type_data(SchemaMetaAssetLoader(maybe_loader))]
#[repr(C, u8)]
pub enum Maybe<T> {
#[default]
Unset,
Set(T),
}
impl<T> Maybe<T> {
#[inline]
pub fn option(self) -> Option<T> {
self.into()
}
#[inline]
pub fn is_set(&self) -> bool {
matches!(self, Maybe::Set(_))
}
#[inline]
pub fn is_unset(&self) -> bool {
matches!(self, Maybe::Unset)
}
#[inline]
pub fn is_some(&self) -> bool {
matches!(self, Maybe::Set(_))
}
#[inline]
pub fn is_none(&self) -> bool {
matches!(self, Maybe::Unset)
}
#[inline]
pub fn contains<U>(&self, x: &U) -> bool
where
U: PartialEq<T>,
{
match self {
Maybe::Set(y) => x == y,
Maybe::Unset => false,
}
}
#[inline]
pub fn as_ref(&self) -> Maybe<&T> {
match *self {
Maybe::Unset => Maybe::Unset,
Maybe::Set(ref x) => Maybe::Set(x),
}
}
#[inline]
pub fn as_mut(&mut self) -> Maybe<&mut T> {
match *self {
Maybe::Unset => Maybe::Unset,
Maybe::Set(ref mut x) => Maybe::Set(x),
}
}
#[inline]
#[track_caller]
pub fn expect(self, msg: &str) -> T {
self.option().expect(msg)
}
#[inline]
#[track_caller]
pub fn unwrap(self) -> T {
self.option().unwrap()
}
#[inline]
pub fn unwrap_or(self, default: T) -> T {
self.option().unwrap_or(default)
}
#[inline]
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
self.option().unwrap_or_else(f)
}
#[inline]
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Maybe<U> {
self.option().map(f).into()
}
#[inline]
pub fn and_then<U, F: FnOnce(T) -> Maybe<U>>(self, f: F) -> Maybe<U> {
self.option().and_then(|x| f(x).option()).into()
}
#[inline]
pub fn and<U>(self, optb: Maybe<U>) -> Maybe<U> {
self.option().and(optb.option()).into()
}
#[inline]
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Maybe<T> {
self.option().filter(predicate).into()
}
#[inline]
pub fn or(self, optb: Maybe<T>) -> Maybe<T> {
self.option().or(optb.option()).into()
}
#[inline]
pub fn or_else<F: FnOnce() -> Maybe<T>>(self, f: F) -> Maybe<T> {
self.option().or_else(|| f().option()).into()
}
#[inline]
pub fn xor(self, optb: Maybe<T>) -> Maybe<T> {
self.option().xor(optb.option()).into()
}
#[inline]
pub fn get_or_insert(&mut self, v: T) -> &mut T {
if let Maybe::Unset = self {
*self = Maybe::Set(v);
}
match self {
Maybe::Set(ref mut v) => v,
Maybe::Unset => unreachable!(),
}
}
#[inline]
pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
if let Maybe::Unset = self {
*self = Maybe::Set(f());
}
match self {
Maybe::Set(ref mut v) => v,
Maybe::Unset => unreachable!(),
}
}
#[inline]
pub fn take(&mut self) -> Maybe<T> {
std::mem::replace(self, Maybe::Unset)
}
#[inline]
pub fn replace(&mut self, value: T) -> Maybe<T> {
std::mem::replace(self, Maybe::Set(value))
}
#[inline]
pub fn zip<U>(self, other: Maybe<U>) -> Maybe<(T, U)> {
self.option().zip(other.option()).into()
}
#[inline]
pub unsafe fn unwrap_unchecked(self) -> T {
self.option().unwrap_unchecked()
}
#[inline]
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
self.option().map_or(default, f)
}
#[inline]
pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
self.option().map_or_else(default, f)
}
#[inline]
pub fn unwrap_or_default(self) -> T
where
T: Default,
{
self.option().unwrap_or_default()
}
#[inline]
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
self.option().ok_or(err)
}
#[inline]
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
self.option().ok_or_else(err)
}
}
impl<T> From<Maybe<T>> for Option<T> {
#[inline]
fn from(value: Maybe<T>) -> Self {
match value {
Maybe::Set(s) => Some(s),
Maybe::Unset => None,
}
}
}
impl<T> From<Option<T>> for Maybe<T> {
#[inline]
fn from(value: Option<T>) -> Self {
match value {
Some(s) => Maybe::Set(s),
None => Maybe::Unset,
}
}
}
fn maybe_loader(
ctx: &mut MetaAssetLoadCtx,
ptr: SchemaRefMut<'_>,
deserialzer: &mut dyn erased_serde::Deserializer,
) -> anyhow::Result<()> {
deserialzer.deserialize_option(MaybeVisitor { ctx, ptr })?;
Ok(())
}
struct MaybeVisitor<'a, 'srv> {
ctx: &'a mut MetaAssetLoadCtx<'srv>,
ptr: SchemaRefMut<'a>,
}
impl<'a, 'srv, 'de> serde::de::Visitor<'de> for MaybeVisitor<'a, 'srv> {
type Value = ();
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "an optional value")
}
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(())
}
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(())
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
unsafe {
self.ptr.as_ptr().cast::<u8>().write(1);
}
let value_offset = self.ptr.schema().field_offsets()[0].1;
let value_schema = self.ptr.schema().kind.as_enum().unwrap().variants[1]
.schema
.kind
.as_struct()
.unwrap()
.fields[0]
.schema;
let value_ref = unsafe {
SchemaRefMut::from_ptr_schema(self.ptr.as_ptr().add(value_offset), value_schema)
};
SchemaPtrLoadCtx {
ctx: self.ctx,
ptr: value_ref,
}
.deserialize(deserializer)
}
}