Skip to main content

polars_core/series/ops/
null.rs

1use polars_arrow::bitmap::Bitmap;
2use polars_arrow::offset::OffsetsBuffer;
3use polars_buffer::Buffer;
4
5#[cfg(feature = "object")]
6use crate::chunked_array::object::registry::get_object_builder;
7use crate::prelude::*;
8
9impl Series {
10    /// Create a Series of `size` null values with the requested dtype.
11    ///
12    /// # Panics
13    /// Panics if `dtype` contains an invalid Map dtype.
14    pub fn full_null(name: PlSmallStr, size: usize, dtype: &DataType) -> Self {
15        // Separate from the `match` below, because it only peels off a single layer of
16        // nesting.
17        #[cfg(feature = "dtype-map")]
18        dtype
19            .ensure_valid_map_dtypes()
20            .expect("invalid Map dtype in `Series::full_null`");
21
22        // match the logical types and create them
23        match dtype {
24            DataType::List(inner_dtype) => {
25                ListChunked::full_null_with_dtype(name, size, inner_dtype).into_series()
26            },
27            #[cfg(feature = "dtype-array")]
28            DataType::Array(inner_dtype, width) => {
29                ArrayChunked::full_null_with_dtype(name, size, inner_dtype, *width).into_series()
30            },
31            #[cfg(feature = "dtype-categorical")]
32            dt @ (DataType::Categorical(_, _) | DataType::Enum(_, _)) => {
33                with_match_categorical_physical_type!(dt.cat_physical().unwrap(), |$C| {
34                    CategoricalChunked::<$C>::full_null_with_dtype(
35                        name,
36                        size,
37                        dtype.clone()
38                    )
39                        .into_series()
40                })
41            },
42            #[cfg(feature = "dtype-date")]
43            DataType::Date => Int32Chunked::full_null(name, size)
44                .into_date()
45                .into_series(),
46            #[cfg(feature = "dtype-datetime")]
47            DataType::Datetime(tu, tz) => Int64Chunked::full_null(name, size)
48                .into_datetime(*tu, tz.clone())
49                .into_series(),
50            #[cfg(feature = "dtype-duration")]
51            DataType::Duration(tu) => Int64Chunked::full_null(name, size)
52                .into_duration(*tu)
53                .into_series(),
54            #[cfg(feature = "dtype-time")]
55            DataType::Time => Int64Chunked::full_null(name, size)
56                .into_time()
57                .into_series(),
58            #[cfg(feature = "dtype-decimal")]
59            DataType::Decimal(precision, scale) => Int128Chunked::full_null(name, size)
60                .into_decimal_unchecked(*precision, *scale)
61                .into_series(),
62            #[cfg(feature = "dtype-struct")]
63            DataType::Struct(fields) => {
64                let fields = fields
65                    .iter()
66                    .map(|fld| Series::full_null(fld.name().clone(), size, fld.dtype()))
67                    .collect::<Vec<_>>();
68                let ca = StructChunked::from_series(name, size, fields.iter()).unwrap();
69
70                ca.with_outer_validity(Some(Bitmap::new_zeroed(size)))
71                    .into_series()
72            },
73            DataType::BinaryOffset => {
74                let length = size;
75
76                let offsets = vec![0; size + 1];
77                let array = BinaryArray::<i64>::new(
78                    dtype.to_arrow(CompatLevel::oldest()),
79                    unsafe { OffsetsBuffer::new_unchecked(Buffer::from(offsets)) },
80                    Buffer::default(),
81                    Some(Bitmap::new_zeroed(size)),
82                );
83
84                unsafe {
85                    BinaryOffsetChunked::new_with_dims(
86                        Arc::new(Field::new(name, dtype.clone())),
87                        vec![Box::new(array)],
88                        length,
89                        length,
90                    )
91                }
92                .into_series()
93            },
94            DataType::Null => Series::new_null(name, size),
95            DataType::Unknown(kind) => {
96                let dtype = kind.materialize().unwrap_or(DataType::Null);
97                Series::full_null(name, size, &dtype)
98            },
99            #[cfg(feature = "object")]
100            DataType::Object(_) => {
101                let mut builder = get_object_builder(name, size);
102                for _ in 0..size {
103                    builder.append_null();
104                }
105                builder.to_series()
106            },
107            #[cfg(feature = "dtype-map")]
108            DataType::Map(_, _) => {
109                let storage = Series::full_null(name, size, &dtype.map_storage_dtype().unwrap());
110                // SAFETY: the dtype is checked above, and an all-null Map holds no entries.
111                unsafe { MapChunked::from_storage_unchecked(dtype.clone(), storage) }.into_series()
112            },
113            #[cfg(feature = "dtype-extension")]
114            DataType::Extension(typ, storage_dtype) => {
115                Series::full_null(name, size, storage_dtype).into_extension(typ.clone())
116            },
117            _ => {
118                macro_rules! primitive {
119                    ($type:ty) => {{ ChunkedArray::<$type>::full_null(name, size).into_series() }};
120                }
121                macro_rules! bool {
122                    () => {{ ChunkedArray::<BooleanType>::full_null(name, size).into_series() }};
123                }
124                macro_rules! string {
125                    () => {{ ChunkedArray::<StringType>::full_null(name, size).into_series() }};
126                }
127                macro_rules! binary {
128                    () => {{ ChunkedArray::<BinaryType>::full_null(name, size).into_series() }};
129                }
130                match_dtype_to_logical_apply_macro!(dtype, primitive, string, binary, bool)
131            },
132        }
133    }
134}