use rbs::Value;
use std::cmp::Ordering;
pub use std::ops::Index;
pub trait AsProxy {
fn i32(&self) -> i32;
fn i64(&self) -> i64;
fn u32(&self) -> u32;
fn u64(&self) -> u64;
fn f64(&self) -> f64;
fn usize(&self) -> usize;
fn bool(&self) -> bool;
fn string(&self) -> String;
fn as_binary(&self) -> Vec<u8>;
}
impl AsProxy for Value {
fn i32(&self) -> i32 {
self.as_i64().unwrap_or_default() as i32
}
fn i64(&self) -> i64 {
self.as_i64().unwrap_or_default()
}
fn u32(&self) -> u32 {
self.as_u64().unwrap_or_default() as u32
}
fn u64(&self) -> u64 {
self.as_u64().unwrap_or_default()
}
fn f64(&self) -> f64 {
self.as_f64().unwrap_or_default()
}
fn string(&self) -> String {
match self {
Value::String(v) => v.to_string(),
Value::Ext(_, ext) => ext.as_string().unwrap_or_default(),
_ => self.to_string(),
}
}
fn bool(&self) -> bool {
self.as_bool().unwrap_or_default()
}
fn as_binary(&self) -> Vec<u8> {
match self {
Value::Binary(s) => s.to_owned(),
_ => vec![],
}
}
fn usize(&self) -> usize {
self.as_u64().unwrap_or_default() as usize
}
}
impl AsProxy for bool {
fn i32(&self) -> i32 {
if *self {
1
} else {
0
}
}
fn i64(&self) -> i64 {
if *self {
1
} else {
0
}
}
fn u32(&self) -> u32 {
if *self {
1
} else {
0
}
}
fn u64(&self) -> u64 {
if *self {
1
} else {
0
}
}
fn usize(&self) -> usize {
if *self {
1
} else {
0
}
}
fn f64(&self) -> f64 {
if *self {
1.0
} else {
0.0
}
}
fn bool(&self) -> bool {
*self
}
fn string(&self) -> String {
self.to_string()
}
fn as_binary(&self) -> Vec<u8> {
if *self {
vec![1u8]
} else {
vec![0u8]
}
}
}
impl AsProxy for String {
fn i32(&self) -> i32 {
self.parse().unwrap_or_default()
}
fn i64(&self) -> i64 {
self.parse().unwrap_or_default()
}
fn u32(&self) -> u32 {
self.parse().unwrap_or_default()
}
fn u64(&self) -> u64 {
self.parse().unwrap_or_default()
}
fn usize(&self) -> usize {
self.parse().unwrap_or_default()
}
fn f64(&self) -> f64 {
self.parse().unwrap_or_default()
}
fn bool(&self) -> bool {
self.parse().unwrap_or_default()
}
fn string(&self) -> String {
self.to_string()
}
fn as_binary(&self) -> Vec<u8> {
self.to_string().into_bytes()
}
}
impl AsProxy for str {
fn i32(&self) -> i32 {
self.parse().unwrap_or_default()
}
fn i64(&self) -> i64 {
self.parse().unwrap_or_default()
}
fn u32(&self) -> u32 {
self.parse().unwrap_or_default()
}
fn u64(&self) -> u64 {
self.parse().unwrap_or_default()
}
fn usize(&self) -> usize {
self.parse().unwrap_or_default()
}
fn f64(&self) -> f64 {
self.parse().unwrap_or_default()
}
fn bool(&self) -> bool {
self.parse().unwrap_or_default()
}
fn string(&self) -> String {
self.to_string()
}
fn as_binary(&self) -> Vec<u8> {
self.to_string().into_bytes()
}
}
macro_rules! as_number {
($ty:ty,$bool_expr:expr) => {
impl AsProxy for $ty {
fn i32(&self) -> i32 {
*self as i32
}
fn i64(&self) -> i64 {
*self as i64
}
fn u32(&self) -> u32 {
*self as u32
}
fn u64(&self) -> u64 {
*self as u64
}
fn usize(&self) -> usize {
*self as usize
}
fn f64(&self) -> f64 {
*self as f64
}
fn string(&self) -> String {
self.to_string()
}
fn bool(&self) -> bool {
if *self == $bool_expr {
true
} else {
false
}
}
fn as_binary(&self) -> Vec<u8> {
self.to_string().into_bytes()
}
}
};
}
as_number!(i8, 1i8);
as_number!(i16, 1i16);
as_number!(i32, 1i32);
as_number!(i64, 1i64);
as_number!(isize, 1isize);
as_number!(u8, 1u8);
as_number!(u16, 1u16);
as_number!(u32, 1u32);
as_number!(u64, 1u64);
as_number!(usize, 1usize);
as_number!(f32, 1.0);
as_number!(f64, 1.0);
pub trait PartialEq<Rhs: ?Sized = Self> {
#[must_use]
fn op_eq(&self, other: &Rhs) -> bool;
#[inline]
#[must_use]
fn op_ne(&self, other: &Rhs) -> bool {
!self.op_eq(other)
}
}
pub trait PartialOrd<Rhs: ?Sized = Self> {
#[must_use]
fn op_partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
#[inline]
#[must_use]
fn op_lt(&self, other: &Rhs) -> bool {
self.op_partial_cmp(other).eq(&Some(Ordering::Less))
}
#[inline]
#[must_use]
fn op_le(&self, other: &Rhs) -> bool {
let v = self.op_partial_cmp(other);
!v.eq(&None) | v.eq(&Some(Ordering::Greater))
}
#[inline]
fn op_gt(&self, other: &Rhs) -> bool {
self.op_partial_cmp(other).eq(&Some(Ordering::Greater))
}
#[inline]
#[must_use]
fn op_ge(&self, other: &Rhs) -> bool {
let v = self.op_partial_cmp(other);
v.eq(&Some(Ordering::Greater)) | v.eq(&Some(Ordering::Equal))
}
}
pub trait Add<Rhs = Self> {
type Output;
#[must_use]
fn op_add(self, rhs: Rhs) -> Self::Output;
}
pub trait Sub<Rhs = Self> {
type Output;
#[must_use]
fn op_sub(self, rhs: Rhs) -> Self::Output;
}
pub trait Mul<Rhs = Self> {
type Output;
#[must_use]
fn op_mul(self, rhs: Rhs) -> Self::Output;
}
pub trait Div<Rhs = Self> {
type Output;
#[must_use]
fn op_div(self, rhs: Rhs) -> Self::Output;
}
pub trait Rem<Rhs = Self> {
type Output;
#[must_use]
fn op_rem(self, rhs: Rhs) -> Self::Output;
}
pub trait Not {
type Output;
#[must_use]
fn op_not(self) -> Self::Output;
}
pub trait BitAnd<Rhs = Self> {
type Output;
#[must_use]
fn op_bitand(self, rhs: Rhs) -> Self::Output;
}
pub trait BitOr<Rhs = Self> {
type Output;
#[must_use]
fn op_bitor(self, rhs: Rhs) -> Self::Output;
}
pub trait BitXor<Rhs = Self> {
type Output;
#[must_use]
fn op_bitxor(self, rhs: Rhs) -> Self::Output;
}
pub trait OpsIndex<Idx: ?Sized> {
type Output: ?Sized;
#[track_caller]
fn index(&self, index: Idx) -> &Self::Output;
}
pub trait OpsIndexMut<Idx: ?Sized>: OpsIndex<Idx> {
#[track_caller]
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}
pub trait From<T>: Sized {
fn op_from(_: T) -> Self;
}
pub trait Neg {
type Output;
#[must_use = "this returns the result of the operation, without modifying the original"]
fn neg(self) -> Self::Output;
}
pub trait StrMethods {
fn contains_str(self, s: &str) -> bool;
fn starts_with(self, other: &str) -> bool;
fn ends_with(self, other: &str) -> bool;
}
#[cfg(test)]
mod test {
use crate::ops::AsProxy;
use rbs::{value};
#[test]
fn test_cast() {
let b = value!(u64::MAX);
assert_eq!(b.i64(), -1);
let b = value!(100u64);
assert_eq!(b.i64(), 100i64);
}
}