clickhouse_arrow/native/values/
bytes.rs1use std::ops::{Deref, DerefMut};
2
3use crate::{FromSql, Result, ToSql, Type, Value, unexpected_type};
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct Bytes(pub Vec<u8>);
11
12impl ToSql for Bytes {
13 fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
14 match type_hint {
15 Some(Type::Array(x)) if **x == Type::UInt8 || **x == Type::Int8 => Ok(Value::Array(
16 self.0
17 .into_iter()
18 .map(|byte| match &**x {
19 Type::UInt8 => Value::UInt8(byte),
20 #[expect(clippy::cast_possible_wrap)]
21 Type::Int8 => Value::Int8(byte as i8),
22 _ => unreachable!(),
23 })
24 .collect(),
25 )),
26 _ => Ok(Value::String(self.0)),
27 }
28 }
29}
30
31impl FromSql for Bytes {
32 fn from_sql(type_: &Type, value: Value) -> Result<Self> {
33 match type_ {
34 Type::String | Type::FixedSizedString(_) => match value {
35 Value::String(s) => Ok(Self(s)),
36 _ => unreachable!(),
37 },
38 Type::Array(x) if **x == Type::UInt8 || **x == Type::Int8 => match value {
39 Value::Array(values) => Ok(Self(
40 values
41 .into_iter()
42 .map(|x| {
43 Ok(match x {
44 Value::UInt8(x) => x,
45 #[expect(clippy::cast_sign_loss)]
46 Value::Int8(x) => x as u8,
47 _ => return Err(unexpected_type(&x.guess_type())),
48 })
49 })
50 .collect::<Result<Vec<u8>>>()?,
51 )),
52 _ => unreachable!(),
53 },
54 _ => Err(unexpected_type(type_)),
55 }
56 }
57}
58
59impl Deref for Bytes {
60 type Target = Vec<u8>;
61
62 fn deref(&self) -> &Self::Target { &self.0 }
63}
64
65impl DerefMut for Bytes {
66 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
67}
68
69impl From<Bytes> for Vec<u8> {
70 fn from(value: Bytes) -> Self { value.0 }
71}
72
73impl From<Vec<u8>> for Bytes {
74 fn from(value: Vec<u8>) -> Self { Self(value) }
75}