Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proptest strategies for generating Dimension, a bunch of Debug impls, and even some arrow stuff #15

Merged
merged 13 commits into from
Mar 20, 2024
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tiledb/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ name = "tiledb"
path = "src/lib.rs"

[dependencies]
serde_json = "1.0.114"
tiledb-sys = { workspace = true }

[dev-dependencies]
Expand Down
19 changes: 19 additions & 0 deletions tiledb/api/src/array/dimension.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::ops::Deref;

use serde_json::json;

use crate::context::Context;
use crate::convert::CAPIConverter;
use crate::filter_list::FilterList;
use crate::fn_typed;
use crate::Datatype;
use crate::Result as TileDBResult;

Expand Down Expand Up @@ -100,6 +104,21 @@ impl<'ctx> Dimension<'ctx> {
}
}

impl<'ctx> Debug for Dimension<'ctx> {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let json = json!({
"datatype": format!("{}", self.datatype()),
"domain": fn_typed!(self.domain, self.datatype() => match domain {
Ok(x) => format!("{:?}", x),
Err(e) => format!("<{}>", e)
}),
/* TODO: filters */
"raw": format!("{:p}", *self.raw)
});
write!(f, "{}", json)
}
}

pub struct Builder<'ctx> {
dim: Dimension<'ctx>,
}
Expand Down
25 changes: 23 additions & 2 deletions tiledb/api/src/array/domain.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use serde_json::json;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::ops::Deref;

use crate::array::{dimension::RawDimension, Dimension};
Expand Down Expand Up @@ -39,7 +41,7 @@ impl<'ctx> Domain<'ctx> {
Domain { context, raw }
}

pub fn ndim(&self) -> u32 {
pub fn ndim(&self) -> usize {
let mut ndim: u32 = out_ptr!();
let c_ret = unsafe {
ffi::tiledb_domain_get_ndim(
Expand All @@ -50,7 +52,7 @@ impl<'ctx> Domain<'ctx> {
};
// the only errors are possible via mis-use of the C API, which Rust prevents
assert_eq!(ffi::TILEDB_OK, c_ret);
ndim
ndim as usize
}

pub fn dimension(&self, idx: usize) -> TileDBResult<Dimension<'ctx>> {
Expand Down Expand Up @@ -85,6 +87,25 @@ impl<'ctx> Domain<'ctx> {
}
}

impl<'ctx> Debug for Domain<'ctx> {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let json = json!({
"dimensions": (0..self.ndim())
.map(|d| {
serde_json::value::Value::String(match self.dimension(d) {
Ok(d) => format!("{:?}", d),
Err(e) => format!("<{}>", e),
})
})
.collect::<Vec<_>>(),
"raw": format!("{:p}", *self.raw)
/* TODO: what other fields? */
});

write!(f, "{}", json)
}
}

pub struct Builder<'ctx> {
domain: Domain<'ctx>,
}
Expand Down
27 changes: 26 additions & 1 deletion tiledb/api/src/array/schema.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use serde_json::json;
use std::convert::TryFrom;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::ops::Deref;

use crate::array::attribute::RawAttribute;
Expand All @@ -7,7 +9,7 @@ use crate::array::{Attribute, Domain, Layout};
use crate::context::Context;
use crate::Result as TileDBResult;

#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub enum ArrayType {
Dense,
Sparse,
Expand Down Expand Up @@ -239,6 +241,29 @@ impl<'ctx> Schema<'ctx> {
}
}

impl<'ctx> Debug for Schema<'ctx> {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let json = json!({
"array_type": format!("{:?}", self.array_type()),
"capacity": self.capacity(),
"cell_order": format!("{:?}", self.cell_order()),
"tile_order": format!("{:?}", self.tile_order()),
"allows_duplicates": self.allows_duplicates(),
"domain": match self.domain() {
Ok(d) => format!("{:?}", d),
Err(e) => format!("<{}>", e)
},
"attributes": (0.. self.nattributes()).map(|a| match self.attribute(a) {
Ok(a) => format!("{:?}", a),
Err(e) => format!("<Error retrieving attribute {}: {}>", a, e)
}).collect::<Vec<String>>(),
"version": self.version(),
"raw": format!("{:p}", *self.raw),
});
write!(f, "{}", json)
}
}

pub struct Builder<'ctx> {
schema: Schema<'ctx>,
}
Expand Down
47 changes: 18 additions & 29 deletions tiledb/api/src/convert.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,31 @@
pub trait CAPISameRepr: Copy + Default {}

impl CAPISameRepr for u8 {}
impl CAPISameRepr for u16 {}
impl CAPISameRepr for u32 {}
impl CAPISameRepr for u64 {}
impl CAPISameRepr for i8 {}
impl CAPISameRepr for i16 {}
impl CAPISameRepr for i32 {}
impl CAPISameRepr for i64 {}
impl CAPISameRepr for f32 {}
impl CAPISameRepr for f64 {}

pub trait CAPIConverter {
type CAPIType: Default + Copy;

fn to_capi(&self) -> Self::CAPIType;
fn to_rust(value: &Self::CAPIType) -> Self;
}

impl CAPIConverter for i32 {
type CAPIType = std::ffi::c_int;

fn to_capi(&self) -> Self::CAPIType {
*self as Self::CAPIType
}

fn to_rust(value: &Self::CAPIType) -> Self {
*value as Self
}
}

impl CAPIConverter for u32 {
type CAPIType = std::ffi::c_uint;

fn to_capi(&self) -> Self::CAPIType {
*self as Self::CAPIType
}

fn to_rust(value: &Self::CAPIType) -> Self {
*value as Self
}
}

impl CAPIConverter for f64 {
type CAPIType = std::ffi::c_double;
impl<T: CAPISameRepr> CAPIConverter for T {
type CAPIType = Self;

fn to_capi(&self) -> Self::CAPIType {
*self as Self::CAPIType
*self
}

fn to_rust(value: &Self::CAPIType) -> Self {
*value as Self
fn to_rust(value: &Self::CAPIType) -> T {
*value
}
}
170 changes: 170 additions & 0 deletions tiledb/api/src/datatype.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#[macro_export]

/// Apply a generic function `$func` to data which implements `$datatype` and then run
/// the expression `$then` on the result.
/// The `$then` expression may use the function name as an identifier for the function result.

// note to developers: this is mimicking the C++ code
// template <class Fn, class... Args>
// inline auto apply_with_type(Fn&& f, Datatype type, Args&&... args)
//
macro_rules! fn_typed {
($func:ident, $datatype:expr$(, $arg:expr)* => $then:expr) => {{
type Datatype = $crate::Datatype;
match $datatype {
Datatype::Int8 => {
let $func = $func::<i8>($($arg,)*);
$then
}
Datatype::Int16 => {
let $func = $func::<i16>($($arg,)*);
$then
}
Datatype::Int32 => {
let $func = $func::<i32>($($arg,)*);
$then
}
Datatype::Int64 => {
let $func = $func::<i64>($($arg,)*);
$then
}
Datatype::UInt8 => {
let $func = $func::<u8>($($arg,)*);
$then
}
Datatype::UInt16 => {
let $func = $func::<u16>($($arg,)*);
$then
}
Datatype::UInt32 => {
let $func = $func::<u32>($($arg,)*);
$then
}
Datatype::UInt64 => {
let $func = $func::<u64>($($arg,)*);
$then
}
Datatype::Float32 => {
let $func = $func::<f32>($($arg,)*);
$then
}
Datatype::Float64 => {
let $func = $func::<f64>($($arg,)*);
$then
}
Datatype::Char => unimplemented!(),
Datatype::StringAscii => unimplemented!(),
Datatype::StringUtf8 => unimplemented!(),
Datatype::StringUtf16 => unimplemented!(),
Datatype::StringUtf32 => unimplemented!(),
Datatype::StringUcs2 => unimplemented!(),
Datatype::StringUcs4 => unimplemented!(),
Datatype::Any => unimplemented!(),
Datatype::DateTimeYear => unimplemented!(),
Datatype::DateTimeMonth => unimplemented!(),
Datatype::DateTimeWeek => unimplemented!(),
Datatype::DateTimeDay => unimplemented!(),
Datatype::DateTimeHour => unimplemented!(),
Datatype::DateTimeMinute => unimplemented!(),
Datatype::DateTimeSecond => unimplemented!(),
Datatype::DateTimeMillisecond => unimplemented!(),
Datatype::DateTimeMicrosecond => unimplemented!(),
Datatype::DateTimeNanosecond => unimplemented!(),
Datatype::DateTimePicosecond => unimplemented!(),
Datatype::DateTimeFemtosecond => unimplemented!(),
Datatype::DateTimeAttosecond => unimplemented!(),
Datatype::TimeHour => unimplemented!(),
Datatype::TimeMinute => unimplemented!(),
Datatype::TimeSecond => unimplemented!(),
Datatype::TimeMillisecond => unimplemented!(),
Datatype::TimeMicrosecond => unimplemented!(),
Datatype::TimeNanosecond => unimplemented!(),
Datatype::TimePicosecond => unimplemented!(),
Datatype::TimeFemtosecond => unimplemented!(),
Datatype::TimeAttosecond => unimplemented!(),
Datatype::Blob => unimplemented!(),
Datatype::Boolean => unimplemented!(),
Datatype::GeometryWkb => unimplemented!(),
Datatype::GeometryWkt => unimplemented!(),
}
}};
($obj:ident.$func:ident, $datatype:expr$(, $arg:expr)* => $then:expr) => {{
type Datatype = $crate::Datatype;
match $datatype {
Datatype::Int8 => {
let $func = $obj.$func::<i8>($($arg,)*);
$then
}
Datatype::Int16 => {
let $func = $obj.$func::<i16>($($arg,)*);
$then
}
Datatype::Int32 => {
let $func = $obj.$func::<i32>($($arg,)*);
$then
}
Datatype::Int64 => {
let $func = $obj.$func::<i64>($($arg,)*);
$then
}
Datatype::UInt8 => {
let $func = $obj.$func::<u8>($($arg,)*);
$then
}
Datatype::UInt16 => {
let $func = $obj.$func::<u16>($($arg,)*);
$then
}
Datatype::UInt32 => {
let $func = $obj.$func::<u32>($($arg,)*);
$then
}
Datatype::UInt64 => {
let $func = $obj.$func::<u64>($($arg,)*);
$then
}
Datatype::Float32 => {
let $func = $obj.$func::<f32>($($arg,)*);
$then
}
Datatype::Float64 => {
let $func = $obj.$func::<f64>($($arg,)*);
$then
}
Datatype::Char => unimplemented!(),
Datatype::StringAscii => unimplemented!(),
Datatype::StringUtf8 => unimplemented!(),
Datatype::StringUtf16 => unimplemented!(),
Datatype::StringUtf32 => unimplemented!(),
Datatype::StringUcs2 => unimplemented!(),
Datatype::StringUcs4 => unimplemented!(),
Datatype::Any => unimplemented!(),
Datatype::DateTimeYear => unimplemented!(),
Datatype::DateTimeMonth => unimplemented!(),
Datatype::DateTimeWeek => unimplemented!(),
Datatype::DateTimeDay => unimplemented!(),
Datatype::DateTimeHour => unimplemented!(),
Datatype::DateTimeMinute => unimplemented!(),
Datatype::DateTimeSecond => unimplemented!(),
Datatype::DateTimeMillisecond => unimplemented!(),
Datatype::DateTimeMicrosecond => unimplemented!(),
Datatype::DateTimeNanosecond => unimplemented!(),
Datatype::DateTimePicosecond => unimplemented!(),
Datatype::DateTimeFemtosecond => unimplemented!(),
Datatype::DateTimeAttosecond => unimplemented!(),
Datatype::TimeHour => unimplemented!(),
Datatype::TimeMinute => unimplemented!(),
Datatype::TimeSecond => unimplemented!(),
Datatype::TimeMillisecond => unimplemented!(),
Datatype::TimeMicrosecond => unimplemented!(),
Datatype::TimeNanosecond => unimplemented!(),
Datatype::TimePicosecond => unimplemented!(),
Datatype::TimeFemtosecond => unimplemented!(),
Datatype::TimeAttosecond => unimplemented!(),
Datatype::Blob => unimplemented!(),
Datatype::Boolean => unimplemented!(),
Datatype::GeometryWkb => unimplemented!(),
Datatype::GeometryWkt => unimplemented!(),
}
}};
}
2 changes: 2 additions & 0 deletions tiledb/api/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,5 @@ impl Drop for Error {
}
}
}

impl std::error::Error for Error {}
Loading