-
-
Save 62mkv/f21d92b84fa826e6cbcd3c4e98181013 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! [dependencies] | |
//! fstrings = "0.1.4" | |
//! itertools = "0.8.0" | |
//! lazy_static = "1.3.0" | |
//! libc = "0.2.60" | |
//! libloading = "0.5.2" | |
#[macro_use] extern crate fstrings; | |
use ::std::{*, | |
convert::{ | |
TryInto, | |
TryFrom, | |
}, | |
ffi::{ | |
CStr, | |
}, | |
fmt::Write, | |
}; | |
use ::libc::{ | |
c_int as int, | |
}; | |
use ::libloading::{ | |
Library, | |
Symbol, | |
}; | |
#[allow(bad_style)] | |
type char = u8; | |
/// TODO: implement utf-16 when needed | |
macro_rules! TEXT {( | |
$text:expr | |
) => ( | |
concat!($text, "\0") | |
)} | |
#[derive( | |
Debug, | |
Default, | |
Clone, Copy, | |
)] | |
#[repr(C, packed(1))] | |
struct SynthForm { | |
form: [char; 30], | |
stem_length: int, | |
} | |
#[derive( | |
Debug, | |
Default, | |
Clone, Copy, | |
)] | |
#[repr(C, packed(1))] | |
struct SynthFormSet { | |
declination_type: int, | |
part_of_speech: [char; 3], | |
number_of_options: int, | |
parallel_forms: int, | |
form_code: [char; 30], | |
forms: [SynthForm; 5], | |
} | |
type SynthesizeFormsFunc = | |
unsafe | |
extern "stdcall" | |
fn (*const char, int, int, *mut SynthFormSet, int) -> int | |
; | |
fn synthesize (word: &'_ CStr) | |
{ | |
let mut buffer = [SynthFormSet::default(); 300]; | |
// use a static to avoid issues with the library being deallocated | |
::lazy_static::lazy_static!{ | |
static ref DLL_INSTANCE: Library = | |
Library::new(TEXT!("fmsynth.dll")) | |
.expect("Failed to load the dynamic library `fmsynth.dll`") | |
; | |
static ref SYNTHESIZE_FORMS: Symbol<'static, SynthesizeFormsFunc> = unsafe { | |
DLL_INSTANCE | |
.get(b"SynthesizeForms\0") | |
.expect("Failed to dynamically load `SynthesizeForms`") | |
}; | |
} | |
let count = usize::try_from(unsafe { | |
SYNTHESIZE_FORMS( | |
word.as_ptr() as *const char, | |
0, | |
0, | |
buffer.as_mut_ptr(), | |
buffer.len().try_into().expect("Overflow"), | |
) | |
}).expect("Overflow"); | |
println!("Options found: {}", count); | |
// buffer[.. count] | |
// .iter() | |
// .for_each(|form| println_f!("{form:#?}")) | |
// ; | |
let mut string = String::new(); | |
for &SynthFormSet { | |
declination_type, | |
part_of_speech, | |
number_of_options, | |
parallel_forms, | |
form_code, | |
forms, | |
} in &buffer[.. count] | |
{ | |
use ::itertools::Itertools; | |
let part_of_speech = String::from_utf8_lossy(&part_of_speech); | |
let form_code = String::from_utf8_lossy(&form_code); | |
string.clear(); | |
write_f!(string, | |
"{part_of_speech}, {declination_type}, {number_of_options}, {parallel_forms}, {form_code}, {forms}, ", | |
forms = | |
forms[.. parallel_forms as usize] | |
.iter() | |
.map(|&SynthForm { ref form, stem_length }| { | |
(String::from_utf8_lossy(form), stem_length) | |
}) | |
.format_with(" ~ ", |(form, stem_length), write| write( | |
&format_args!("{} ({})", form, stem_length) | |
)), | |
).unwrap(); | |
println_f!("{string}"); | |
} | |
} | |
macro_rules! c_str {( | |
$str:literal | |
) => ( | |
CStr::from_bytes_with_nul(concat!($str, "\0").as_bytes()) | |
.unwrap() | |
)} | |
fn main () | |
{ | |
synthesize(c_str!("iga")); | |
synthesize(c_str!("hea")); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment