#![warn(missing_docs)]
pub mod addon;
pub mod lang;
pub mod modifications;
pub mod output;
pub mod pkg;
pub mod util;
pub mod versions;
use std::{fmt::Display, str::FromStr};
use anyhow::anyhow;
#[cfg(feature = "schema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub mod later {
	#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
	pub enum Later<T> {
		#[default]
		Empty,
		Full(T),
	}
	impl<T> Later<T> {
		#[inline(always)]
		pub fn new() -> Self {
			Self::Empty
		}
		#[inline(always)]
		pub fn fill(&mut self, value: T) {
			*self = Self::Full(value);
		}
		pub fn ensure_full(&mut self, f: impl Fn() -> T) {
			if self.is_empty() {
				self.fill(f());
			}
		}
		#[inline(always)]
		pub fn clear(&mut self) {
			*self = Self::Empty;
		}
		#[must_use]
		#[inline(always)]
		pub fn is_empty(&self) -> bool {
			matches!(self, Self::Empty)
		}
		#[must_use]
		#[inline(always)]
		pub fn is_full(&self) -> bool {
			matches!(self, Self::Full(..))
		}
		#[inline(always)]
		pub fn get(&self) -> &T {
			if let Self::Full(value) = self {
				value
			} else {
				self.fail();
			}
		}
		#[inline(always)]
		pub fn get_mut(&mut self) -> &mut T {
			if let Self::Full(value) = self {
				value
			} else {
				self.fail();
			}
		}
		#[inline(always)]
		pub fn get_val(self) -> T {
			if let Self::Full(value) = self {
				value
			} else {
				self.fail();
			}
		}
		#[inline(always)]
		pub fn into_option(self) -> Option<T> {
			match self {
				Self::Empty => None,
				Self::Full(val) => Some(val),
			}
		}
		fn fail(&self) -> ! {
			panic!("Value in Later<T> does not exist");
		}
	}
	impl<T: Clone> Later<T> {
		pub fn get_clone(&self) -> T {
			if let Self::Full(value) = self {
				value.clone()
			} else {
				self.fail();
			}
		}
	}
	#[cfg(test)]
	mod tests {
		use super::*;
		#[test]
		fn test_later_fill() {
			let mut later = Later::new();
			later.fill(7);
			later.get();
		}
		#[test]
		#[should_panic(expected = "Value in Later<T> does not exist")]
		fn test_later_fail() {
			let later: Later<i32> = Later::new();
			later.get();
		}
	}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum Side {
	Client,
	Server,
}
impl Side {
	pub fn parse_from_str(string: &str) -> Option<Self> {
		match string {
			"client" => Some(Self::Client),
			"server" => Some(Self::Server),
			_ => None,
		}
	}
}
impl FromStr for Side {
	type Err = anyhow::Error;
	fn from_str(s: &str) -> Result<Self, Self::Err> {
		Self::parse_from_str(s).ok_or(anyhow!("Not a valid side"))
	}
}
impl Display for Side {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		write!(
			f,
			"{}",
			match self {
				Self::Client => "client",
				Self::Server => "server",
			}
		)
	}
}