vaticle / typedb

TypeDB: the polymorphic database powered by types
https://typedb.com
Mozilla Public License 2.0
3.72k stars 337 forks source link

Do encoding/decoding through traits, layout schema validation #7076

Closed krishnangovindraj closed 1 month ago

krishnangovindraj commented 1 month ago

Usage and product changes

We refactor the encoding package to replace the TypeVertex/TypeEdge/TypeVertexProperty/TypeEdgeProperty constructor methods ( buildX newX , buildprefix* etc) with 'TypeXEncoding' traits.

The TypeXPropertyEncoding traits include build & decode methods for the value type of the property. This organises scattered encoding/decoding logic across TypeManager & free serialize/deserialize methods.

There are also some elements of schema validation introduced.

Implementation

The TypeXEncoding traits

The TypeVertex constructors for EntityType goes from the macro generated methods:


type_vertex_constructors!(
    new_vertex_entity_type,
    build_vertex_entity_type,
    build_vertex_entity_type_prefix,
    is_vertex_entity_type,
    Prefix::VertexEntityType
);

to a TypeVertexEncoding trait implementation + an implementation for EntityType:

// Trait:
// This had to be split in two to support `ObjectType`s
pub trait TypeVertexEncoding<'a> : Sized {

    fn from_vertex(vertex: TypeVertex<'a>) -> Result<Self, EncodingError>;

    fn from_bytes(bytes: Bytes<'a, BUFFER_KEY_INLINE>) -> Result<Self, EncodingError> {
        Self::from_vertex(TypeVertex::new(bytes))
    }

    fn into_vertex(self) -> TypeVertex<'a>;
}

pub trait PrefixedTypeVertexEncoding<'a> : TypeVertexEncoding<'a>{
    const PREFIX: Prefix;

    fn build_from_type_id(type_id: TypeID) -> Self {
        Self::from_vertex(TypeVertex::build(Self::PREFIX.prefix_id(), type_id)).unwrap()
    }

    fn prefix_for_kind() -> StorageKey<'static, { TypeVertex::LENGTH_PREFIX }> {
        build_type_vertex_prefix_key(Self::PREFIX)
    }

    fn is_decodable_from_key(key: StorageKeyReference<'_>) -> bool {
        key.keyspace_id() == EncodingKeyspace::Schema.id() &&
            Self::is_decodable_from(Bytes::Reference(key.byte_ref()))
    }

    fn is_decodable_from(bytes: Bytes<'_, BUFFER_KEY_INLINE>) -> bool {
        bytes.length() == TypeVertex::LENGTH
            && TypeVertex::new(bytes).prefix() == Self::PREFIX
    }
}

// Implementation:
impl <'a> PrefixedTypeVertexEncoding<'a> for EntityType<'a> {
    const PREFIX: Prefix = VertexEntityType;
}
impl<'a> TypeVertexEncoding<'a> for EntityType<'a> {
    fn from_vertex(vertex: TypeVertex<'a>) -> Result<Self, EncodingError> {
        debug_assert!(Self::PREFIX == VertexEntityType);
        if vertex.prefix() != Prefix::VertexEntityType {
            Err(UnexpectedPrefix { expected_prefix: Prefix::VertexEntityType, actual_prefix: vertex.prefix() })
        } else {
            Ok(EntityType { vertex })
        }
    }

    fn into_vertex(self) -> TypeVertex<'a> {
        self.vertex
    }
}

Example of the encode/decode methods for a property value:

impl<'a> TypeVertexPropertyEncoding<'a> for Label<'a> {
    const INFIX: Infix = Infix::PropertyLabel;

    fn from_value_bytes<'b>(value: ByteReference<'b>) -> Self {
        let string_bytes = StringBytes::new(Bytes::<LABEL_SCOPED_NAME_STRING_INLINE>::Reference(value));
        Label::parse_from(string_bytes)
    }

    fn to_value_bytes(self) -> Option<Bytes<'a, BUFFER_VALUE_INLINE>> {
        Some(Bytes::Array(ByteArray::from(self.scoped_name().bytes())))
    }
}
vaticle-bot commented 1 month ago

PR Review Checklist

Do not edit the content of this comment. The PR reviewer should simply update this comment by ticking each review item below, as they get completed.


Trivial Change

Code

Architecture