This repository has been archived by the owner on Feb 18, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eb7b34f
commit 4b987fc
Showing
13 changed files
with
1,003 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Scalar API | ||
|
||
Design choices: | ||
|
||
### `Scalar` is trait object | ||
|
||
There are three reasons: | ||
|
||
* a scalar should have a small memory footprint, which an enum would not ensure given the different physical types available. | ||
* forward-compatibility: a new entry on an `enum` is backward-incompatible | ||
* do not expose implementation details to users (reduce the surface of the public API) | ||
|
||
### `Scalar` MUST contain nullability information | ||
|
||
This is to be aligned with the general notion of arrow's `Array`. | ||
|
||
This API is a companion to the `Array`, and follows the same design as `Array`. | ||
Specifically, a `Scalar` is a trait object that can be downcasted to concrete implementations. | ||
|
||
Like `Array`, `Scalar` implements | ||
|
||
* `data_type`, which is used to perform the correct downcast | ||
* `is_valid`, to tell whether the scalar is null or not | ||
|
||
### There is one implementation per arrows' physical type | ||
|
||
* Reduces the number of `match` that users need to write | ||
* Allows casting of logical types without changing the underlying physical type |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
use crate::{array::*, buffer::Buffer, datatypes::DataType}; | ||
|
||
use super::Scalar; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct BinaryScalar<O: Offset> { | ||
value: Buffer<u8>, | ||
is_valid: bool, | ||
phantom: std::marker::PhantomData<O>, | ||
} | ||
|
||
impl<O: Offset> PartialEq for BinaryScalar<O> { | ||
fn eq(&self, other: &Self) -> bool { | ||
self.is_valid == other.is_valid && ((!self.is_valid) | (self.value == other.value)) | ||
} | ||
} | ||
|
||
impl<O: Offset> BinaryScalar<O> { | ||
#[inline] | ||
pub fn new<P: AsRef<[u8]>>(v: Option<P>) -> Self { | ||
let is_valid = v.is_some(); | ||
O::from_usize(v.as_ref().map(|x| x.as_ref().len()).unwrap_or_default()).expect("Too large"); | ||
let value = Buffer::from(v.as_ref().map(|x| x.as_ref()).unwrap_or(&[])); | ||
Self { | ||
value, | ||
is_valid, | ||
phantom: std::marker::PhantomData, | ||
} | ||
} | ||
|
||
#[inline] | ||
pub fn value(&self) -> &[u8] { | ||
self.value.as_slice() | ||
} | ||
} | ||
|
||
impl<O: Offset, P: AsRef<[u8]>> From<Option<P>> for BinaryScalar<O> { | ||
#[inline] | ||
fn from(v: Option<P>) -> Self { | ||
Self::new(v) | ||
} | ||
} | ||
|
||
impl<O: Offset> Scalar for BinaryScalar<O> { | ||
#[inline] | ||
fn as_any(&self) -> &dyn std::any::Any { | ||
self | ||
} | ||
|
||
#[inline] | ||
fn is_valid(&self) -> bool { | ||
self.is_valid | ||
} | ||
|
||
#[inline] | ||
fn data_type(&self) -> &DataType { | ||
if O::is_large() { | ||
&DataType::LargeBinary | ||
} else { | ||
&DataType::Binary | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[allow(clippy::eq_op)] | ||
#[test] | ||
fn equal() { | ||
let a = BinaryScalar::<i32>::from(Some("a")); | ||
let b = BinaryScalar::<i32>::from(None::<&str>); | ||
assert_eq!(a, a); | ||
assert_eq!(b, b); | ||
assert!(a != b); | ||
let b = BinaryScalar::<i32>::from(Some("b")); | ||
assert!(a != b); | ||
assert_eq!(b, b); | ||
} | ||
|
||
#[test] | ||
fn basics() { | ||
let a = BinaryScalar::<i32>::from(Some("a")); | ||
|
||
assert_eq!(a.value(), b"a"); | ||
assert_eq!(a.data_type(), &DataType::Binary); | ||
assert!(a.is_valid()); | ||
|
||
let a = BinaryScalar::<i64>::from(None::<&str>); | ||
|
||
assert_eq!(a.data_type(), &DataType::LargeBinary); | ||
assert!(!a.is_valid()); | ||
} | ||
} |
Oops, something went wrong.