1use std::fmt;
21
22#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
24pub enum Pos {
25 Noun,
26 Verb,
27 Adj,
28 Adv,
29}
30
31impl Pos {
32 pub fn from_char(c: char) -> Option<Self> {
34 match c {
35 'n' => Some(Pos::Noun),
36 'v' => Some(Pos::Verb),
37 'a' | 's' => Some(Pos::Adj),
38 'r' => Some(Pos::Adv),
39 _ => None,
40 }
41 }
42
43 pub fn to_char(self) -> char {
45 match self {
46 Pos::Noun => 'n',
47 Pos::Verb => 'v',
48 Pos::Adj => 'a',
49 Pos::Adv => 'r',
50 }
51 }
52}
53
54impl fmt::Display for Pos {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.write_str(match self {
57 Pos::Noun => "noun",
58 Pos::Verb => "verb",
59 Pos::Adj => "adj",
60 Pos::Adv => "adv",
61 })
62 }
63}
64
65#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
67pub struct SynsetId {
68 pub pos: Pos,
69 pub offset: u32,
70}
71
72#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
74pub enum SynsetType {
75 Noun,
76 Verb,
77 Adj,
78 Adv,
79 AdjSatellite,
80}
81
82impl SynsetType {
83 pub fn from_char(c: char) -> Option<Self> {
85 match c {
86 'n' => Some(SynsetType::Noun),
87 'v' => Some(SynsetType::Verb),
88 'a' => Some(SynsetType::Adj),
89 's' => Some(SynsetType::AdjSatellite),
90 'r' => Some(SynsetType::Adv),
91 _ => None,
92 }
93 }
94}
95
96#[derive(Clone, Debug)]
98pub struct Lemma<'a> {
99 pub text: &'a str,
100 pub lex_id: u8,
101}
102
103#[derive(Clone, Debug)]
105pub struct Frame {
106 pub frame_number: u16,
107 pub word_number: Option<u16>,
108}
109
110#[derive(Clone, Debug)]
112pub struct Pointer<'a> {
113 pub symbol: &'a str,
114 pub target: SynsetId,
115 pub src_word: Option<u16>,
116 pub dst_word: Option<u16>,
117}
118
119#[derive(Clone, Debug)]
121pub struct Gloss<'a> {
122 pub raw: &'a str,
123 pub definition: &'a str,
124 pub examples: Vec<&'a str>,
125}
126
127#[derive(Clone, Debug)]
129pub struct Synset<'a> {
130 pub id: SynsetId,
131 pub lex_filenum: u8,
132 pub synset_type: SynsetType,
133 pub words: Vec<Lemma<'a>>,
134 pub pointers: Vec<Pointer<'a>>,
135 pub frames: &'a [Frame],
136 pub gloss: Gloss<'a>,
137}
138
139#[derive(Clone, Debug)]
141pub struct IndexEntry<'a> {
142 pub lemma: &'a str,
143 pub pos: Pos,
144 pub synset_cnt: u32,
145 pub p_cnt: u32,
146 pub ptr_symbols: Vec<&'a str>,
147 pub sense_cnt: u32,
148 pub tagsense_cnt: u32,
149 pub synset_offsets: &'a [u32],
150}
151
152pub fn decode_st(hex4: &str) -> (Option<u16>, Option<u16>) {
157 if hex4.len() != 4 {
158 return (None, None);
159 }
160
161 match u16::from_str_radix(hex4, 16) {
162 Ok(val) => {
163 let src = val >> 8;
164 let dst = val & 0x00FF;
165 let src = if src == 0 { None } else { Some(src) };
166 let dst = if dst == 0 { None } else { Some(dst) };
167 (src, dst)
168 }
169 Err(_) => (None, None),
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn decode_source_target() {
179 assert_eq!(decode_st("0000"), (None, None));
180 assert_eq!(decode_st("0100"), (Some(1), None));
181 assert_eq!(decode_st("00ff"), (None, Some(255)));
182 assert_eq!(decode_st("0a0b"), (Some(10), Some(11)));
183 assert_eq!(decode_st("bad"), (None, None));
184 }
185}