1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
use std::fmt; use std::io::{self, Write}; use std::borrow::Borrow; use byteorder::{ByteOrder, NativeEndian, WriteBytesExt}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Morph<S> where S: Borrow<str> { pub surface: S, pub left_id: u16, pub right_id: u16, pub weight: i16, pub contents: S, } impl<S: Borrow<str>> Morph<S> { pub fn encode<W: Write, O: ByteOrder>(&self, mut w: W) -> io::Result<()> { let surface_bytes = self.surface.borrow().as_bytes(); w.write_u32::<O>(surface_bytes.len() as u32)?; w.write_all(surface_bytes)?; w.write_u16::<O>(self.left_id)?; w.write_u16::<O>(self.right_id)?; w.write_i16::<O>(self.weight)?; let contents_bytes = self.contents.borrow().as_bytes(); w.write_u32::<O>(contents_bytes.len() as u32)?; w.write_all(contents_bytes)?; Ok(()) } pub fn encode_native<W: Write>(&self, w: W) -> io::Result<()> { self.encode::<W, NativeEndian>(w) } } impl<'a> Morph<&'a str> { pub unsafe fn decode(mut bs: &'a [u8]) -> Self { let ptr = bs.as_ptr() as *const u32; let surface_len = *ptr; bs = &bs[::std::mem::size_of::<u32>()..]; let surface = ::std::str::from_utf8_unchecked(&bs[..surface_len as usize]); bs = &bs[surface_len as usize..]; let ptr = bs.as_ptr() as *const u16; let left_id = *ptr; let right_id = *ptr.offset(1); let weight = *(ptr.offset(2) as *const i16); bs = &bs[::std::mem::size_of::<i16>() * 3..]; let ptr = bs.as_ptr() as *const u32; let contents_len = *ptr; bs = &bs[::std::mem::size_of::<u32>()..]; let contents = ::std::str::from_utf8_unchecked(&bs[..contents_len as usize]); Morph { surface: surface, left_id: left_id, right_id: right_id, weight: weight, contents: contents, } } } impl<S: Borrow<str>> fmt::Display for Morph<S> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{},{},{},{},{}", self.surface.borrow(), self.left_id, self.right_id, self.weight, self.contents.borrow()) } } #[test] fn test_encode_decode() { let m = Morph { surface: "見出し語", left_id: 1, right_id: 2, weight: 3, contents: "contents", }; let mut buf = Vec::new(); m.encode_native(&mut buf).unwrap(); let m2 = unsafe { Morph::decode(&buf) }; assert_eq!(m2, m); }