Compare commits

...

4 commits

Author SHA1 Message Date
Jimmy-Z c6e44e9078 compatible with v1 keystore 2023-08-20 01:08:57 +08:00
Jimmy-Z 971ed05b58 key parser compatibility improvement 2023-08-19 22:15:01 +08:00
Jimmy-Z 243006ceff expose more internals for external use 2023-08-19 20:56:21 +08:00
Pyry Kontio 5ec9bd59ec
Update and rename README.md to adding a notice in README (#6)
Update README.md adding a notice about piracy
2023-08-01 17:46:03 +09:00
6 changed files with 52 additions and 38 deletions

View file

@ -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

View file

@ -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,

View file

@ -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())?;

View file

@ -4,7 +4,7 @@ mod dict;
mod error;
mod key;
mod pages;
mod resource;
pub mod resource;
mod headline;
pub use audio::Audio;

View file

@ -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 {

View file

@ -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 {