icu_collections/codepointtrie/
serde.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5use crate::codepointtrie::{CodePointTrie, CodePointTrieHeader, TrieValue};
6use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
7use zerofrom::ZeroFrom;
8use zerovec::ZeroVec;
9
10#[derive(Serialize, Deserialize)]
11pub struct CodePointTrieSerde<'trie, T: TrieValue> {
12    header: CodePointTrieHeader,
13    #[serde(borrow)]
14    index: ZeroVec<'trie, u16>,
15    #[serde(borrow)]
16    data: ZeroVec<'trie, T>,
17}
18
19impl<T: TrieValue + Serialize> Serialize for CodePointTrie<'_, T> {
20    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21    where
22        S: Serializer,
23    {
24        let ser = CodePointTrieSerde {
25            header: self.header,
26            index: ZeroFrom::zero_from(&self.index),
27            data: ZeroFrom::zero_from(&self.data),
28        };
29        ser.serialize(serializer)
30    }
31}
32
33impl<'de, 'trie, T: TrieValue + Deserialize<'de>> Deserialize<'de> for CodePointTrie<'trie, T>
34where
35    'de: 'trie,
36{
37    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
38    where
39        D: Deserializer<'de>,
40    {
41        let de = CodePointTrieSerde::deserialize(deserializer)?;
42        // SAFETY:
43        // `validate_fields` upholds the invariants for the fields that
44        // fast-path access without bound checks relies on.
45        let error_value = match CodePointTrie::validate_fields(&de.header, &de.index, &de.data) {
46            Ok(v) => v,
47            Err(e) => {
48                match e {
49                    super::CodePointTrieError::FromDeserialized { reason } => {
50                        // Not supposed to be returned by `validate_fields`.
51                        debug_assert!(false);
52                        return Err(D::Error::custom(reason));
53                    }
54                    super::CodePointTrieError::EmptyDataVector => {
55                        return Err(D::Error::custom("CodePointTrie must be constructed from data vector with at least one element"));
56                    }
57                    super::CodePointTrieError::IndexTooShortForFastAccess => {
58                        return Err(D::Error::custom("CodePointTrie must be constructed from index vector long enough to accommodate fast-path access"));
59                    }
60                    super::CodePointTrieError::DataTooShortForFastAccess => {
61                        return Err(D::Error::custom("CodePointTrie must be constructed from data vector long enough to accommodate fast-path access"));
62                    }
63                }
64            }
65        };
66        // Field invariants upheld: Checked by `validate_fields` above.
67        Ok(CodePointTrie {
68            header: de.header,
69            index: de.index,
70            data: de.data,
71            error_value,
72        })
73    }
74}