initial commit

pull/1/head
Avril 4 years ago
commit fe3381650e
Signed by: flanchan
GPG Key ID: 284488987C31F630

3
.gitignore vendored

@ -0,0 +1,3 @@
/target
Cargo.lock
*~

@ -0,0 +1,15 @@
[package]
name = "kana-hash"
version = "0.1.0"
authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[dependencies]
sha2 = "0.9"
malloc-array = "1.3.3"
libc = "0.2"
crc = "1.8"

@ -0,0 +1,16 @@
pub fn copy_slice<T,D,S>(mut dst: D, src: S) -> usize
where T: Clone,
D: AsMut<[T]>,
S: AsRef<[T]>
{
let mut i =0;
for (d,s) in dst.as_mut().iter_mut().zip(src.as_ref().iter())
{
*d = s.clone();
i+=1;
}
i
}

@ -0,0 +1,36 @@
use std::ops::RangeInclusive;
#[derive(Clone,Debug,PartialEq,Eq,Hash)]
pub enum Definition
{
Single(RangeInclusive<usize>),
Any,
None,
}
impl Definition
{
pub const fn single(idx: RangeInclusive<usize>) -> Self
{
Self::Single(idx)
}
pub const fn any() -> Self
{
Self::Any
}
pub const fn none() -> Self
{
Self::None
}
pub fn contains(&self, sz: usize) -> bool
{
use Definition::*;
match self {
Single(range) => range.contains(&sz),
Any => true,
_ => false,
}
}
}

@ -0,0 +1,68 @@
use std::{
fmt,
io,
error,
};
#[derive(Debug)]
pub enum Error
{
IO(io::Error),
Format(fmt::Error),
Length{expected: usize, got:usize,},
Unknown,
}
impl error::Error for Error
{
fn source(&self) -> Option<&(dyn error::Error + 'static)>
{
match &self {
Error::IO(e_io) => Some(e_io),
Error::Format(e_fmt) => Some(e_fmt),
_ => None,
}
}
}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "kana-hash error: ")?;
match self {
Error::IO(io) => write!(f, "io: {}", io),
Error::Format(fmt) => write!(f, "fmt: {}", fmt),
Error::Length{expected, got} => write!(f, "invalid length: expected {}, got {}", expected, got),
_ => write!(f, "unknown failure"),
}
}
}
impl From<Error> for i32
{
fn from(er: Error) -> Self
{
match er {
Error::IO(_) => 1,
Error::Format(_) => 2,
Error::Length{..} => 3,
_ => -1,
}
}
}
impl From<io::Error> for Error
{
fn from(i: io::Error) -> Self
{
Self::IO(i)
}
}
impl From<fmt::Error> for Error
{
fn from(i: fmt::Error) -> Self
{
Self::Format(i)
}
}

@ -0,0 +1,47 @@
#![allow(unused_macros)]
pub const GENERIC_ERROR: i32 = -1;
pub const GENERIC_SUCCESS: i32 = 0;
macro_rules! c_try {
($e:expr) => {
match $e {
Ok(v) => v,
Err(e) => return i32::from(e),
}
}
}
macro_rules! no_unwind {
(try $t:expr; $($e:tt)*) => {
{
match std::panic::catch_unwind(|| {
$($e)*
}) {
Ok(v) => i32::from(v),
Err(_) => return i32::from($t),
}
}
};
($($e:tt)*) => {
no_unwind! {try $crate::ffi::GENERIC_ERROR; $($e)*}
}
}
macro_rules! string_from_ffi {
($file:expr) => {
unsafe {
let file = $file;
if file.is_null() {
return $crate::ffi::GENERIC_ERROR;
}
let file = CStr::from_ptr(file);
match file.to_str() {
Ok(file) => file.to_owned(),
Err(_) => return $crate::ffi::GENERIC_ERROR,
}
}
}
}

@ -0,0 +1,57 @@
/// Group iterator output every n values into `Vec<T>`.
pub struct GroupIter<T,I>
where I: Iterator<Item=T>
{
buffer: Vec<T>,
iter: I,
group_at: usize,
}
impl<T,I> Iterator for GroupIter<T,I>
where I: Iterator<Item=T>
{
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item>
{
while self.buffer.len() < self.group_at
{
if let Some(value) = self.iter.next() {
self.buffer.push(value)
} else {
return self.swap();
}
}
self.swap()
}
}
impl<T,I> GroupIter<T,I>
where I: Iterator<Item=T>
{
fn swap(&mut self) -> Option<Vec<T>>
{
let buff = {
let next = Vec::with_capacity(self.group_at);
std::mem::replace(&mut self.buffer, next)
};
if buff.len() > 0 {
Some(buff)
} else {
None
}
}
}
pub trait GroupExt: Iterator + Sized {
fn group_at(self, at: usize) -> GroupIter<<Self as Iterator>::Item, Self>
{
GroupIter{
group_at: at,
iter: self,
buffer: Vec::with_capacity(at),
}
}
}
impl<T> GroupExt for T where T: Iterator{}

@ -0,0 +1,41 @@
use super::*;
use crc::{Hasher32, crc32};
pub struct Crc32Checksum
{
hash: u32,
}
impl provider::ByteProvider for Crc32Checksum
{
fn bytes(&self) -> &[u8]
{
unsafe{reinterpret::bytes(&self.hash)}
}
fn compute<T: Read + ?Sized>(input: &mut T, done: &mut usize) -> Result<Self, error::Error>
{
let mut buffer = [0u8; BUFFER_SIZE];
let mut hasher = crc32::Digest::new(crc32::IEEE);
let mut read;
while (read = input.read(&mut buffer[..])?, read!=0).1
{
hasher.write(&buffer[..read]);
*done += read;
}
Ok(Self{hash: hasher.sum32()})
}
}
use std::fmt;
impl fmt::Display for Crc32Checksum
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "Crc32checksum (")?;
for b in provider::ByteProvider::bytes(self) {
write!(f, "{:02x}", *b)?;
}
write!(f, ")")
}
}

@ -0,0 +1,41 @@
use super::*;
use crc::{Hasher64, crc64};
pub struct Crc64Checksum
{
hash: u64,
}
impl provider::ByteProvider for Crc64Checksum
{
fn bytes(&self) -> &[u8]
{
unsafe{reinterpret::bytes(&self.hash)}
}
fn compute<T: Read + ?Sized>(input: &mut T, done: &mut usize) -> Result<Self, error::Error>
{
let mut buffer = [0u8; BUFFER_SIZE];
let mut hasher = crc64::Digest::new(crc64::ECMA);
let mut read;
while (read = input.read(&mut buffer[..])?, read!=0).1
{
hasher.write(&buffer[..read]);
*done += read;
}
Ok(Self{hash: hasher.sum64()})
}
}
use std::fmt;
impl fmt::Display for Crc64Checksum
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "Crc64checksum (")?;
for b in provider::ByteProvider::bytes(self) {
write!(f, "{:02x}", *b)?;
}
write!(f, ")")
}
}

@ -0,0 +1,10 @@
use crate::*;
mod sha256;
pub use sha256::*;
mod crc64;
pub use crc64::*;
mod crc32;
pub use crc32::*;

@ -0,0 +1,83 @@
use super::*;
use sha2::{Sha256, Digest};
use std::{
io::{
self,
Read,
},
};
pub const SHA256_SIZE: usize = 32;
#[repr(C)]
#[repr(packed)]
#[derive(Copy,Clone,Debug,PartialEq,Eq,Hash)]
pub struct Sha256Hash
{
hash: [u8; SHA256_SIZE],
}
fn compute_stream<T: Read +?Sized, D: Digest>(input: &mut T, output: &mut D) -> io::Result<usize>
{
let mut buffer = [0u8; BUFFER_SIZE];
let mut read;
let mut done=0;
while (read = input.read(&mut buffer[..])?, read!=0).1
{
output.update(&buffer[..read]);
done+=read;
}
Ok(done)
}
impl Sha256Hash
{
/// Compute a hash from a stream.
pub fn compute<T: Read + ?Sized>(input: &mut T) -> io::Result<(usize, Self)>
{
let mut hash = [0u8; SHA256_SIZE];
let mut hasher = Sha256::new();
let ok = compute_stream(input, &mut hasher)?;
assert_eq!(array::copy_slice(&mut hash, hasher.finalize()), SHA256_SIZE);
Ok((ok, Self{hash}))
}
pub fn bytes(&self) -> &[u8; SHA256_SIZE]
{
&self.hash
}
}
use std::fmt;
impl fmt::Display for Sha256Hash
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "Sha256hash (")?;
for byte in self.hash.iter()
{
write!(f, "{:02x}", *byte)?;
}
write!(f, ")")
}
}
impl provider::ByteProvider for hash::Sha256Hash
{
fn bytes(&self) -> &[u8]
{
&self.bytes()[..]
}
fn compute<T: Read + ?Sized>(input: &mut T, done: &mut usize) -> Result<Self, error::Error>
{
let (ok, this) = Self::compute(input)?;
*done = ok;
Ok(this)
}
}

@ -0,0 +1,104 @@
#![allow(dead_code)]
use std::{
io::{
Read,
},
fmt::Write,
};
type HASHER =hash::Crc64Checksum;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() -> Result<(), error::Error>
{
let input = b"hello world!!";
let kana = generate(input)?;
println!("kana: {}", kana);
panic!("uhh")
}
}
pub const BUFFER_SIZE: usize = 4096;
mod array;
mod reinterpret;
mod group;
mod sixteen;
use sixteen::Bit16IterExt;
mod def;
mod map;
mod hash;
mod provider;
mod mnemonic;
mod error;
#[macro_use]
mod ffi;
use ffi::*;
fn compute<T: Read, Digest: provider::ByteProvider>(mut from: T) -> Result<(usize, String), error::Error>
{
let (read, hash) = provider::compute::<_, Digest>(&mut from)?;
println!("hash ({}): {}", read, hash);
let mut output = String::with_capacity(128);
for element in hash.bytes().iter()
.into_16()
.map(|bytes| mnemonic::Digest::new(unsafe{reinterpret::bytes(&bytes)}))
{
write!(output, "{}", element)?;
}
Ok((read,output))
}
pub fn generate<T: AsRef<[u8]>>(bytes: T) -> Result<String, error::Error>
{
let bytes = bytes.as_ref();
let mut nbytes = bytes;
let (ok, string) = compute::<_, HASHER>(&mut nbytes)?;
if ok == bytes.len() {
Ok(string)
} else {
return Err(error::Error::Length{expected: bytes.len(), got: ok});
}
}
use std::ffi::c_void;
use libc::{
size_t,
c_char,
};
use malloc_array::{
HeapArray,
};
#[no_mangle]
pub unsafe extern "C" fn _kana_length(bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32
{
no_unwind!{
try error::Error::Unknown;
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string = c_try!(generate(&bin));
*out_len = (string.bytes().len()+1).into();
GENERIC_SUCCESS
}
}
#[no_mangle]
pub unsafe extern "C" fn _kana_do(bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32
{
no_unwind!{
try error::Error::Unknown;
let bin = HeapArray::<u8>::from_raw_copied(bin as *const u8, usize::from(sz));
let string: Vec<u8> = c_try!(generate(&bin)).bytes().collect();
libc::memcpy(out_str as *mut c_void, &string[0] as *const u8 as *const c_void, std::cmp::min(str_len, string.len()));
GENERIC_SUCCESS
}
}

@ -0,0 +1,92 @@
pub const KANA: &[char; 92] = &[
'あ', 'い', 'う', 'え', 'お',
'か', 'き', 'く', 'け', 'こ',
'さ', 'し', 'す', 'せ', 'そ',
'た', 'ち', 'つ', 'て', 'と',
'な', 'に', 'ぬ', 'ね', 'の',
'は', 'ひ', 'ふ', 'へ', 'ほ',
'ま', 'み', 'む', 'め', 'も',
'ら', 'り', 'る', 'れ', 'ろ',
'や', 'ゆ', 'よ', 'わ', 'ん',
'を', //45
'ア', 'イ', 'ウ', 'エ', 'オ',
'カ', 'キ', 'ク', 'ケ', 'コ',
'サ', 'シ', 'ス', 'セ', 'ソ',
'タ', 'チ', 'ツ', 'テ', 'ト',
'ナ', 'ニ', 'ヌ', 'ネ', '',
'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
'マ', 'ミ', 'ム', 'メ', 'モ',
'ラ', 'リ', 'ル', 'レ', 'ロ',
'ヤ', 'ユ', 'ヨ',
'ワ', 'ン', 'ヲ',
];
pub const KANA_SUB: &[char; 18] = &[
'ゃ',
'ゅ',
'ょ',
'ャ',
'ュ',
'ョ',
'っ',
'ッ',
'ぁ','ぃ','ぅ','ぇ','ぉ',
'ァ','ィ','ゥ','ェ','ォ',
];
use crate::def::Definition;
pub const KANA_SUB_VALID_FOR: &[Definition; 18] = &[ // Should we properly restrict these to only ones that make sense? (i.e. KI SHI HI etc..)
Definition::single(5..=39),
Definition::single(5..=39),
Definition::single(5..=39),
Definition::single(51..=85),
Definition::single(51..=85),
Definition::single(51..=85),
Definition::any(),
Definition::any(),
Definition::single(5..=39),
Definition::single(5..=39),
Definition::single(5..=39),
Definition::single(5..=39),
Definition::single(5..=39),
Definition::single(51..=85),
Definition::single(51..=85),
Definition::single(51..=85),
Definition::single(51..=85),
Definition::single(51..=85),
];
/// Find all subs that are okay for this kana. If `kana` is not in `KANA`, return None.
pub fn find_sub(kana: char) -> Option<Vec<char>>
{
for (i,x) in (0..(KANA.len())).zip(KANA.iter()) {
if *x == kana {
let mut output = Vec::with_capacity(KANA_SUB.len());
for (def,sub) in KANA_SUB_VALID_FOR.iter().zip(KANA_SUB.iter())
{
if def.contains(i) {
output.push(sub.clone());
}
}
return Some(output);
}
}
None
}
/// Find subs by index.
pub fn sub(i: usize) -> Option<Vec<char>>
{
if i < KANA.len() {
let mut output = Vec::with_capacity(KANA_SUB.len());
for (def,sub) in KANA_SUB_VALID_FOR.iter().zip(KANA_SUB.iter())
{
if def.contains(i) {
output.push(sub.clone());
}
}
Some(output)
} else {
None
}
}

@ -0,0 +1,59 @@
use crate::*;
#[derive(Debug,Clone,PartialEq,Eq,Hash)]
pub struct Digest(Option<char>, Option<char>);
impl Default for Digest
{
fn default() -> Self
{
Self(None,None)
}
}
impl Digest {
/// Create new single 2-byte digest.
pub fn new(from: &[u8]) -> Self
{
let mut d = Self::default();
let master = usize::from(from[0]) % map::KANA.len();
d.0 = Some(map::KANA[master]);
if from[1] > 0 {
if let Some(slaves) = map::sub(master) {
if slaves.len() > 0 {
d.1 = Some(slaves[usize::from(from[1]) % slaves.len()]);
return d;
}
}
let from = [from[1]];
d.1 = Self::new(&from[..]).0;
}
d
/*let master = usize::from(from) % map::KANA.len();
d.0 = Some(map::KANA[master]);
if let Some(slaves) = map::sub(master) {
if slaves.len() > 0 {
}
} else {
}
return d;*/
}
}
use std::fmt;
impl fmt::Display for Digest
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
if let Some(master) = self.0 {
write!(f, "{}", master)?;
}
if let Some(slave) = self.1 {
write!(f, "{}", slave)?;
}
Ok(())
}
}

@ -0,0 +1,15 @@
use crate::*;
pub trait ByteProvider: Sized + std::fmt::Display
{
fn compute<T: Read + ?Sized>(input: &mut T, provided: &mut usize) -> Result<Self, error::Error>;
fn bytes(&self) -> &[u8];
}
pub fn compute<T: Read + ?Sized, P: ByteProvider>(input: &mut T) -> Result<(usize, P), error::Error>
{
let mut output = 0usize;
let this = P::compute(input, &mut output)?;
Ok((output, this))
}

@ -0,0 +1,13 @@
pub unsafe fn bytes<'a, T>(src: &'a T) -> &'a [u8]
where T: ?Sized
{
std::slice::from_raw_parts(src as *const T as *const u8, std::mem::size_of_val(src))
}
pub unsafe fn bytes_mut<'a, T>(src: &'a mut T) -> &'a mut [u8]
where T: ?Sized
{
std::slice::from_raw_parts_mut(src as *mut T as *mut u8, std::mem::size_of_val(src))
}

@ -0,0 +1,49 @@
use std::borrow::Borrow;
/// Iter that converts 2 `u8`s into 1 `u16`
pub struct Bit16Iter<I>
where I: Iterator,
<I as Iterator>::Item: Borrow<u8>
{
iter: I,
}
impl<I> Iterator for Bit16Iter<I>
where I: Iterator,
<I as Iterator>::Item: Borrow<u8>
{
type Item = u16;
fn next(&mut self) -> Option<Self::Item>
{
let mut c = 0u16;
unsafe {
if let Some(a) = self.iter.next() {
crate::reinterpret::bytes_mut(&mut c)[0] = *a.borrow();
} else {
return None;
}
if let Some(b) = self.iter.next() {
crate::reinterpret::bytes_mut(&mut c)[1] = *b.borrow();
}
}
Some(c)
}
}
pub trait Bit16IterExt: Iterator + Sized
where <Self as Iterator>::Item: Borrow<u8>
{
fn into_16(self) -> Bit16Iter<Self>;
}
impl<I> Bit16IterExt for I
where I: Iterator,
<I as Iterator>::Item: Borrow<u8>
{
fn into_16(self) -> Bit16Iter<Self>
{
Bit16Iter{
iter: self
}
}
}
Loading…
Cancel
Save