parquet/encryption/
modules.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::errors::ParquetError;
19
20#[derive(PartialEq)]
21pub(crate) enum ModuleType {
22    Footer = 0,
23    ColumnMetaData = 1,
24    DataPage = 2,
25    DictionaryPage = 3,
26    DataPageHeader = 4,
27    DictionaryPageHeader = 5,
28    ColumnIndex = 6,
29    OffsetIndex = 7,
30    _BloomFilterHeader = 8,
31    _BloomFilterBitset = 9,
32}
33
34pub fn create_footer_aad(file_aad: &[u8]) -> crate::errors::Result<Vec<u8>> {
35    create_module_aad(file_aad, ModuleType::Footer, 0, 0, None)
36}
37
38pub(crate) fn create_module_aad(
39    file_aad: &[u8],
40    module_type: ModuleType,
41    row_group_idx: usize,
42    column_ordinal: usize,
43    page_ordinal: Option<usize>,
44) -> crate::errors::Result<Vec<u8>> {
45    let module_buf = [module_type as u8];
46
47    if module_buf[0] == (ModuleType::Footer as u8) {
48        let mut aad = Vec::with_capacity(file_aad.len() + 1);
49        aad.extend_from_slice(file_aad);
50        aad.extend_from_slice(module_buf.as_ref());
51        return Ok(aad);
52    }
53
54    if row_group_idx > i16::MAX as usize {
55        return Err(general_err!(
56            "Encrypted parquet files can't have more than {} row groups: {}",
57            i16::MAX,
58            row_group_idx
59        ));
60    }
61    if column_ordinal > i16::MAX as usize {
62        return Err(general_err!(
63            "Encrypted parquet files can't have more than {} columns: {}",
64            i16::MAX,
65            column_ordinal
66        ));
67    }
68
69    if module_buf[0] != (ModuleType::DataPageHeader as u8)
70        && module_buf[0] != (ModuleType::DataPage as u8)
71    {
72        let mut aad = Vec::with_capacity(file_aad.len() + 5);
73        aad.extend_from_slice(file_aad);
74        aad.extend_from_slice(module_buf.as_ref());
75        aad.extend_from_slice((row_group_idx as i16).to_le_bytes().as_ref());
76        aad.extend_from_slice((column_ordinal as i16).to_le_bytes().as_ref());
77        return Ok(aad);
78    }
79
80    let page_ordinal =
81        page_ordinal.ok_or_else(|| general_err!("Page ordinal must be set for data pages"))?;
82
83    if page_ordinal > i16::MAX as usize {
84        return Err(general_err!(
85            "Encrypted parquet files can't have more than {} pages per column chunk: {}",
86            i16::MAX,
87            page_ordinal
88        ));
89    }
90
91    let mut aad = Vec::with_capacity(file_aad.len() + 7);
92    aad.extend_from_slice(file_aad);
93    aad.extend_from_slice(module_buf.as_ref());
94    aad.extend_from_slice((row_group_idx as i16).to_le_bytes().as_ref());
95    aad.extend_from_slice((column_ordinal as i16).to_le_bytes().as_ref());
96    aad.extend_from_slice((page_ordinal as i16).to_le_bytes().as_ref());
97    Ok(aad)
98}