#![cfg_attr(not(any(feature = "std", test)), no_std)]
extern crate alloc;
pub mod prelude;
use alloc::string::{String, ToString};
use core::fmt;
use core::str::FromStr;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct ParseEnumError {
kind: &'static str,
input: String,
}
impl ParseEnumError {
#[must_use]
#[inline]
pub fn new(kind: &'static str, input: impl Into<String>) -> Self {
Self {
kind,
input: input.into(),
}
}
#[must_use]
#[inline]
pub const fn kind(&self) -> &'static str {
self.kind
}
#[must_use]
#[inline]
pub fn input(&self) -> &str {
&self.input
}
}
impl fmt::Display for ParseEnumError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "invalid {} value: {:?}", self.kind, self.input)
}
}
impl core::error::Error for ParseEnumError {}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[repr(u8)]
#[non_exhaustive]
pub enum UnderlyingAssetType {
Crypto = 0,
#[default]
Stock = 1,
Forex = 2,
Commodity = 3,
Bond = 4,
Other = 5,
Future = 6,
Forward = 7,
}
impl UnderlyingAssetType {
#[must_use]
#[inline]
pub const fn is_stock(&self) -> bool {
matches!(self, Self::Stock)
}
#[must_use]
#[inline]
pub const fn is_crypto(&self) -> bool {
matches!(self, Self::Crypto)
}
#[must_use]
#[inline]
pub const fn is_forex(&self) -> bool {
matches!(self, Self::Forex)
}
#[must_use]
#[inline]
pub const fn is_commodity(&self) -> bool {
matches!(self, Self::Commodity)
}
#[must_use]
#[inline]
pub const fn is_bond(&self) -> bool {
matches!(self, Self::Bond)
}
#[must_use]
#[inline]
pub const fn is_future(&self) -> bool {
matches!(self, Self::Future)
}
#[must_use]
#[inline]
pub const fn is_forward(&self) -> bool {
matches!(self, Self::Forward)
}
#[must_use]
#[inline]
pub const fn as_str(&self) -> &'static str {
match self {
Self::Crypto => "Crypto",
Self::Stock => "Stock",
Self::Forex => "Forex",
Self::Commodity => "Commodity",
Self::Bond => "Bond",
Self::Other => "Other",
Self::Future => "Future",
Self::Forward => "Forward",
}
}
pub const ALL: &'static [Self] = &[
Self::Crypto,
Self::Stock,
Self::Forex,
Self::Commodity,
Self::Bond,
Self::Other,
Self::Future,
Self::Forward,
];
}
impl fmt::Display for UnderlyingAssetType {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for UnderlyingAssetType {
type Err = ParseEnumError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"crypto" => Ok(Self::Crypto),
"stock" => Ok(Self::Stock),
"forex" => Ok(Self::Forex),
"commodity" => Ok(Self::Commodity),
"bond" => Ok(Self::Bond),
"other" => Ok(Self::Other),
"future" => Ok(Self::Future),
"forward" => Ok(Self::Forward),
_ => Err(ParseEnumError::new("UnderlyingAssetType", s)),
}
}
}
impl TryFrom<&str> for UnderlyingAssetType {
type Error = ParseEnumError;
#[inline]
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::from_str(value)
}
}
impl TryFrom<u8> for UnderlyingAssetType {
type Error = ParseEnumError;
#[inline]
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Crypto),
1 => Ok(Self::Stock),
2 => Ok(Self::Forex),
3 => Ok(Self::Commodity),
4 => Ok(Self::Bond),
5 => Ok(Self::Other),
6 => Ok(Self::Future),
7 => Ok(Self::Forward),
other => Err(ParseEnumError::new(
"UnderlyingAssetType",
other.to_string(),
)),
}
}
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[repr(u8)]
#[non_exhaustive]
pub enum Action {
#[default]
Buy = 0,
Sell = 1,
Other = 2,
}
impl Action {
#[must_use]
#[inline]
pub const fn is_buy(&self) -> bool {
matches!(self, Self::Buy)
}
#[must_use]
#[inline]
pub const fn is_sell(&self) -> bool {
matches!(self, Self::Sell)
}
#[must_use]
#[inline]
pub const fn as_str(&self) -> &'static str {
match self {
Self::Buy => "Buy",
Self::Sell => "Sell",
Self::Other => "Other",
}
}
pub const ALL: &'static [Self] = &[Self::Buy, Self::Sell, Self::Other];
#[must_use]
#[inline]
pub const fn opposite(&self) -> Self {
match self {
Self::Buy => Self::Sell,
Self::Sell => Self::Buy,
Self::Other => Self::Other,
}
}
}
impl fmt::Display for Action {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for Action {
type Err = ParseEnumError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"buy" => Ok(Self::Buy),
"sell" => Ok(Self::Sell),
"other" => Ok(Self::Other),
_ => Err(ParseEnumError::new("Action", s)),
}
}
}
impl TryFrom<&str> for Action {
type Error = ParseEnumError;
#[inline]
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::from_str(value)
}
}
impl TryFrom<u8> for Action {
type Error = ParseEnumError;
#[inline]
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Buy),
1 => Ok(Self::Sell),
2 => Ok(Self::Other),
other => Err(ParseEnumError::new("Action", other.to_string())),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[repr(u8)]
pub enum Side {
#[default]
Long = 0,
Short = 1,
}
impl Side {
#[must_use]
#[inline]
pub const fn is_long(&self) -> bool {
matches!(self, Self::Long)
}
#[must_use]
#[inline]
pub const fn is_short(&self) -> bool {
matches!(self, Self::Short)
}
#[must_use]
#[inline]
pub const fn opposite(&self) -> Self {
match self {
Self::Long => Self::Short,
Self::Short => Self::Long,
}
}
#[must_use]
#[inline]
pub const fn as_str(&self) -> &'static str {
match self {
Self::Long => "Long",
Self::Short => "Short",
}
}
pub const ALL: &'static [Self] = &[Self::Long, Self::Short];
}
impl fmt::Display for Side {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl fmt::Debug for Side {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Long => write!(f, "Side::Long"),
Self::Short => write!(f, "Side::Short"),
}
}
}
impl FromStr for Side {
type Err = ParseEnumError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"long" => Ok(Self::Long),
"short" => Ok(Self::Short),
_ => Err(ParseEnumError::new("Side", s)),
}
}
}
impl TryFrom<&str> for Side {
type Error = ParseEnumError;
#[inline]
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::from_str(value)
}
}
impl TryFrom<u8> for Side {
type Error = ParseEnumError;
#[inline]
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Long),
1 => Ok(Self::Short),
other => Err(ParseEnumError::new("Side", other.to_string())),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[repr(u8)]
pub enum OptionStyle {
#[default]
Call = 0,
Put = 1,
}
impl OptionStyle {
#[must_use]
#[inline]
pub const fn is_call(&self) -> bool {
matches!(self, Self::Call)
}
#[must_use]
#[inline]
pub const fn is_put(&self) -> bool {
matches!(self, Self::Put)
}
#[must_use]
#[inline]
pub const fn opposite(&self) -> Self {
match self {
Self::Call => Self::Put,
Self::Put => Self::Call,
}
}
#[must_use]
#[inline]
pub const fn as_str(&self) -> &'static str {
match self {
Self::Call => "Call",
Self::Put => "Put",
}
}
pub const ALL: &'static [Self] = &[Self::Call, Self::Put];
}
impl fmt::Display for OptionStyle {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl fmt::Debug for OptionStyle {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Call => write!(f, "OptionStyle::Call"),
Self::Put => write!(f, "OptionStyle::Put"),
}
}
}
impl FromStr for OptionStyle {
type Err = ParseEnumError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"call" => Ok(Self::Call),
"put" => Ok(Self::Put),
_ => Err(ParseEnumError::new("OptionStyle", s)),
}
}
}
impl TryFrom<&str> for OptionStyle {
type Error = ParseEnumError;
#[inline]
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::from_str(value)
}
}
impl TryFrom<u8> for OptionStyle {
type Error = ParseEnumError;
#[inline]
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Call),
1 => Ok(Self::Put),
other => Err(ParseEnumError::new("OptionStyle", other.to_string())),
}
}
}
#[cfg(feature = "proptest")]
mod proptest_support {
use super::{Action, OptionStyle, Side, UnderlyingAssetType};
use proptest::prelude::*;
impl Arbitrary for UnderlyingAssetType {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
prop_oneof![
Just(Self::Crypto),
Just(Self::Stock),
Just(Self::Forex),
Just(Self::Commodity),
Just(Self::Bond),
Just(Self::Other),
Just(Self::Future),
Just(Self::Forward),
]
.boxed()
}
}
impl Arbitrary for Action {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
prop_oneof![Just(Self::Buy), Just(Self::Sell), Just(Self::Other)].boxed()
}
}
impl Arbitrary for Side {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
prop_oneof![Just(Self::Long), Just(Self::Short)].boxed()
}
}
impl Arbitrary for OptionStyle {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
prop_oneof![Just(Self::Call), Just(Self::Put)].boxed()
}
}
}