common_function/scalars/vector/
impl_conv.rs1use std::borrow::Cow;
16
17use common_query::error::{InvalidFuncArgsSnafu, Result};
18use datafusion_common::ScalarValue;
19
20pub fn as_veclit(arg: &ScalarValue) -> Result<Option<Cow<'_, [f32]>>> {
22 match arg {
23 ScalarValue::Binary(b) | ScalarValue::BinaryView(b) => {
24 b.as_ref().map(|x| binlit_as_veclit(x)).transpose()
25 }
26 ScalarValue::Utf8(s) | ScalarValue::Utf8View(s) => s
27 .as_ref()
28 .map(|x| parse_veclit_from_strlit(x).map(Cow::Owned))
29 .transpose(),
30 _ => InvalidFuncArgsSnafu {
31 err_msg: format!("Unsupported data type: {:?}", arg.data_type()),
32 }
33 .fail(),
34 }
35}
36
37pub fn binlit_as_veclit(bytes: &[u8]) -> Result<Cow<'_, [f32]>> {
39 if !bytes.len().is_multiple_of(size_of::<f32>()) {
40 return InvalidFuncArgsSnafu {
41 err_msg: format!("Invalid binary length of vector: {}", bytes.len()),
42 }
43 .fail();
44 }
45
46 if cfg!(target_endian = "little") {
47 Ok(unsafe {
48 let vec = std::slice::from_raw_parts(
49 bytes.as_ptr() as *const f32,
50 bytes.len() / std::mem::size_of::<f32>(),
51 );
52 Cow::Borrowed(vec)
53 })
54 } else {
55 let v = bytes
56 .as_chunks::<{ std::mem::size_of::<f32>() }>()
57 .0
58 .iter()
59 .map(|chunk| f32::from_le_bytes(*chunk))
60 .collect::<Vec<f32>>();
61 Ok(Cow::Owned(v))
62 }
63}
64
65pub fn parse_veclit_from_strlit(s: &str) -> Result<Vec<f32>> {
68 let trimmed = s.trim();
69 if !trimmed.starts_with('[') || !trimmed.ends_with(']') {
70 return InvalidFuncArgsSnafu {
71 err_msg: format!(
72 "Failed to parse {s} to Vector value: not properly enclosed in brackets"
73 ),
74 }
75 .fail();
76 }
77 let content = trimmed[1..trimmed.len() - 1].trim();
78 if content.is_empty() {
79 return Ok(Vec::new());
80 }
81
82 content
83 .split(',')
84 .map(|s| s.trim().parse::<f32>())
85 .collect::<std::result::Result<_, _>>()
86 .map_err(|e| {
87 InvalidFuncArgsSnafu {
88 err_msg: format!("Failed to parse {s} to Vector value: {e}"),
89 }
90 .build()
91 })
92}
93
94pub fn veclit_to_binlit(vec: &[f32]) -> Vec<u8> {
96 if cfg!(target_endian = "little") {
97 unsafe {
98 std::slice::from_raw_parts(vec.as_ptr() as *const u8, std::mem::size_of_val(vec))
99 .to_vec()
100 }
101 } else {
102 let mut bytes = Vec::with_capacity(std::mem::size_of_val(vec));
103 for e in vec {
104 bytes.extend_from_slice(&e.to_le_bytes());
105 }
106 bytes
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_parse_veclit_from_strlit() {
116 let result = parse_veclit_from_strlit("[1.0, 2.0, 3.0]").unwrap();
117 assert_eq!(result, vec![1.0, 2.0, 3.0]);
118
119 let result = parse_veclit_from_strlit("[]").unwrap();
120 assert_eq!(result, Vec::<f32>::new());
121
122 let result = parse_veclit_from_strlit("[1.0, a, 3.0]");
123 assert!(result.is_err());
124 }
125
126 #[test]
127 fn test_binlit_as_veclit() {
128 let vec = &[1.0, 2.0, 3.0];
129 let bytes = veclit_to_binlit(vec);
130 let result = binlit_as_veclit(&bytes).unwrap();
131 assert_eq!(result.as_ref(), vec);
132
133 let invalid_bytes = [0, 0, 128];
134 let result = binlit_as_veclit(&invalid_bytes);
135 assert!(result.is_err());
136 }
137}