use crate::{make_typed_id, ContainerIndex, Serializer, Serializable};
make_typed_id!(RawTextKey, u32);
#[derive(Default, Debug)]
pub struct TextPool(Vec<String>);
impl TextPool {
pub fn add_text(&mut self, text: &str) -> RawTextKey {
self.0.push(text.to_string());
RawTextKey::from(self.0.len() as u32)
}
pub fn get_text_from_key(&self, key: RawTextKey) -> &str {
if key.is_valid() { self.0.get(key.index() as usize).unwrap().as_str() }
else { &"NOTEXTKEY" }
}
}
impl Serializable for TextPool {
fn serialize(&self, s: &mut Serializer) {
self.0.serialize(s);
}
fn deserialize(&mut self, s: &mut Serializer) {
self.0.deserialize(s);
}
fn serialized_size(&self) -> usize {
self.0.serialized_size()
}
}
make_typed_id!(TextKey, u32);
make_typed_id!(LocaleKey, u8);
#[derive(Default, Debug)]
pub struct UnlocalisedTextPool {
locale_keys: std::collections::BTreeMap<String, TextKey>,
}
impl UnlocalisedTextPool {
pub fn get_key_as_string(&self, key: TextKey) -> String {
if key.is_valid() {
self.locale_keys.iter().filter(|x| *x.1 == key)
.map(|x| x.0.clone())
.next()
.unwrap_or_default()
} else {
"NOTEXTKEY".to_string()
}
}
pub fn find_or_add_key(&mut self, text: &str) -> TextKey {
self.locale_keys.get(text)
.map(|x| *x)
.or_else(|| {
let id = TextKey::from((self.locale_keys.len() + 1) as u32);
self.locale_keys.insert(text.to_string(), id);
Some(id)
}).unwrap()
}
pub fn view_locale_keys(&self) -> &std::collections::BTreeMap<String, TextKey> {
&self.locale_keys
}
}
impl Serializable for UnlocalisedTextPool {
fn serialize(&self, s: &mut Serializer) {
self.locale_keys.serialize(s);
}
fn deserialize(&mut self, s: &mut Serializer) {
self.locale_keys.deserialize(s);
}
fn serialized_size(&self) -> usize {
self.locale_keys.serialized_size()
}
}
#[derive(Default)]
pub struct LocalisedTextPool {
raw_text: TextPool,
per_locale_text: Vec<Vec<RawTextKey>>,
locale_keys: std::collections::BTreeMap<String, TextKey>,
locale_native_name: Vec<String>,
}
impl LocalisedTextPool {
pub fn add_locale(&mut self, native_name: &str) -> LocaleKey {
let plt = Vec::default();
self.per_locale_text.push(plt);
self.locale_native_name.push(native_name.to_string());
LocaleKey::from(self.per_locale_text.len() as u8)
}
pub fn get_text_from_key(&self, locale: LocaleKey, key: TextKey) -> &str {
if key.is_valid() {
let rk = self.per_locale_text[locale.index() as usize][key.index() as usize];
if rk.is_valid() {
self.raw_text.get_text_from_key(rk)
} else {
&"NOLOCALEKEY"
}
} else {
&"NOTEXTKEY"
}
}
pub fn get_text_from_text_key(&self, locale: LocaleKey, key: &str) -> &str {
self.get_text_from_key(locale, self.locale_keys.get(key)
.map(|&v| v)
.unwrap_or_default())
}
pub fn get_key_as_string(&self, key: TextKey) -> String {
if key.is_valid() {
self.locale_keys.iter()
.filter(|&(_, &v)| v == key)
.map(|(k, _)| k.clone())
.next()
.unwrap_or_default()
} else {
"NOTEXTKEY".to_string()
}
}
pub fn set_locale_keys(&mut self, ks: &std::collections::BTreeMap<String, TextKey>) {
self.locale_keys = ks.clone();
for plt in self.per_locale_text.iter_mut() {
plt.resize(self.locale_keys.len(), RawTextKey::default());
}
}
pub fn add_locale_key(&mut self, locale: LocaleKey, text: &str, code: &str) -> TextKey {
let nk = self.raw_text.add_text(text);
if let Some(&fid) = self.locale_keys.get(&code.to_string()) {
unsafe {
*(*self.per_locale_text.get_unchecked_mut(locale.index() as usize)).get_unchecked_mut(fid.index() as usize) = nk;
}
fid
} else {
let v = TextKey::from((self.locale_keys.len() + 1) as u16);
self.locale_keys.insert(code.to_string(), v);
if v.index() as usize >= self.per_locale_text[locale.index() as usize].len() {
let prealloc = 8192; for plt in self.per_locale_text.iter_mut() {
plt.resize(v.index() as usize + prealloc, RawTextKey::default());
}
}
unsafe {
*(*self.per_locale_text.get_unchecked_mut(locale.index() as usize)).get_unchecked_mut(v.index() as usize) = nk;
}
v
}
}
pub fn optimize(&mut self) {
}
}
impl Serializable for LocalisedTextPool {
fn serialize(&self, s: &mut Serializer) {
self.raw_text.serialize(s);
self.per_locale_text.serialize(s);
self.locale_keys.serialize(s);
self.locale_native_name.serialize(s);
}
fn deserialize(&mut self, s: &mut Serializer) {
self.raw_text.deserialize(s);
self.per_locale_text.deserialize(s);
self.locale_keys.deserialize(s);
self.locale_native_name.deserialize(s);
}
fn serialized_size(&self) -> usize {
self.raw_text.serialized_size()
+ self.per_locale_text.serialized_size()
+ self.locale_keys.serialized_size()
+ self.locale_native_name.serialized_size()
}
}
make_typed_id!(MutTextKey, u16);
#[derive(Default)]
pub struct MutTextPool(Vec<Option<String>>);
impl MutTextPool {
pub fn add_text(&mut self, text: &str) -> MutTextKey {
for e in self.0.iter_mut().enumerate() {
if let None = e.1 {
*e.1 = Some(text.to_string());
return MutTextKey::from(e.0 as u16);
}
}
self.0.push(Some(text.to_string()));
MutTextKey::from(self.0.len() as u16)
}
pub fn remove_text(&mut self, k: MutTextKey) {
self.0[k.index() as usize] = None;
}
pub fn get_text<'a>(&'a self, k: MutTextKey) -> Option<&'a str> {
if k.is_valid() {
self.0[k.index() as usize].as_ref().map(|x| x.as_str())
} else {
None
}
}
}
impl Serializable for MutTextPool {
fn serialize(&self, s: &mut Serializer) {
self.0.serialize(s);
}
fn deserialize(&mut self, s: &mut Serializer) {
self.0.deserialize(s);
}
fn serialized_size(&self) -> usize {
self.0.serialized_size()
}
}