resb/bundle.rs
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
//! The `bundle` module provides data structures for working directly with the
//! contents of a resource bundle.
//!
//! WARNING: This module is not suitable for use at runtime due to its reliance
//! on `std` and `alloc` and therefore not intended for general deserialization
//! of resource bundles. Rather, it is intended to be used in development-time
//! tools for working with bundles.
extern crate alloc;
use alloc::{borrow::Cow, collections::BTreeMap};
use crate::MASK_28_BIT;
/// A tree-like collection of data [`Resource`]s primarily intended for storing
/// locale and other internationalization data for [ICU] (International
/// Components for Unicode).
///
/// [ICU]: https://icu.unicode.org/
#[derive(Debug)]
pub struct ResourceBundle<'a> {
name: Cow<'a, str>,
root: Resource<'a>,
/// Whether fallback is enabled for this resource bundle.
///
/// A resource bundle storing locale data may omit some data in order to
/// reduce duplication, allowing fallback to more general locales which
/// use the same values.
pub is_locale_fallback_enabled: bool,
}
impl<'a> ResourceBundle<'a> {
/// Makes a new resource bundle with the specified resource at its root.
pub fn new(name: Cow<'a, str>, root: Resource<'a>, is_locale_fallback_enabled: bool) -> Self {
Self {
name,
root,
is_locale_fallback_enabled,
}
}
/// Gets the name of the resource bundle.
///
/// This name is used as the "key" of the root resource in a text format
/// bundle, but is not used in building binary resource bundles.
pub fn name(&self) -> &str {
&self.name
}
/// Gets the root resource in the resource tree.
pub fn root(&self) -> &Resource {
&self.root
}
}
/// A data resource within a [`ResourceBundle`].
#[derive(Debug)]
#[non_exhaustive]
pub enum Resource<'a> {
/// A well-formed UTF-8 string.
String(Cow<'a, str>),
/// A heterogeneous list of resources, ordered by insertion.
Array(Vec<Resource<'a>>),
/// A set of key-resource pairs, sorted lexically by key.
Table(Table<'a>),
/// A slice of arbitrary binary data.
Binary(Cow<'a, [u8]>),
/// A 28-bit integer.
///
/// May be interpreted as either signed or unsigned depending on consumer
/// expectations. See [`Int28`] for further details.
Integer(Int28),
/// A list of 32-bit integers, ordered by insertion.
IntVector(Vec<u32>),
}
/// A table of [`Resource`]s indexed by a string-based [`Key`].
// Ordering of keys in a table is significant, so `HashMap` isn't appropriate
// here.
pub type Table<'a> = BTreeMap<Key<'a>, Resource<'a>>;
/// A key for a [`Resource`] within a [`Table`].
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Key<'a>(Cow<'a, str>);
impl Key<'_> {
/// Converts the string representing the key into a slice of UTF-8 bytes.
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl<'a> From<&'a str> for Key<'a> {
fn from(value: &'a str) -> Self {
Self(Cow::from(value))
}
}
impl From<String> for Key<'_> {
fn from(value: String) -> Self {
Self(Cow::from(value))
}
}
impl<'a> From<Key<'a>> for String {
fn from(value: Key<'a>) -> Self {
value.0.into_owned()
}
}
/// A 28-bit integer of undetermined signedness.
///
/// [`Resource`]s may include 28-bit integers whose signedness is determined at
/// runtime by consumers. Because these integers are stored in a 32-bit value,
/// negative values in signed integers require special handling, provided by
/// this newtype wrapper.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Int28(u32);
impl From<Int28> for i32 {
fn from(value: Int28) -> Self {
((value.0 as i32) << 4) >> 4
}
}
impl From<Int28> for u32 {
fn from(value: Int28) -> Self {
value.0
}
}
impl From<i32> for Int28 {
fn from(value: i32) -> Self {
Self::from(value as u32)
}
}
impl From<u32> for Int28 {
fn from(value: u32) -> Self {
Self(value & MASK_28_BIT)
}
}