1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use tokio::io::AsyncWriteExt;

use crate::{io::ClickhouseWrite, values::Value, Result};

use super::{Serializer, SerializerState, Type};
pub struct NullableSerializer;

#[async_trait::async_trait]
impl Serializer for NullableSerializer {
    async fn write<W: ClickhouseWrite>(
        type_: &Type,
        value: &Value,
        writer: &mut W,
        state: &mut SerializerState,
    ) -> Result<()> {
        let inner_type = if let Type::Nullable(n) = type_ {
            &**n
        } else {
            unimplemented!()
        };

        match value {
            Value::Null => {
                writer.write_u8(1).await?;
                inner_type
                    .serialize(&inner_type.default_value(), writer, state)
                    .await?;
            }
            x => {
                writer.write_u8(0).await?;
                inner_type.serialize(x, writer, state).await?;
            }
        }
        Ok(())
    }

    async fn write_n<W: ClickhouseWrite>(
        type_: &Type,
        values: &[Value],
        writer: &mut W,
        state: &mut SerializerState,
    ) -> Result<()> {
        for value in values {
            let mask = if value == &Value::Null { 1u8 } else { 0u8 };
            writer.write_u8(mask).await?;
        }
        type_
            .strip_null()
            .serialize_column(values, writer, state)
            .await?;
        Ok(())
    }
}