Compare commits
4 commits
Author | SHA1 | Date | |
---|---|---|---|
c6e44e9078 | |||
971ed05b58 | |||
243006ceff | |||
5ec9bd59ec |
17
README.md
17
README.md
|
@ -1,6 +1,14 @@
|
|||
# monokakido.rs
|
||||
A Rust library for parsing and interpreting the [Monokakido](https://www.monokakido.jp/en/dictionaries/app/) dictionary format.
|
||||
Aiming for full test coverage and efficient implementation with minimal dependencies.
|
||||
|
||||
A Rust library for parsing and interpreting the [Monokakido](https://www.monokakido.jp/en/dictionaries/app/) dictionary format. Aiming for full test coverage and efficient implementation with minimal dependencies.
|
||||
## Notice
|
||||
|
||||
This library started as a personal project driven by curiosity.
|
||||
It is ABSOLUTELY NOT inteded to support piracy;
|
||||
I strongly condemn making unauthorized copies of Monokakido's dictionaries,
|
||||
and take no part or responsibility in that kind of activity.
|
||||
Please buy your own dictionaries directly from Monokakido to show your love and support.
|
||||
|
||||
## TODO:
|
||||
- Add headline support
|
||||
|
@ -39,12 +47,5 @@ A Rust library for parsing and interpreting the [Monokakido](https://www.monokak
|
|||
## Planned to support:
|
||||
- WISDOM3
|
||||
- SMK8
|
||||
- RHEJ
|
||||
- OLT
|
||||
- OLEX
|
||||
- OLDAE
|
||||
- OCD
|
||||
- OALD10
|
||||
- NHKACCENT2
|
||||
- DAIJISEN2
|
||||
- CCCAD
|
||||
|
|
10
src/dict.rs
10
src/dict.rs
|
@ -60,9 +60,7 @@ impl Paths {
|
|||
}
|
||||
|
||||
pub(crate) fn key_path(&self) -> PathBuf {
|
||||
let mut pb = PathBuf::from(&self.base_path);
|
||||
pb.push("Contents");
|
||||
pb.push(&self.contents_dir);
|
||||
let mut pb = self.contents_path();
|
||||
pb.push("key");
|
||||
pb
|
||||
}
|
||||
|
@ -74,9 +72,7 @@ impl Paths {
|
|||
}
|
||||
|
||||
pub(crate) fn headline_path(&self) -> PathBuf {
|
||||
let mut pb = PathBuf::from(&self.base_path);
|
||||
pb.push("Contents");
|
||||
pb.push(&self.contents_dir);
|
||||
let mut pb = self.contents_path();
|
||||
pb.push("headline");
|
||||
pb
|
||||
}
|
||||
|
@ -136,7 +132,7 @@ impl MonokakidoDict {
|
|||
};
|
||||
let pages = Pages::new(&paths)?;
|
||||
let audio = Audio::new(&paths)?;
|
||||
let keys = Keys::new(&paths)?;
|
||||
let keys = Keys::new(paths.key_headword_path())?;
|
||||
|
||||
Ok(MonokakidoDict {
|
||||
paths,
|
||||
|
|
57
src/key.rs
57
src/key.rs
|
@ -4,12 +4,12 @@ use std::{
|
|||
fs::File,
|
||||
io::{Read, Seek},
|
||||
mem::size_of,
|
||||
path::Path,
|
||||
str::from_utf8,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
abi_utils::{TransmuteSafe, LE32, read_vec},
|
||||
dict::Paths,
|
||||
abi_utils::{read_vec, TransmuteSafe, LE32},
|
||||
Error,
|
||||
};
|
||||
|
||||
|
@ -19,27 +19,42 @@ mod abi {
|
|||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub(super) struct FileHeader {
|
||||
pub ver: LE32,
|
||||
magic1: LE32,
|
||||
magic2: LE32,
|
||||
pub words_offset: LE32,
|
||||
pub idx_offset: LE32,
|
||||
magic3: LE32,
|
||||
magic4: LE32,
|
||||
// Jimmy-Z: no idea what this is
|
||||
// present on (not limited to) OALD10, SANKOKU8
|
||||
pub next_offset: LE32,
|
||||
magic5: LE32,
|
||||
magic6: LE32,
|
||||
magic7: LE32,
|
||||
}
|
||||
|
||||
impl FileHeader {
|
||||
pub(super) fn validate(&self) -> Result<(), Error> {
|
||||
if self.magic1.read() == 0x20000
|
||||
&& self.magic2.read() == 0
|
||||
&& self.magic3.read() == 0
|
||||
&& self.magic4.read() == 0
|
||||
&& self.magic5.read() == 0
|
||||
&& self.magic6.read() == 0
|
||||
&& self.words_offset.us() < self.idx_offset.us()
|
||||
pub(super) fn from(r: &mut impl Read) -> Result<Self, Error> {
|
||||
let mut h = FileHeader::default();
|
||||
r.read_exact(&mut h.as_bytes_mut()[..0x10])?;
|
||||
if h.ver.read() == 0x10000 && h.words_offset.read() == 0x10{
|
||||
} else if h.ver.read() == 0x20000 && h.words_offset.read() == 0x20 {
|
||||
r.read_exact(&mut h.as_bytes_mut()[0x10..])?;
|
||||
} else {
|
||||
return Err(Error::KeyFileHeaderValidate)
|
||||
}
|
||||
if h.ver.read() == 0x10000
|
||||
&& h.magic1.read() == 0
|
||||
&& h.words_offset.us() < h.idx_offset.us()
|
||||
{
|
||||
Ok(())
|
||||
Ok(h)
|
||||
} else if h.ver.read() == 0x20000
|
||||
&& h.magic1.read() == 0
|
||||
&& h.magic5.read() == 0
|
||||
&& h.magic6.read() == 0
|
||||
&& h.magic7.read() == 0
|
||||
&& h.words_offset.us() < h.idx_offset.us()
|
||||
&& (h.next_offset.read() == 0 || h.idx_offset.us() < h.next_offset.us())
|
||||
{
|
||||
Ok(h)
|
||||
} else {
|
||||
Err(Error::KeyFileHeaderValidate)
|
||||
}
|
||||
|
@ -119,18 +134,20 @@ impl Keys {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn new(paths: &Paths) -> Result<Keys, Error> {
|
||||
let mut file = File::open(paths.key_headword_path())?;
|
||||
pub fn new<P: AsRef<Path>>(path: P) -> Result<Keys, Error> {
|
||||
let mut file = File::open(path)?;
|
||||
let file_size = file.metadata()?.len() as usize;
|
||||
let mut hdr = FileHeader::default();
|
||||
file.read_exact(hdr.as_bytes_mut())?;
|
||||
hdr.validate()?;
|
||||
let hdr = FileHeader::from(&mut file)?;
|
||||
|
||||
file.seek(std::io::SeekFrom::Start(hdr.words_offset.read() as u64))?;
|
||||
let words = read_vec(&mut file, hdr.words_offset.us(), hdr.idx_offset.us())?;
|
||||
let Some(words) = words else { return Err(Error::InvalidIndex); };
|
||||
|
||||
let idx_end = file_size - hdr.idx_offset.us();
|
||||
let idx_end = (if hdr.next_offset.us() == 0 {
|
||||
file_size
|
||||
} else {
|
||||
hdr.next_offset.us()
|
||||
}) - hdr.idx_offset.us();
|
||||
let mut ihdr = IndexHeader::default();
|
||||
file.seek(std::io::SeekFrom::Start(hdr.idx_offset.read() as u64))?;
|
||||
file.read_exact(ihdr.as_bytes_mut())?;
|
||||
|
|
|
@ -4,7 +4,7 @@ mod dict;
|
|||
mod error;
|
||||
mod key;
|
||||
mod pages;
|
||||
mod resource;
|
||||
pub mod resource;
|
||||
mod headline;
|
||||
|
||||
pub use audio::Audio;
|
||||
|
|
|
@ -210,7 +210,7 @@ impl Nrsc {
|
|||
Ok(files)
|
||||
}
|
||||
|
||||
pub(crate) fn new(path: &Path) -> Result<Self, Error> {
|
||||
pub fn new(path: &Path) -> Result<Self, Error> {
|
||||
let files = Nrsc::files(path)?;
|
||||
let index = NrscIndex::new(path)?;
|
||||
Ok(Nrsc {
|
||||
|
|
|
@ -280,7 +280,7 @@ impl Rsc {
|
|||
Ok(files)
|
||||
}
|
||||
|
||||
pub(crate) fn new(path: &Path, rsc_name: &str) -> Result<Self, Error> {
|
||||
pub fn new(path: &Path, rsc_name: &str) -> Result<Self, Error> {
|
||||
let files = Rsc::files(path, rsc_name)?;
|
||||
let index = RscIndex::new(path, rsc_name)?;
|
||||
Ok(Self {
|
||||
|
|
Loading…
Reference in a new issue