Skip to main content

lindera_dictionary/
util.rs

1use std::fs::File;
2use std::io::{Read, Write};
3use std::ops::Deref;
4use std::path::Path;
5
6#[cfg(feature = "mmap")]
7use memmap2::Mmap;
8
9use anyhow::anyhow;
10use encoding_rs::Encoding;
11use serde::{Deserialize, Serialize};
12
13use crate::LinderaResult;
14use crate::error::LinderaErrorKind;
15
16use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
17
18/// Write data directly to the writer.
19pub fn write_data<W: Write>(buffer: &[u8], writer: &mut W) -> LinderaResult<()> {
20    writer.write_all(buffer).map_err(|err| {
21        LinderaErrorKind::Io
22            .with_error(err)
23            .add_context("Failed to write data to output")
24    })?;
25    Ok(())
26}
27
28pub fn read_file(filename: &Path) -> LinderaResult<Vec<u8>> {
29    let mut input_read = File::open(filename).map_err(|err| {
30        LinderaErrorKind::Io
31            .with_error(err)
32            .add_context(format!("Failed to open file: {}", filename.display()))
33    })?;
34    let mut buffer = Vec::new();
35    input_read.read_to_end(&mut buffer).map_err(|err| {
36        LinderaErrorKind::Io.with_error(err).add_context(format!(
37            "Failed to read file contents: {}",
38            filename.display()
39        ))
40    })?;
41    Ok(buffer)
42}
43
44/// Reads a file into a 16-byte aligned buffer, as required when loading rkyv
45/// archives (e.g. `char_def.bin`, `unk.bin`).
46pub fn read_aligned_file(filename: &Path) -> LinderaResult<rkyv::util::AlignedVec<16>> {
47    let raw_data = read_file(filename)?;
48
49    let mut aligned_data = rkyv::util::AlignedVec::<16>::new();
50    aligned_data.extend_from_slice(&raw_data);
51
52    Ok(aligned_data)
53}
54
55#[cfg(feature = "mmap")]
56pub fn mmap_file(filename: &Path) -> LinderaResult<Mmap> {
57    let file = File::open(filename).map_err(|err| {
58        LinderaErrorKind::Io.with_error(err).add_context(format!(
59            "Failed to open file for memory mapping: {}",
60            filename.display()
61        ))
62    })?;
63    let mmap = unsafe { Mmap::map(&file) }.map_err(|err| {
64        LinderaErrorKind::Io
65            .with_error(err)
66            .add_context(format!("Failed to memory map file: {}", filename.display()))
67    })?;
68    Ok(mmap)
69}
70
71pub fn read_file_with_encoding(filepath: &Path, encoding_name: &str) -> LinderaResult<String> {
72    let encoding = Encoding::for_label_no_replacement(encoding_name.as_bytes());
73    let encoding = encoding.ok_or_else(|| {
74        LinderaErrorKind::Decode.with_error(anyhow!("Invalid encoding: {encoding_name}"))
75    })?;
76
77    let buffer = read_file(filepath)?;
78    Ok(encoding.decode(&buffer).0.into_owned())
79}
80
81use std::sync::Arc;
82
83#[derive(Clone)]
84pub enum Data {
85    Static(&'static [u8]),
86    Vec(Vec<u8>),
87    #[cfg(feature = "mmap")]
88    Map(Arc<Mmap>),
89}
90
91impl Archive for Data {
92    type Archived = rkyv::vec::ArchivedVec<u8>;
93    type Resolver = rkyv::vec::VecResolver;
94
95    fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place<Self::Archived>) {
96        rkyv::vec::ArchivedVec::resolve_from_slice(self.deref(), resolver, out);
97    }
98}
99
100impl<S> RkyvSerialize<S> for Data
101where
102    S: rkyv::rancor::Fallible + rkyv::ser::Writer + rkyv::ser::Allocator + ?Sized,
103{
104    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
105        rkyv::vec::ArchivedVec::serialize_from_slice(self.deref(), serializer)
106    }
107}
108
109impl<D: rkyv::rancor::Fallible + ?Sized> RkyvDeserialize<Data, D> for rkyv::vec::ArchivedVec<u8> {
110    fn deserialize(&self, _deserializer: &mut D) -> Result<Data, D::Error> {
111        let mut vec = Vec::with_capacity(self.len());
112        vec.extend_from_slice(self.as_slice());
113        Ok(Data::Vec(vec))
114    }
115}
116
117impl Deref for Data {
118    type Target = [u8];
119    fn deref(&self) -> &Self::Target {
120        match self {
121            Data::Static(s) => s,
122            Data::Vec(v) => v,
123            #[cfg(feature = "mmap")]
124            Data::Map(m) => m,
125        }
126    }
127}
128
129impl From<&'static [u8]> for Data {
130    fn from(s: &'static [u8]) -> Self {
131        Self::Static(s)
132    }
133}
134
135impl<T: Deref<Target = [u8]>> From<&'static T> for Data {
136    fn from(t: &'static T) -> Self {
137        Self::Static(t)
138    }
139}
140
141impl From<Vec<u8>> for Data {
142    fn from(v: Vec<u8>) -> Self {
143        Self::Vec(v)
144    }
145}
146
147#[cfg(feature = "mmap")]
148impl From<Mmap> for Data {
149    fn from(m: Mmap) -> Self {
150        Self::Map(Arc::new(m))
151    }
152}
153
154impl Serialize for Data {
155    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
156    where
157        S: serde::Serializer,
158    {
159        serializer.serialize_bytes(self.deref())
160    }
161}
162
163impl<'de> Deserialize<'de> for Data {
164    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
165    where
166        D: serde::Deserializer<'de>,
167    {
168        let v = <Vec<u8> as serde::Deserialize>::deserialize(deserializer)?;
169        Ok(Data::Vec(v))
170    }
171}