Repository: launchbadge/sqlx
File: sqlx-postgres/src/types/cube.rs (Rust)

Code before:
use crate::types::Type;
use crate::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
use sqlx_core::Error;

const BYTE_WIDTH: usize = 8;
const CUBE_TYPE_ZERO_VOLUME: usize = 128;
const CUBE_TYPE_DEFAULT: usize = 0;
const CUBE_DIMENSION_ONE: usize = 1;
const DIMENSIONALITY_POSITION: usize = 3;
const START_INDEX: usize = 4;

#[derive(Debug, Clone, PartialEq)]
pub enum PgCube {
    Point(f64),
    ZeroVolume(Vec<f64>),
    OneDimensionInterval(f64, f64),
    MultiDimension(Vec<Vec<f64>>),
}

impl Type<Postgres> for PgCube {
    fn type_info() -> PgTypeInfo {
        PgTypeInfo::with_name("cube")
    }
}

impl<'r> Decode<'r, Postgres> for PgCube {
    fn decode(value: PgValueRef<'r>) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
        match value.format() {
            PgValueFormat::Text => Ok(PgCube::try_from(value.as_str()?)?),
            PgValueFormat::Binary => Ok(PgCube::try_from(value.as_bytes()?)?),
        }
    }
}

impl<'q> Encode<'q, Postgres> for PgCube {
    fn produces(&self) -> Option<PgTypeInfo> {
        Some(PgTypeInfo::with_name("cube"))
    }

    fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
        buf.extend_from_slice(&self.serialize());

        IsNull::No
    }
}

impl TryFrom<&str> for PgCube {
    type Error = Error;

    fn try_from(input: &str) -> Result<Self, Self::Error> {
        let content = &input.get(1..input.len() - 1).ok_or(Error::Decode(

Review comment (suggestion):
You may want to consider implementing [`PgHasArrayType`](https://docs.rs/sqlx/latest/sqlx/postgres/trait.PgHasArrayType.html) so `Vec<PgCube>` works too.

Note that the actual name for the array type would be `_cube` (that's just how Postgres does array types internally).

Code after:
use crate::error::BoxDynError;
use crate::types::Type;
use crate::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
use sqlx_core::Error;
use std::str::FromStr;

const BYTE_WIDTH: usize = 8;
const CUBE_TYPE_ZERO_VOLUME: usize = 128;
const CUBE_TYPE_DEFAULT: usize = 0;
const CUBE_DIMENSION_ONE: usize = 1;
const DIMENSIONALITY_POSITION: usize = 3;
const START_INDEX: usize = 4;

#[derive(Debug, Clone, PartialEq)]
pub enum PgCube {
    Point(f64),
    ZeroVolume(Vec<f64>),
    OneDimensionInterval(f64, f64),
    MultiDimension(Vec<Vec<f64>>),
}

impl Type<Postgres> for PgCube {
    fn type_info() -> PgTypeInfo {
        PgTypeInfo::with_name("cube")
    }
}

impl PgHasArrayType for PgCube {
    fn array_type_info() -> PgTypeInfo {
        PgTypeInfo::with_name("_cube")
    }
}

impl<'r> Decode<'r, Postgres> for PgCube {
    fn decode(value: PgValueRef<'r>) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
        match value.format() {
            PgValueFormat::Text => Ok(PgCube::from_str(value.as_str()?)?),
            PgValueFormat::Binary => Ok(pg_cube_from_bytes(value.as_bytes()?)?),
        }
    }
}

impl<'q> Encode<'q, Postgres> for PgCube {
    fn produces(&self) -> Option<PgTypeInfo> {
        Some(PgTypeInfo::with_name("cube"))
    }

    fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
        self.serialize(buf)?;
        Ok(IsNull::No)
    }