This is an automated email from the ASF dual-hosted git repository.

xiaokang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-graphar.git


The following commit(s) were added to refs/heads/main by this push:
     new 79967810 feat(Rust): add `Property` support (#830)
79967810 is described below

commit 79967810bc631d0a84354468569f8331477c3971
Author: Jinye Wu <[email protected]>
AuthorDate: Wed Jan 21 11:48:31 2026 +0800

    feat(Rust): add `Property` support (#830)
    
    * support property
    
    * make clippy happy
---
 rust/include/graphar_rs.h |  36 +++-
 rust/src/ffi.rs           | 119 ++++++++++++-
 rust/src/graphar_rs.cc    |  51 +++++-
 rust/src/lib.rs           |  12 +-
 rust/src/property.rs      | 432 ++++++++++++++++++++++++++++++++++++++++++++++
 rust/src/types.rs         |  10 +-
 6 files changed, 654 insertions(+), 6 deletions(-)

diff --git a/rust/include/graphar_rs.h b/rust/include/graphar_rs.h
index e654c7ea..f04ae645 100644
--- a/rust/include/graphar_rs.h
+++ b/rust/include/graphar_rs.h
@@ -19,10 +19,44 @@
 
 #pragma once
 
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "graphar/fwd.h"
+#include "graphar/graph_info.h"
 #include "graphar/types.h"
 #include "rust/cxx.h"
 
+namespace graphar {
+using SharedPropertyGroup = std::shared_ptr<PropertyGroup>;
+}
+
 namespace graphar_rs {
 rust::String to_type_name(const graphar::DataType &type);
-}
\ No newline at end of file
+
+std::unique_ptr<graphar::Property>
+new_property(const std::string &name, std::shared_ptr<graphar::DataType> type,
+             bool is_primary, bool is_nullable,
+             graphar::Cardinality cardinality);
+const std::string &property_get_name(const graphar::Property &prop);
+const std::shared_ptr<graphar::DataType> &
+property_get_type(const graphar::Property &prop);
+bool property_is_primary(const graphar::Property &prop);
+bool property_is_nullable(const graphar::Property &prop);
+graphar::Cardinality property_get_cardinality(const graphar::Property &prop);
+std::unique_ptr<graphar::Property>
+property_clone(const graphar::Property &prop);
+
+void property_vec_push_property(std::vector<graphar::Property> &properties,
+                                std::unique_ptr<graphar::Property> prop);
+void property_vec_emplace_property(std::vector<graphar::Property> &properties,
+                                   const std::string &name,
+                                   std::shared_ptr<graphar::DataType> type,
+                                   bool is_primary, bool is_nullable,
+                                   graphar::Cardinality cardinality);
+
+void property_group_vec_push_property_group(
+    std::vector<graphar::SharedPropertyGroup> &property_groups,
+    std::shared_ptr<graphar::PropertyGroup> property_group);
+} // namespace graphar_rs
diff --git a/rust/src/ffi.rs b/rust/src/ffi.rs
index a6ffe000..a649f3d5 100644
--- a/rust/src/ffi.rs
+++ b/rust/src/ffi.rs
@@ -15,15 +15,44 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use cxx::{ExternType, SharedPtr};
+
+/// A shared pointer wrapper for `graphar::PropertyGroup`.
+#[repr(transparent)]
+pub struct SharedPropertyGroup(pub(crate) SharedPtr<graphar::PropertyGroup>);
+
+unsafe impl ExternType for SharedPropertyGroup {
+    type Id = cxx::type_id!("graphar::SharedPropertyGroup");
+    type Kind = cxx::kind::Opaque;
+}
+
 #[cxx::bridge(namespace = "graphar")]
 pub(crate) mod graphar {
     extern "C++" {
         include!("graphar_rs.h");
     }
 
+    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+    #[repr(i32)]
+    /// File format for GraphAr chunk files.
+    enum FileType {
+        /// CSV format.
+        #[cxx_name = "CSV"]
+        Csv = 0,
+        /// Parquet format.
+        #[cxx_name = "PARQUET"]
+        Parquet = 1,
+        /// ORC format.
+        #[cxx_name = "ORC"]
+        Orc = 2,
+        /// JSON format.
+        #[cxx_name = "JSON"]
+        Json = 3,
+    }
+
     /// The main data type enumeration used by GraphAr.
     #[derive(Debug, Clone, Copy, PartialEq, Eq)]
-    #[repr(u32)]
+    #[repr(i32)]
     enum Type {
         /// Boolean.
         #[cxx_name = "BOOL"]
@@ -59,9 +88,28 @@ pub(crate) mod graphar {
         #[cxx_name = "MAX_ID"]
         MaxId,
     }
-    // C++ Enum
+
+    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+    #[repr(i32)]
+    /// Cardinality of a property.
+    ///
+    /// This defines how multiple values are handled for a given property key.
+    enum Cardinality {
+        /// A single value.
+        #[cxx_name = "SINGLE"]
+        Single = 0,
+        /// A list of values.
+        #[cxx_name = "LIST"]
+        List = 1,
+        /// A set of values.
+        #[cxx_name = "SET"]
+        Set = 2,
+    }
+
     unsafe extern "C++" {
+        type FileType;
         type Type;
+        type Cardinality;
     }
 
     // `DataType`
@@ -84,4 +132,71 @@ pub(crate) mod graphar {
         fn timestamp() -> &'static SharedPtr<DataType>;
         fn list(inner: &SharedPtr<DataType>) -> SharedPtr<DataType>;
     }
+
+    // `Property`
+    unsafe extern "C++" {
+        type Property;
+
+        #[namespace = "graphar_rs"]
+        fn new_property(
+            name: &CxxString,
+            type_: SharedPtr<DataType>,
+            is_primary: bool,
+            is_nullable: bool,
+            cardinality: Cardinality,
+        ) -> UniquePtr<Property>;
+        #[namespace = "graphar_rs"]
+        fn property_get_name(prop: &Property) -> &CxxString;
+        #[namespace = "graphar_rs"]
+        fn property_get_type(prop: &Property) -> &SharedPtr<DataType>;
+        #[namespace = "graphar_rs"]
+        fn property_is_primary(prop: &Property) -> bool;
+        #[namespace = "graphar_rs"]
+        fn property_is_nullable(prop: &Property) -> bool;
+        #[namespace = "graphar_rs"]
+        fn property_get_cardinality(prop: &Property) -> Cardinality;
+        #[namespace = "graphar_rs"]
+        fn property_clone(prop: &Property) -> UniquePtr<Property>;
+
+        #[namespace = "graphar_rs"]
+        fn property_vec_push_property(
+            properties: Pin<&mut CxxVector<Property>>,
+            prop: UniquePtr<Property>,
+        );
+
+        #[namespace = "graphar_rs"]
+        fn property_vec_emplace_property(
+            properties: Pin<&mut CxxVector<Property>>,
+            name: &CxxString,
+            data_type: SharedPtr<DataType>,
+            is_primary: bool,
+            is_nullable: bool,
+            cardinality: Cardinality,
+        );
+    }
+
+    // `PropertyGroup`
+    unsafe extern "C++" {
+        type PropertyGroup;
+
+        fn GetProperties(&self) -> &CxxVector<Property>;
+        fn HasProperty(&self, property_name: &CxxString) -> bool;
+
+        fn CreatePropertyGroup(
+            properties: &CxxVector<Property>,
+            file_type: FileType,
+            prefix: &CxxString,
+        ) -> SharedPtr<PropertyGroup>;
+
+        #[namespace = "graphar_rs"]
+        fn property_group_vec_push_property_group(
+            property_groups: Pin<&mut CxxVector<SharedPropertyGroup>>,
+            property_group: SharedPtr<PropertyGroup>,
+        );
+    }
+
+    unsafe extern "C++" {
+        type SharedPropertyGroup = crate::ffi::SharedPropertyGroup;
+    }
+    impl CxxVector<SharedPropertyGroup> {}
 }
diff --git a/rust/src/graphar_rs.cc b/rust/src/graphar_rs.cc
index 88cdf6f9..15c138cc 100644
--- a/rust/src/graphar_rs.cc
+++ b/rust/src/graphar_rs.cc
@@ -19,8 +19,57 @@
 
 #include "graphar_rs.h"
 
+#include <utility>
+
 namespace graphar_rs {
 rust::String to_type_name(const graphar::DataType &type) {
   return rust::String(type.ToTypeName());
 }
-} // namespace graphar_rs
\ No newline at end of file
+
+std::unique_ptr<graphar::Property>
+new_property(const std::string &name, std::shared_ptr<graphar::DataType> type,
+             bool is_primary, bool is_nullable,
+             graphar::Cardinality cardinality) {
+  return std::make_unique<graphar::Property>(name, type, is_primary,
+                                             is_nullable, cardinality);
+}
+const std::string &property_get_name(const graphar::Property &prop) {
+  return prop.name;
+}
+const std::shared_ptr<graphar::DataType> &
+property_get_type(const graphar::Property &prop) {
+  return prop.type;
+}
+bool property_is_primary(const graphar::Property &prop) {
+  return prop.is_primary;
+}
+bool property_is_nullable(const graphar::Property &prop) {
+  return prop.is_nullable;
+}
+graphar::Cardinality property_get_cardinality(const graphar::Property &prop) {
+  return prop.cardinality;
+}
+std::unique_ptr<graphar::Property>
+property_clone(const graphar::Property &prop) {
+  return std::make_unique<graphar::Property>(prop);
+}
+
+void property_vec_push_property(std::vector<graphar::Property> &properties,
+                                std::unique_ptr<graphar::Property> prop) {
+  properties.emplace_back(*prop);
+}
+
+void property_vec_emplace_property(std::vector<graphar::Property> &properties,
+                                   const std::string &name,
+                                   std::shared_ptr<graphar::DataType> type,
+                                   bool is_primary, bool is_nullable,
+                                   graphar::Cardinality cardinality) {
+  properties.emplace_back(name, type, is_primary, is_nullable, cardinality);
+}
+
+void property_group_vec_push_property_group(
+    std::vector<graphar::SharedPropertyGroup> &property_groups,
+    std::shared_ptr<graphar::PropertyGroup> property_group) {
+  property_groups.emplace_back(std::move(property_group));
+}
+} // namespace graphar_rs
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index e26e72c9..6f6bcc73 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -15,9 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-//! Rust bindings for GraphAr data types.
+//! Rust bindings for GraphAr.
+
+#![deny(missing_docs)]
+
+use cxx::CxxString;
 
 mod ffi;
 
+/// GraphAr property.
+pub mod property;
 /// GraphAr logical data types.
 pub mod types;
+
+fn cxx_string_to_string(value: &CxxString) -> String {
+    String::from_utf8_lossy(value.as_bytes()).into_owned()
+}
diff --git a/rust/src/property.rs b/rust/src/property.rs
new file mode 100644
index 00000000..eae7cc9f
--- /dev/null
+++ b/rust/src/property.rs
@@ -0,0 +1,432 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Rust bindings for GraphAr property types.
+
+use std::ops::{Deref, DerefMut};
+
+use crate::ffi;
+use crate::types::{Cardinality, DataType, FileType};
+use cxx::{CxxVector, SharedPtr, UniquePtr, let_cxx_string};
+
+/// A property definition in the GraphAr schema.
+///
+/// This is a thin wrapper around the C++ `graphar::Property`.
+pub struct Property(pub(crate) UniquePtr<ffi::graphar::Property>);
+
+impl Property {
+    /// Create a new property definition.
+    ///
+    /// Note: In upstream GraphAr C++ (`graphar::Property` constructor), a 
primary key property is
+    /// always treated as non-nullable. Concretely, `is_nullable` is forced to 
`false` when
+    /// `is_primary` is `true` (regardless of the provided `is_nullable` 
value).
+    ///
+    /// This method takes `data_type` by value. Clone it if you need to reuse 
it.
+    pub fn new<S: AsRef<str>>(
+        name: S,
+        data_type: DataType,
+        is_primary: bool,
+        is_nullable: bool,
+        cardinality: Cardinality,
+    ) -> Self {
+        let_cxx_string!(name = name.as_ref());
+        Self(ffi::graphar::new_property(
+            &name,
+            data_type.0,
+            is_primary,
+            is_nullable,
+            cardinality,
+        ))
+    }
+
+    /// Return the property name.
+    pub fn name(&self) -> String {
+        crate::cxx_string_to_string(ffi::graphar::property_get_name(&self.0))
+    }
+
+    /// Return the property data type.
+    pub fn data_type(&self) -> DataType {
+        let ty = ffi::graphar::property_get_type(&self.0);
+        DataType(ty.clone())
+    }
+
+    /// Return whether this property is a primary key.
+    pub fn is_primary(&self) -> bool {
+        ffi::graphar::property_is_primary(&self.0)
+    }
+
+    /// Return whether this property is nullable.
+    ///
+    /// Note: In upstream GraphAr C++ (`graphar::Property` constructor), a 
primary key property is
+    /// always treated as non-nullable, so this returns `false` when 
`is_primary()` is `true`.
+    pub fn is_nullable(&self) -> bool {
+        ffi::graphar::property_is_nullable(&self.0)
+    }
+
+    /// Return the cardinality of this property.
+    pub fn cardinality(&self) -> Cardinality {
+        ffi::graphar::property_get_cardinality(&self.0)
+    }
+}
+
+/// A builder for constructing a [`Property`].
+///
+/// This builder is primarily intended to be used with [`PropertyVec::emplace`]
+/// to avoid allocating an intermediate `graphar::Property` on the C++ heap.
+///
+/// Defaults:
+/// - `is_primary = false`
+/// - `is_nullable = true` (matches upstream GraphAr C++ default)
+/// - `cardinality = Cardinality::Single`
+pub struct PropertyBuilder<S: AsRef<str>> {
+    name: S,
+    data_type: DataType,
+    is_primary: bool,
+    is_nullable: bool,
+    cardinality: Cardinality,
+}
+
+impl<S: AsRef<str>> PropertyBuilder<S> {
+    /// Create a new builder with the given name and data type.
+    pub fn new(name: S, data_type: DataType) -> Self {
+        Self {
+            name,
+            data_type,
+            is_primary: false,
+            is_nullable: true,
+            cardinality: Cardinality::Single,
+        }
+    }
+
+    /// Mark whether this property is a primary key.
+    pub fn primary_key(mut self, is_primary: bool) -> Self {
+        self.is_primary = is_primary;
+        self
+    }
+
+    /// Mark whether this property is nullable.
+    pub fn nullable(mut self, is_nullable: bool) -> Self {
+        self.is_nullable = is_nullable;
+        self
+    }
+
+    /// Set the cardinality of this property.
+    pub fn cardinality(mut self, cardinality: Cardinality) -> Self {
+        self.cardinality = cardinality;
+        self
+    }
+
+    /// Build a [`Property`].
+    pub fn build(self) -> Property {
+        let Self {
+            name,
+            data_type,
+            is_primary,
+            is_nullable,
+            cardinality,
+        } = self;
+
+        let_cxx_string!(name = name.as_ref());
+        Property(ffi::graphar::new_property(
+            &name,
+            data_type.0,
+            is_primary,
+            is_nullable,
+            cardinality,
+        ))
+    }
+}
+
+/// A vector of properties.
+///
+/// This is a wrapper around a C++ `std::vector<graphar::Property>`.
+pub struct PropertyVec(UniquePtr<CxxVector<ffi::graphar::Property>>);
+
+impl Default for PropertyVec {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl Deref for PropertyVec {
+    type Target = UniquePtr<CxxVector<ffi::graphar::Property>>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl DerefMut for PropertyVec {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl PropertyVec {
+    /// Create an empty property vector.
+    pub fn new() -> Self {
+        Self(CxxVector::new())
+    }
+
+    /// Push a property into the vector.
+    pub fn push(&mut self, property: Property) {
+        ffi::graphar::property_vec_push_property(self.0.pin_mut(), property.0);
+    }
+
+    /// Construct and append a property directly in the underlying C++ vector.
+    ///
+    /// Compared to `push(builder.build())`, this avoids allocating an
+    /// intermediate `graphar::Property` on the C++ heap.
+    pub fn emplace<S: AsRef<str>>(&mut self, builder: PropertyBuilder<S>) {
+        let PropertyBuilder {
+            name,
+            data_type,
+            is_primary,
+            is_nullable,
+            cardinality,
+        } = builder;
+
+        let_cxx_string!(name = name.as_ref());
+        ffi::graphar::property_vec_emplace_property(
+            self.0.pin_mut(),
+            &name,
+            data_type.0,
+            is_primary,
+            is_nullable,
+            cardinality,
+        );
+    }
+}
+
+/// A group of properties stored in the same file(s).
+pub struct PropertyGroup(SharedPtr<ffi::graphar::PropertyGroup>);
+
+impl PropertyGroup {
+    /// Create a new property group.
+    ///
+    /// The `prefix` is a logical prefix string used by GraphAr (it is not a
+    /// filesystem path).
+    pub fn new<S: AsRef<[u8]>>(properties: PropertyVec, file_type: FileType, 
prefix: S) -> Self {
+        let_cxx_string!(prefix = prefix);
+        let props = properties
+            .0
+            .as_ref()
+            .expect("properties vec should be valid");
+        let inner = ffi::graphar::CreatePropertyGroup(props, file_type, 
&prefix);
+        Self(inner)
+    }
+
+    /// Return properties contained in this group.
+    pub fn properties(&self) -> Vec<Property> {
+        let props_cxx = self.0.GetProperties();
+        let mut props = Vec::with_capacity(props_cxx.len());
+        for prop in props_cxx {
+            props.push(Property(ffi::graphar::property_clone(prop)));
+        }
+
+        props
+    }
+
+    /// Check whether this group contains the given property.
+    pub fn has_property(&self, property_name: &str) -> bool {
+        let_cxx_string!(name = property_name);
+
+        self.0.HasProperty(&name)
+    }
+}
+
+/// A vector of property groups.
+pub struct PropertyGroupVector(UniquePtr<CxxVector<ffi::SharedPropertyGroup>>);
+
+impl Default for PropertyGroupVector {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl Deref for PropertyGroupVector {
+    type Target = UniquePtr<CxxVector<ffi::SharedPropertyGroup>>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl DerefMut for PropertyGroupVector {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl PropertyGroupVector {
+    /// Create an empty property group vector.
+    pub fn new() -> Self {
+        Self(CxxVector::new())
+    }
+
+    /// Push a property group into the vector.
+    pub fn push(&mut self, property_group: PropertyGroup) {
+        ffi::graphar::property_group_vec_push_property_group(self.0.pin_mut(), 
property_group.0);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::types::Type;
+
+    #[test]
+    fn test_property_roundtrip_getters() {
+        let p = Property::new("name", DataType::string(), false, true, 
Cardinality::Single);
+
+        assert_eq!(p.name(), "name");
+        assert_eq!(p.data_type().id(), Type::String);
+        assert!(!p.is_primary());
+        assert!(p.is_nullable());
+        assert_eq!(p.cardinality(), Cardinality::Single);
+    }
+
+    #[test]
+    fn test_property_primary_implies_non_nullable_upstream_behavior() {
+        // Upstream GraphAr C++ (`graphar::Property` constructor) forces:
+        //   is_nullable = !is_primary && is_nullable
+        // This test documents that behavior at the Rust binding layer.
+        let p = Property::new("id", DataType::int64(), true, true, 
Cardinality::Single);
+
+        assert!(p.is_primary());
+        assert!(!p.is_nullable());
+    }
+
+    #[test]
+    fn test_property_builder_default() {
+        let built = PropertyBuilder::new("id", DataType::int64()).build();
+        assert_eq!(built.name(), "id");
+        assert_eq!(built.data_type().id(), Type::Int64);
+        assert!(!built.is_primary());
+        assert!(built.is_nullable());
+        assert_eq!(built.cardinality(), Cardinality::Single);
+    }
+
+    #[test]
+    fn test_property_builder_emplace_options() {
+        let mut props = PropertyVec::new();
+        props.emplace(
+            PropertyBuilder::new("id", DataType::int64())
+                .primary_key(true)
+                .nullable(true),
+        );
+        props.emplace(
+            PropertyBuilder::new("tags", DataType::string())
+                .nullable(true)
+                .cardinality(Cardinality::List),
+        );
+
+        let pg = PropertyGroup::new(props, FileType::Parquet, "builder/");
+        let mut got = pg.properties();
+        got.sort_by_key(|a| a.name());
+
+        assert_eq!(got.len(), 2);
+        assert_eq!(got[0].name(), "id");
+        assert!(got[0].is_primary());
+        assert!(!got[0].is_nullable());
+        assert_eq!(got[0].cardinality(), Cardinality::Single);
+
+        assert_eq!(got[1].name(), "tags");
+        assert!(!got[1].is_primary());
+        assert!(got[1].is_nullable());
+        assert_eq!(got[1].cardinality(), Cardinality::List);
+    }
+
+    #[test]
+    fn test_property_vec_deref() {
+        let mut vec = PropertyVec::default();
+        assert_eq!(vec.deref().len(), 0);
+        assert!(vec.deref().is_empty());
+        assert_eq!(vec.deref().capacity(), 0);
+
+        // test `deref_mut`
+        vec.pin_mut().reserve(2);
+        assert_eq!(vec.deref().capacity(), 2);
+    }
+
+    #[test]
+    fn test_property_vec_and_group_roundtrip() {
+        let mut props = PropertyVec::default();
+        props.emplace(PropertyBuilder::new("id", 
DataType::int64()).primary_key(true));
+        props.push(Property::new(
+            "name",
+            DataType::string(),
+            false,
+            true,
+            Cardinality::Single,
+        ));
+
+        let pg = PropertyGroup::new(props, FileType::Parquet, "id_name/");
+        let mut got_names: Vec<String> = pg.properties().into_iter().map(|p| 
p.name()).collect();
+        got_names.sort();
+
+        assert_eq!(got_names, vec!["id".to_string(), "name".to_string()]);
+        assert!(pg.has_property("id"));
+        assert!(pg.has_property("name"));
+        assert!(!pg.has_property("missing"));
+    }
+
+    #[test]
+    fn test_property_group_vector_default_and_deref() {
+        let mut vec = PropertyGroupVector::default();
+        assert_eq!(vec.deref().len(), 0);
+        assert!(vec.deref().is_empty());
+        // test `deref_mut`
+        vec.deref_mut().pin_mut().reserve(2);
+        assert_eq!(vec.deref().capacity(), 2);
+    }
+
+    #[test]
+    fn test_property_group_vector_push() {
+        let mut props1 = PropertyVec::new();
+        props1.push(Property::new(
+            "id1",
+            DataType::int64(),
+            true,
+            false,
+            Cardinality::Single,
+        ));
+
+        let mut props2 = PropertyVec::new();
+        props2.push(Property::new(
+            "id",
+            DataType::int64(),
+            true,
+            false,
+            Cardinality::Single,
+        ));
+
+        let pg1 = PropertyGroup::new(props1, FileType::Parquet, "pg1/");
+        let pg2 = PropertyGroup::new(props2, FileType::Parquet, "pg2/");
+
+        let mut vec = PropertyGroupVector::default();
+        assert_eq!(vec.deref().len(), 0);
+        assert!(vec.deref().is_empty());
+
+        vec.push(pg1);
+        assert_eq!(vec.deref().len(), 1);
+        assert!(!vec.deref().is_empty());
+
+        vec.push(pg2);
+        assert_eq!(vec.deref().len(), 2);
+    }
+}
diff --git a/rust/src/types.rs b/rust/src/types.rs
index 826cec7d..57f427a9 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -30,6 +30,14 @@ use std::fmt::{Debug, Display};
 /// This is a re-export of the C++ `graphar::Type` enum.
 pub use crate::ffi::graphar::Type;
 
+/// File format for GraphAr chunk files.
+pub use crate::ffi::graphar::FileType;
+
+/// Cardinality of a property.
+///
+/// This defines how multiple values are handled for a given property key.
+pub use crate::ffi::graphar::Cardinality;
+
 #[derive(Clone)]
 /// A logical data type used by GraphAr.
 ///
@@ -39,7 +47,7 @@ pub use crate::ffi::graphar::Type;
 /// Note that `DataType` may be a null pointer. A null `DataType` is used as a
 /// sentinel value (e.g. `value_type()` for non-list types) and formats as
 /// `"null"` via [`Display`] and [`Debug`].
-pub struct DataType(SharedPtr<ffi::graphar::DataType>);
+pub struct DataType(pub(crate) SharedPtr<ffi::graphar::DataType>);
 
 impl PartialEq for DataType {
     fn eq(&self, other: &Self) -> bool {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to