three-commas-scraper 0.2.7

3commas scraper
use crossbeam::atomic::AtomicCell;
use prometheus::core::{Atomic, Number};
use rust_decimal::prelude::ToPrimitive;
use std::{
  ops::{self},
  sync::atomic::Ordering,
};

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Decimal(rust_decimal::Decimal);

impl From<rust_decimal::Decimal> for Decimal {
  #[inline]
  fn from(value: rust_decimal::Decimal) -> Self {
    Decimal(value)
  }
}

impl From<Decimal> for rust_decimal::Decimal {
  #[inline]
  fn from(value: Decimal) -> Self {
    value.0
  }
}

impl ops::AddAssign for Decimal {
  #[inline]
  fn add_assign(&mut self, rhs: Self) {
    self.0.add_assign(rhs.0)
  }
}

impl ops::SubAssign for Decimal {
  #[inline]
  fn sub_assign(&mut self, rhs: Self) {
    self.0.sub_assign(rhs.0)
  }
}

pub struct AtomicDecimal(AtomicCell<Decimal>);

impl Number for Decimal {
  fn from_i64(v: i64) -> Self {
    rust_decimal::Decimal::from(v).into()
  }

  fn into_f64(self) -> f64 {
    self.0.to_f64().unwrap()
  }
}

impl Atomic for AtomicDecimal {
  type T = Decimal;

  fn new(val: Self::T) -> Self {
    AtomicDecimal(AtomicCell::new(val))
  }

  fn set(&self, val: Self::T) {
    self.0.store(val)
  }

  fn get(&self) -> Self::T {
    self.0.load()
  }

  fn inc_by(&self, delta: Self::T) {
    loop {
      let current = self.0.load();
      let new = Decimal(current.0 + delta.0);
      if self.0.compare_exchange(current, new).is_ok() {
        break;
      }
    }
  }

  fn dec_by(&self, delta: Self::T) {
    loop {
      let current = self.0.load();
      let new = Decimal(current.0 - delta.0);
      if self.0.compare_exchange(current, new).is_ok() {
        break;
      }
    }
  }
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Boolean(bool);

impl From<bool> for Boolean {
  #[inline]
  fn from(value: bool) -> Self {
    Boolean(value)
  }
}

impl From<Boolean> for bool {
  #[inline]
  fn from(value: Boolean) -> Self {
    value.0
  }
}

impl ops::AddAssign for Boolean {
  #[inline]
  #[allow(clippy::suspicious_op_assign_impl)]
  fn add_assign(&mut self, rhs: Self) {
    self.0 = self.0 || rhs.0
  }
}

impl ops::SubAssign for Boolean {
  #[inline]
  #[allow(clippy::suspicious_op_assign_impl)]
  fn sub_assign(&mut self, rhs: Self) {
    self.0 = self.0 && rhs.0
  }
}

pub struct AtomicBool(std::sync::atomic::AtomicBool);

impl Number for Boolean {
  fn from_i64(v: i64) -> Self {
    if v == 0 {
      Boolean(false)
    } else {
      Boolean(true)
    }
  }

  fn into_f64(self) -> f64 {
    if self.0 {
      1f64
    } else {
      0f64
    }
  }
}

impl Atomic for AtomicBool {
  type T = Boolean;

  fn new(val: Self::T) -> Self {
    AtomicBool(std::sync::atomic::AtomicBool::new(val.into()))
  }

  fn set(&self, val: Self::T) {
    self.0.store(val.0, Ordering::Release)
  }

  fn get(&self) -> Self::T {
    Boolean(self.0.load(Ordering::Acquire))
  }

  fn inc_by(&self, delta: Self::T) {
    loop {
      let current = self.0.load(Ordering::Acquire);
      let new = current && delta.0;
      if self
        .0
        .compare_exchange(current, new, Ordering::SeqCst, Ordering::Relaxed)
        .is_ok()
      {
        break;
      }
    }
  }

  fn dec_by(&self, delta: Self::T) {
    loop {
      let current = self.0.load(Ordering::Acquire);
      let new = current || delta.0;
      if self
        .0
        .compare_exchange(current, new, Ordering::SeqCst, Ordering::Relaxed)
        .is_ok()
      {
        break;
      }
    }
  }
}