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

Code before:
        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(
            format!("Could not decode cube string: {}", input).into(),
        ))?;

        if !content.contains('(') && !content.contains(',') {
            return parse_point(content);
        }

        if !content.contains("),(") {
            return parse_zero_volume(content);
        }

        let point_vecs = content.split("),(").collect::<Vec<&str>>();
        if point_vecs.len() == 2 && !point_vecs.iter().any(|pv| pv.contains(',')) {
            return parse_one_dimensional_interval(point_vecs);
        }

        parse_multidimensional_interval(point_vecs)
    }
}

impl TryFrom<&[u8]> for PgCube {

Review comment (suggestion):
This should be a [`FromStr`](https://doc.rust-lang.org/stable/std/str/trait.FromStr.html) impl.

It's fine to have both, but it's surprising to have a `TryFrom<&str>` impl and not a `FromStr` impl. 

The only reason to do that is if `Self` wants to borrow from the string (think zero-copy parsing) which the `FromStr` trait doesn't support due to its lack of a lifetime bound.

Code after:
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)
    }
}

impl FromStr for PgCube {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let content = s
            .trim_start_matches('(')
            .trim_start_matches('[')
            .trim_end_matches(')')
            .trim_end_matches(']')
            .replace(' ', "");

        if !content.contains('(') && !content.contains(',') {
            return parse_point(&content);
        }

        if !content.contains("),(") {
            return parse_zero_volume(&content);
        }