nativeclick 0.26.9

Nativeclick is a pure Rust SDK for working with Clickhouse with the native protocol in async environments with minimal boilerplate and maximal performance.
Documentation
use std::fmt;

use crate::{
    Result, Value,
    convert::{FromSql, ToSql, unexpected_type},
    types::Type,
};

/// Wrapper type for Clickhouse `Int256` type.
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Debug, Default)]
#[allow(non_camel_case_types)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct i256(pub [u8; 32]);

impl i256 {
    /// Decimal text of the signed two's complement value (big-endian bytes).
    pub(crate) fn to_decimal(self) -> String {
        let negative = self.0[0] & 0x80 != 0;
        let mut bytes = self.0;
        if negative {
            // two's complement negation
            let mut carry = true;
            for byte in bytes.iter_mut().rev() {
                let (value, overflow) = (!*byte).overflowing_add(carry as u8);
                *byte = value;
                carry = carry && overflow;
            }
        }
        let mut digits = vec![];
        while bytes.iter().any(|x| *x != 0) {
            let mut remainder = 0u32;
            for byte in bytes.iter_mut() {
                let current = (remainder << 8) | *byte as u32;
                *byte = (current / 10) as u8;
                remainder = current % 10;
            }
            digits.push(b'0' + remainder as u8);
        }
        if digits.is_empty() {
            digits.push(b'0');
        }
        if negative {
            digits.push(b'-');
        }
        digits.reverse();
        String::from_utf8(digits).unwrap()
    }
}

impl From<i256> for u256 {
    fn from(i: i256) -> Self {
        u256(i.0)
    }
}

impl ToSql for i256 {
    fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
        Ok(Value::Int256(self))
    }
}

impl FromSql for i256 {
    fn from_sql(type_: &Type, value: Value) -> Result<Self> {
        if !matches!(type_, Type::Int256) {
            return Err(unexpected_type(type_));
        }
        match value {
            Value::Int256(x) => Ok(x),
            _ => unimplemented!(),
        }
    }
}

impl From<i256> for (u128, u128) {
    fn from(i: i256) -> Self {
        let mut buf = [0u8; 16];
        buf.copy_from_slice(&i.0[..16]);
        let n1 = u128::from_be_bytes(buf);
        buf.copy_from_slice(&i.0[16..]);
        let n2 = u128::from_be_bytes(buf);
        (n1, n2)
    }
}

impl From<(u128, u128)> for i256 {
    fn from(other: (u128, u128)) -> Self {
        let mut buf = [0u8; 32];
        buf[..16].copy_from_slice(&other.0.to_be_bytes()[..]);
        buf[16..].copy_from_slice(&other.1.to_be_bytes()[..]);
        i256(buf)
    }
}

impl fmt::Display for i256 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "0x")?;
        for b in self.0 {
            write!(f, "{b:02X}")?;
        }
        Ok(())
    }
}
/// Wrapper type for Clickhouse `UInt256` type.
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(non_camel_case_types)]
pub struct u256(pub [u8; 32]);

impl ToSql for u256 {
    fn to_sql(self, _type_hint: Option<&Type>) -> Result<Value> {
        Ok(Value::UInt256(self))
    }
}

impl FromSql for u256 {
    fn from_sql(type_: &Type, value: Value) -> Result<Self> {
        if !matches!(type_, Type::UInt256) {
            return Err(unexpected_type(type_));
        }
        match value {
            Value::UInt256(x) => Ok(x),
            _ => unimplemented!(),
        }
    }
}

impl From<u256> for i256 {
    fn from(u: u256) -> Self {
        i256(u.0)
    }
}

impl From<u256> for (u128, u128) {
    fn from(u: u256) -> Self {
        let mut buf = [0u8; 16];
        buf.copy_from_slice(&u.0[..16]);
        let n1 = u128::from_be_bytes(buf);
        buf.copy_from_slice(&u.0[16..]);
        let n2 = u128::from_be_bytes(buf);
        (n1, n2)
    }
}

impl From<(u128, u128)> for u256 {
    fn from(other: (u128, u128)) -> Self {
        let mut buf = [0u8; 32];
        buf[..16].copy_from_slice(&other.0.to_be_bytes()[..]);
        buf[16..].copy_from_slice(&other.1.to_be_bytes()[..]);
        u256(buf)
    }
}

impl fmt::Display for u256 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "0x")?;
        for b in self.0 {
            write!(f, "{b:02X}")?;
        }
        Ok(())
    }
}