Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"rust/lance-tools",
"rust/compression/fsst",
"rust/compression/bitpacking",
"rust/arrow-scalar",
]
exclude = ["python", "java/lance-jni"]
# Python package needs to be built by maturin.
Expand Down Expand Up @@ -72,6 +73,7 @@ lance-testing = { version = "=3.0.0-beta.2", path = "./rust/lance-testing" }
approx = "0.5.1"
# Note that this one does not include pyarrow
arrow = { version = "57.0.0", optional = false, features = ["prettyprint"] }
arrow-scalar = { version = "=57.0.0", path = "./rust/arrow-scalar" }
arrow-arith = "57.0.0"
arrow-array = "57.0.0"
arrow-buffer = "57.0.0"
Expand Down
31 changes: 31 additions & 0 deletions rust/arrow-scalar/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "arrow-scalar"
version = "57.0.0"
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
description = "Arrow scalar type with Ord, Hash, and Eq support"
keywords.workspace = true
categories.workspace = true
rust-version.workspace = true
readme = "README.md"

[dependencies]
# Note: this is a core crate and we should aim to keep this dependency list
# as minimal as possible.
arrow-array = { workspace = true }
Comment on lines +14 to +17
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to be defensive, might want to leave a brief comment that you want to keep the dependency list here small.

arrow-buffer = { workspace = true }
arrow-cast = { workspace = true }
arrow-data = { workspace = true }
arrow-row = { workspace = true }
arrow-schema = { workspace = true }
half = { workspace = true }

[dev-dependencies]
arrow-ord = { workspace = true }
proptest = { workspace = true }
rstest = { workspace = true }

[lints]
workspace = true
105 changes: 105 additions & 0 deletions rust/arrow-scalar/src/convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright The Lance Authors

use std::sync::Arc;

use arrow_array::*;
use half::f16;

use crate::ArrowScalar;

macro_rules! impl_from_primitive {
($native_ty:ty, $array_ty:ty) => {
impl From<$native_ty> for ArrowScalar {
fn from(value: $native_ty) -> Self {
let array: ArrayRef = Arc::new(<$array_ty>::from(vec![value]));
Self::try_from_array(array).expect("single-element primitive array is always valid")
}
}
};
}

impl_from_primitive!(i8, Int8Array);
impl_from_primitive!(i16, Int16Array);
impl_from_primitive!(i32, Int32Array);
impl_from_primitive!(i64, Int64Array);
impl_from_primitive!(u8, UInt8Array);
impl_from_primitive!(u16, UInt16Array);
impl_from_primitive!(u32, UInt32Array);
impl_from_primitive!(u64, UInt64Array);
impl_from_primitive!(f32, Float32Array);
impl_from_primitive!(f64, Float64Array);

impl From<bool> for ArrowScalar {
fn from(value: bool) -> Self {
let array: ArrayRef = Arc::new(BooleanArray::from(vec![value]));
Self::try_from_array(array).expect("single-element boolean array is always valid")
}
}

impl From<f16> for ArrowScalar {
fn from(value: f16) -> Self {
let array: ArrayRef = Arc::new(Float16Array::from(vec![value]));
Self::try_from_array(array).expect("single-element f16 array is always valid")
}
}

impl From<&str> for ArrowScalar {
fn from(value: &str) -> Self {
let array: ArrayRef = Arc::new(StringArray::from(vec![value]));
Self::try_from_array(array).expect("single-element string array is always valid")
}
}

impl From<String> for ArrowScalar {
fn from(value: String) -> Self {
Self::from(value.as_str())
}
}

impl From<&[u8]> for ArrowScalar {
fn from(value: &[u8]) -> Self {
let array: ArrayRef = Arc::new(BinaryArray::from_vec(vec![value]));
Self::try_from_array(array).expect("single-element binary array is always valid")
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_from_primitives() {
let s = ArrowScalar::from(42i32);
assert!(!s.is_null());
assert_eq!(format!("{s}"), "42");

let s = ArrowScalar::from(1.5f64);
assert!(!s.is_null());

let s = ArrowScalar::from(true);
assert_eq!(format!("{s}"), "true");
}

#[test]
fn test_from_string_types() {
let s = ArrowScalar::from("hello");
assert_eq!(format!("{s}"), "hello");

let s = ArrowScalar::from(String::from("world"));
assert_eq!(format!("{s}"), "world");
}

#[test]
fn test_from_binary() {
let bytes: &[u8] = &[0xDE, 0xAD];
let s = ArrowScalar::from(bytes);
assert!(!s.is_null());
}

#[test]
fn test_from_f16() {
let s = ArrowScalar::from(f16::from_f32(1.5));
assert!(!s.is_null());
}
}
Loading
Loading