pub mod bytes_builder;
pub mod map;
pub mod map_builder;
pub mod text;
pub mod text_builder;
pub mod vector;
pub mod vector_builder;
use axum::body::Bytes as AxumBytes;
use axum::response::{IntoResponse, Response};
use bb8_redis::redis::{
ErrorKind, FromRedisValue, RedisError, RedisResult, RedisWrite, ToRedisArgs, Value,
};
pub use bytes_builder::BytesBuilder;
use chrono::{Date, DateTime, Utc};
use pyo3::types::PyBytes;
use pyo3::{IntoPy, Py, PyAny, PyObject, Python, ToPyObject};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{Debug, Formatter};
use std::ops::Deref;
pub use map::Map;
pub use map_builder::MapBuilder;
pub use text::Text;
pub use text_builder::TextBuilder;
pub use vector::Vector;
pub use vector_builder::VectorBuilder;
pub trait Puff: Clone + Send + Sync + 'static {
fn puff(&self) -> Self {
self.clone()
}
}
#[derive(Clone, PartialEq, Hash)]
pub struct Bytes(AxumBytes);
impl Debug for Bytes {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
base64::encode(self.as_slice()).fmt(f)
}
}
impl Bytes {
pub fn as_slice(&self) -> &[u8] {
&self.0[..]
}
}
impl Serialize for Bytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serde_bytes::Bytes::new(&self.0).serialize(serializer)
}
}
impl FromRedisValue for Bytes {
fn from_redis_value(v: &Value) -> RedisResult<Self> {
match v {
Value::Data(v) => Ok(Bytes::copy_from_slice(v.as_slice())),
Value::Okay => Ok("OK".into()),
Value::Status(ref val) => Ok(val.to_string().into()),
val => Err(RedisError::from((
ErrorKind::TypeError,
"Response was of incompatible type",
format!(
"Response type not bytes compatible. (response was {:?})",
val
),
))),
}
}
}
impl ToRedisArgs for Bytes {
fn write_redis_args<W>(&self, out: &mut W)
where
W: ?Sized + RedisWrite,
{
out.write_arg(self.0.as_ref())
}
}
impl IntoResponse for Bytes {
fn into_response(self) -> Response {
self.0.into_response()
}
}
impl<'de> Deserialize<'de> for Bytes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
serde_bytes::ByteBuf::deserialize(deserializer)
.map(|v| Bytes(AxumBytes::from(v.into_vec())))
}
}
impl Bytes {
pub fn copy_from_slice(slice: &[u8]) -> Self {
Self(AxumBytes::copy_from_slice(slice))
}
pub fn from_vec(slice: Vec<u8>) -> Self {
Self(slice.into())
}
pub fn into_bytes(self) -> AxumBytes {
self.0
}
}
impl<T: Into<AxumBytes>> From<T> for Bytes {
fn from(v: T) -> Self {
Bytes(v.into())
}
}
impl IntoPy<Py<PyBytes>> for Bytes {
fn into_py(self, py: Python<'_>) -> Py<PyBytes> {
PyBytes::new(py, &self).into_py(py)
}
}
impl IntoPy<Py<PyAny>> for Bytes {
fn into_py(self, py: Python<'_>) -> Py<PyAny> {
PyBytes::new(py, &self).to_object(py)
}
}
impl ToPyObject for Bytes {
fn to_object(&self, py: Python<'_>) -> PyObject {
self.clone().into_py(py)
}
}
impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Hash, Debug)]
pub struct UtcDateTime(DateTime<Utc>);
impl Deref for UtcDateTime {
type Target = DateTime<Utc>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl UtcDateTime {
pub fn new(dt: DateTime<Utc>) -> Self {
Self(dt)
}
pub fn to_chrono(&self) -> DateTime<Utc> {
self.0.clone()
}
}
impl IntoPy<Py<PyAny>> for UtcDateTime {
fn into_py(self, py: Python<'_>) -> Py<PyAny> {
pyo3_chrono::NaiveDateTime::from(self.0.naive_local()).into_py(py)
}
}
#[derive(Clone)]
pub struct UtcDate(Date<Utc>);
impl IntoPy<Py<PyAny>> for UtcDate {
fn into_py(self, py: Python<'_>) -> Py<PyAny> {
pyo3_chrono::NaiveDate::from(self.0.naive_local()).into_py(py)
}
}
impl Deref for UtcDate {
type Target = Date<Utc>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl UtcDate {
pub fn new(dt: Date<Utc>) -> Self {
Self(dt)
}
}
impl<T: Puff, T2: Puff> Puff for (T, T2) {
fn puff(&self) -> Self {
(self.0.puff(), self.1.puff())
}
}
impl<T: Puff, T2: Puff, T3: Puff> Puff for (T, T2, T3) {
fn puff(&self) -> Self {
(self.0.puff(), self.1.puff(), self.2.puff())
}
}
impl<T: Puff, T2: Puff, T3: Puff, T4: Puff> Puff for (T, T2, T3, T4) {
fn puff(&self) -> Self {
(self.0.puff(), self.1.puff(), self.2.puff(), self.3.puff())
}
}
impl Puff for UtcDate {}
impl Puff for UtcDateTime {}
impl<T: Puff> Puff for Option<T> {}
impl Puff for usize {}
impl Puff for f64 {}
impl Puff for f32 {}
impl Puff for u8 {}
impl Puff for u16 {}
impl Puff for u32 {}
impl Puff for u64 {}
impl Puff for i8 {}
impl Puff for i32 {}
impl Puff for i64 {}
impl Puff for bool {}
impl Puff for () {}
impl Puff for Bytes {}