1use std::io::{self, Read, Write};
11
12use crate::constants::*;
13use crate::protocol::{
14 flush_lines, parse_event_id, parse_single_integer, parse_single_value, parse_typed_lines,
15 write_lines,
16};
17use crate::types::*;
18
19#[cfg(all(not(feature = "async-mio"), unix))]
21pub use std::os::unix::io::AsRawFd as Source;
22
23#[cfg(feature = "async-mio")]
24pub use mio::event::Source;
25
26fn on_off(value: bool) -> &'static str {
28 if value {
29 "on"
30 } else {
31 "off"
32 }
33}
34
35#[derive(Debug, Clone)]
36pub enum Request {
38 SetName(ClientName),
39 Speak,
41 SendLine(String),
42 SendLines(Vec<String>),
43 SpeakChar(char),
44 SpeakKey(KeyName),
45 Stop(MessageScope),
47 Cancel(MessageScope),
48 Pause(MessageScope),
49 Resume(MessageScope),
50 SetPriority(Priority),
52 SetDebug(bool),
53 SetOutputModule(ClientScope, String),
54 GetOutputModule,
55 ListOutputModules,
56 SetLanguage(ClientScope, String),
57 GetLanguage,
58 SetSsmlMode(bool),
59 SetPunctuationMode(ClientScope, PunctuationMode),
60 SetSpelling(ClientScope, bool),
61 SetCapitalLettersRecognitionMode(ClientScope, CapitalLettersRecognitionMode),
62 SetVoiceType(ClientScope, String),
63 GetVoiceType,
64 ListVoiceTypes,
65 SetSynthesisVoice(ClientScope, String),
66 ListSynthesisVoices,
67 SetRate(ClientScope, i8),
68 GetRate,
69 SetPitch(ClientScope, i8),
70 GetPitch,
71 SetVolume(ClientScope, i8),
72 GetVolume,
73 SetPauseContext(ClientScope, u32),
74 SetNotification(NotificationType, bool),
75 Begin,
77 End,
78 SetHistory(ClientScope, bool),
80 HistoryGetClients,
81 HistoryGetClientId,
82 HistoryGetClientMsgs(ClientScope, u32, u32),
83 HistoryGetLastMsgId,
84 HistoryGetMsg(MessageId),
85 HistoryCursorGet,
86 HistoryCursorSet(ClientScope, HistoryPosition),
87 HistoryCursorMove(CursorDirection),
88 HistorySpeak(MessageId),
89 HistorySort(SortDirection, SortKey),
90 HistorySetShortMsgLength(u32),
91 HistorySetMsgTypeOrdering(Vec<Ordering>),
92 HistorySearch(ClientScope, String),
93 Quit,
95}
96
97impl Request {
98 pub fn is_data(&self) -> bool {
103 matches!(self, Request::SendLine(_) | Request::SendLines(_))
104 }
105}
106
107#[derive(Debug)]
108pub enum Response {
110 LanguageSet, PrioritySet, RateSet, PitchSet, PunctuationSet, CapLetRecognSet, SpellingSet, ClientNameSet, VoiceSet, Stopped, Paused, Resumed, Canceled, TableSet, OutputModuleSet, PauseContextSet, VolumeSet, SsmlModeSet, NotificationSet, PitchRangeSet, DebugSet, HistoryCurSetFirst, HistoryCurSetLast, HistoryCurSetPos, HistoryCurMoveFor, HistoryCurMoveBack, MessageQueued, SoundIconQueued, MessageCanceled, ReceivingData, Bye, HistoryClientListSent(Vec<HistoryClientStatus>), HistoryMsgsListSent(Vec<String>), HistoryLastMsg(String), HistoryCurPosRet(String), TableListSent(Vec<String>), HistoryClientIdSent(ClientId), MessageTextSent, HelpSent(Vec<String>), VoicesListSent(Vec<SynthesisVoice>), OutputModulesListSent(Vec<String>), Get(String), InsideBlock, OutsideBlock, NotImplemented, EventIndexMark(EventId, String), EventBegin(EventId), EventEnd(EventId), EventCanceled(EventId), EventPaused(EventId), EventResumed(EventId), }
162
163macro_rules! send_one_line {
164 ($self:expr, $fmt:expr, $( $arg:expr ),+) => {
165 flush_lines(&mut $self.output, &[format!($fmt, $( $arg ),+).as_str()])
166 };
167 ($self:expr, $fmt:expr) => {
168 flush_lines(&mut $self.output, &[$fmt])
169 }
170}
171
172macro_rules! send_toggle {
173 ($output:expr, $fmt:expr, $val:expr) => {
174 send_one_line!($output, $fmt, on_off($val))
175 };
176 ($output:expr, $fmt:expr, $arg:expr, $val:expr) => {
177 send_one_line!($output, $fmt, $arg, on_off($val))
178 };
179}
180
181macro_rules! send_range {
182 ($output:expr, $fmt:expr, $scope:expr, $val:expr) => {
183 send_one_line!(
184 $output,
185 $fmt,
186 $scope,
187 std::cmp::max(-100, std::cmp::min(100, $val))
188 )
189 };
190}
191
192#[derive(Debug)]
198pub struct Client<S: Read + Write + Source> {
199 input: io::BufReader<S>,
200 output: io::BufWriter<S>,
201}
202
203impl<S: Read + Write + Source> Client<S> {
204 pub(crate) fn new(input: io::BufReader<S>, output: io::BufWriter<S>) -> Self {
206 Self { input, output }
208 }
209
210 fn flush(&mut self) -> ClientResult<&mut Self> {
212 self.output.flush()?;
213 Ok(self)
214 }
215
216 #[cfg(all(not(feature = "async-mio"), unix))]
217 pub(crate) fn input_source(&self) -> &S {
219 self.input.get_ref()
220 }
221
222 #[cfg(all(not(feature = "async-mio"), unix))]
223 pub(crate) fn output_source(&self) -> &S {
225 self.output.get_ref()
226 }
227
228 pub fn send_lines(&mut self, lines: &[String]) -> ClientResult<&mut Self> {
230 const END_OF_DATA: [&str; 1] = ["."];
231 write_lines(
232 &mut self.output,
233 lines
234 .iter()
235 .map(|s| s.as_str())
236 .collect::<Vec<&str>>()
237 .as_slice(),
238 )?;
239 flush_lines(&mut self.output, &END_OF_DATA)?;
240 Ok(self)
241 }
242
243 pub fn send_line(&mut self, line: &str) -> ClientResult<&mut Self> {
245 const END_OF_DATA: &str = ".";
246 flush_lines(&mut self.output, &[line, END_OF_DATA])?;
247 Ok(self)
248 }
249
250 pub fn send(&mut self, request: Request) -> ClientResult<&mut Self> {
252 match request {
253 Request::SetName(client_name) => send_one_line!(
254 self,
255 "SET self CLIENT_NAME {}:{}:{}",
256 client_name.user,
257 client_name.application,
258 client_name.component
259 ),
260 Request::Speak => send_one_line!(self, "SPEAK"),
261 Request::SendLine(line) => self.send_line(&line).map(|_| ()),
262 Request::SendLines(lines) => self.send_lines(&lines).map(|_| ()),
263 Request::SpeakChar(ch) => send_one_line!(self, "CHAR {}", ch),
264 Request::SpeakKey(key) => send_one_line!(self, "KEY {}", key),
265 Request::Stop(scope) => send_one_line!(self, "STOP {}", scope),
266 Request::Cancel(scope) => send_one_line!(self, "CANCEL {}", scope),
267 Request::Pause(scope) => send_one_line!(self, "PAUSE {}", scope),
268 Request::Resume(scope) => send_one_line!(self, "RESUME {}", scope),
269 Request::SetPriority(prio) => send_one_line!(self, "SET self PRIORITY {}", prio),
270 Request::SetDebug(value) => send_toggle!(self, "SET all DEBUG {}", value),
271 Request::SetOutputModule(scope, value) => {
272 send_one_line!(self, "SET {} OUTPUT_MODULE {}", scope, value)
273 }
274 Request::GetOutputModule => send_one_line!(self, "GET OUTPUT_MODULE"),
275 Request::ListOutputModules => send_one_line!(self, "LIST OUTPUT_MODULES"),
276 Request::SetLanguage(scope, lang) => {
277 send_one_line!(self, "SET {} LANGUAGE {}", scope, lang)
278 }
279 Request::GetLanguage => send_one_line!(self, "GET LANGUAGE"),
280 Request::SetSsmlMode(value) => send_toggle!(self, "SET self SSML_MODE {}", value),
281 Request::SetPunctuationMode(scope, mode) => {
282 send_one_line!(self, "SET {} PUNCTUATION {}", scope, mode)
283 }
284 Request::SetSpelling(scope, value) => {
285 send_toggle!(self, "SET {} SPELLING {}", scope, value)
286 }
287 Request::SetCapitalLettersRecognitionMode(scope, mode) => {
288 send_one_line!(self, "SET {} CAP_LET_RECOGN {}", scope, mode)
289 }
290 Request::SetVoiceType(scope, value) => {
291 send_one_line!(self, "SET {} VOICE_TYPE {}", scope, value)
292 }
293 Request::GetVoiceType => send_one_line!(self, "GET VOICE_TYPE"),
294 Request::ListVoiceTypes => send_one_line!(self, "LIST VOICES"),
295 Request::SetSynthesisVoice(scope, value) => {
296 send_one_line!(self, "SET {} SYNTHESIS_VOICE {}", scope, value)
297 }
298 Request::ListSynthesisVoices => send_one_line!(self, "LIST SYNTHESIS_VOICES"),
299 Request::SetRate(scope, value) => send_range!(self, "SET {} RATE {}", scope, value),
300 Request::GetRate => send_one_line!(self, "GET RATE"),
301 Request::SetPitch(scope, value) => send_range!(self, "SET {} PITCH {}", scope, value),
302 Request::GetPitch => send_one_line!(self, "GET PITCH"),
303 Request::SetVolume(scope, value) => {
304 send_range!(self, "SET {} VOLUME {}", scope, value)
305 }
306 Request::GetVolume => send_one_line!(self, "GET VOLUME"),
307 Request::SetPauseContext(scope, value) => {
308 send_one_line!(self, "SET {} PAUSE_CONTEXT {}", scope, value)
309 }
310 Request::SetHistory(scope, value) => {
311 send_toggle!(self, "SET {} HISTORY {}", scope, value)
312 }
313 Request::SetNotification(ntype, value) => {
314 send_toggle!(self, "SET self NOTIFICATION {} {}", ntype, value)
315 }
316 Request::Begin => send_one_line!(self, "BLOCK BEGIN"),
317 Request::End => send_one_line!(self, "BLOCK END"),
318 Request::HistoryGetClients => send_one_line!(self, "HISTORY GET CLIENT_LIST"),
319 Request::HistoryGetClientId => send_one_line!(self, "HISTORY GET CLIENT_ID"),
320 Request::HistoryGetClientMsgs(scope, start, number) => send_one_line!(
321 self,
322 "HISTORY GET CLIENT_MESSAGES {} {}_{}",
323 scope,
324 start,
325 number
326 ),
327 Request::HistoryGetLastMsgId => send_one_line!(self, "HISTORY GET LAST"),
328 Request::HistoryGetMsg(id) => send_one_line!(self, "HISTORY GET MESSAGE {}", id),
329 Request::HistoryCursorGet => send_one_line!(self, "HISTORY CURSOR GET"),
330 Request::HistoryCursorSet(scope, pos) => {
331 send_one_line!(self, "HISTORY CURSOR SET {} {}", scope, pos)
332 }
333 Request::HistoryCursorMove(direction) => {
334 send_one_line!(self, "HISTORY CURSOR {}", direction)
335 }
336 Request::HistorySpeak(id) => send_one_line!(self, "HISTORY SAY {}", id),
337 Request::HistorySort(direction, key) => {
338 send_one_line!(self, "HISTORY SORT {} {}", direction, key)
339 }
340 Request::HistorySetShortMsgLength(length) => {
341 send_one_line!(self, "HISTORY SET SHORT_MESSAGE_LENGTH {}", length)
342 }
343 Request::HistorySetMsgTypeOrdering(ordering) => {
344 send_one_line!(
345 self,
346 "HISTORY SET MESSAGE_TYPE_ORDERING \"{}\"",
347 ordering
348 .iter()
349 .map(|x| x.to_string())
350 .collect::<Vec<String>>()
351 .join(" ")
352 )
353 }
354 Request::HistorySearch(scope, condition) => {
355 send_one_line!(self, "HISTORY SEARCH {} \"{}\"", scope, condition)
356 }
357 Request::Quit => send_one_line!(self, "QUIT"),
358 }?;
359 Ok(self)
360 }
361
362 pub fn set_client_name(&mut self, client_name: ClientName) -> ClientResult<&mut Self> {
364 self.send(Request::SetName(client_name))
365 }
366
367 pub fn speak(&mut self) -> ClientResult<&mut Self> {
369 self.send(Request::Speak)
370 }
371
372 pub fn speak_char(&mut self, ch: char) -> ClientResult<&mut Self> {
374 self.send(Request::SpeakChar(ch))
375 }
376
377 pub fn speak_key(&mut self, key_name: KeyName) -> ClientResult<&mut Self> {
379 self.send(Request::SpeakKey(key_name))
380 }
381
382 pub fn stop(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
384 self.send(Request::Stop(scope))
385 }
386
387 pub fn cancel(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
389 self.send(Request::Cancel(scope))
390 }
391
392 pub fn pause(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
394 self.send(Request::Pause(scope))
395 }
396
397 pub fn resume(&mut self, scope: MessageScope) -> ClientResult<&mut Self> {
399 self.send(Request::Resume(scope))
400 }
401
402 pub fn set_priority(&mut self, prio: Priority) -> ClientResult<&mut Self> {
404 self.send(Request::SetPriority(prio))
405 }
406
407 pub fn set_debug(&mut self, value: bool) -> ClientResult<&mut Self> {
409 self.send(Request::SetDebug(value))
410 }
411
412 pub fn set_output_module(
414 &mut self,
415 scope: ClientScope,
416 value: &str,
417 ) -> ClientResult<&mut Self> {
418 self.send(Request::SetOutputModule(scope, value.to_string()))
419 }
420
421 pub fn get_output_module(&mut self) -> ClientResult<&mut Self> {
423 self.send(Request::GetOutputModule)
424 }
425
426 pub fn list_output_modules(&mut self) -> ClientResult<&mut Self> {
428 self.send(Request::ListOutputModules)
429 }
430
431 pub fn set_language(&mut self, scope: ClientScope, value: &str) -> ClientResult<&mut Self> {
433 self.send(Request::SetLanguage(scope, value.to_string()))
434 }
435
436 pub fn get_language(&mut self) -> ClientResult<&mut Self> {
438 self.send(Request::GetLanguage)
439 }
440
441 pub fn set_ssml_mode(&mut self, mode: bool) -> ClientResult<&mut Self> {
443 self.send(Request::SetSsmlMode(mode))
444 }
445
446 pub fn set_punctuation_mode(
448 &mut self,
449 scope: ClientScope,
450 mode: PunctuationMode,
451 ) -> ClientResult<&mut Self> {
452 self.send(Request::SetPunctuationMode(scope, mode))
453 }
454
455 pub fn set_spelling(&mut self, scope: ClientScope, value: bool) -> ClientResult<&mut Self> {
457 self.send(Request::SetSpelling(scope, value))
458 }
459
460 pub fn set_capital_letter_recogn(
462 &mut self,
463 scope: ClientScope,
464 mode: CapitalLettersRecognitionMode,
465 ) -> ClientResult<&mut Self> {
466 self.send(Request::SetCapitalLettersRecognitionMode(scope, mode))
467 }
468
469 pub fn set_voice_type(&mut self, scope: ClientScope, value: &str) -> ClientResult<&mut Self> {
471 self.send(Request::SetVoiceType(scope, value.to_string()))
472 }
473
474 pub fn get_voice_type(&mut self) -> ClientResult<&mut Self> {
476 self.send(Request::GetVoiceType)
477 }
478
479 pub fn list_voice_types(&mut self) -> ClientResult<&mut Self> {
481 self.send(Request::ListVoiceTypes)
482 }
483
484 pub fn set_synthesis_voice(
486 &mut self,
487 scope: ClientScope,
488 value: &str,
489 ) -> ClientResult<&mut Self> {
490 self.send(Request::SetSynthesisVoice(scope, value.to_string()))
491 }
492
493 pub fn list_synthesis_voices(&mut self) -> ClientResult<&mut Self> {
495 self.send(Request::ListSynthesisVoices)
496 }
497
498 pub fn set_rate(&mut self, scope: ClientScope, value: i8) -> ClientResult<&mut Self> {
500 self.send(Request::SetRate(scope, value))
501 }
502
503 pub fn get_rate(&mut self) -> ClientResult<&mut Self> {
505 self.send(Request::GetRate)
506 }
507
508 pub fn set_pitch(&mut self, scope: ClientScope, value: i8) -> ClientResult<&mut Self> {
510 self.send(Request::SetPitch(scope, value))
511 }
512
513 pub fn get_pitch(&mut self) -> ClientResult<&mut Self> {
515 self.send(Request::GetPitch)
516 }
517
518 pub fn set_volume(&mut self, scope: ClientScope, value: i8) -> ClientResult<&mut Self> {
520 self.send(Request::SetVolume(scope, value))
521 }
522
523 pub fn get_volume(&mut self) -> ClientResult<&mut Self> {
525 self.send(Request::GetVolume)
526 }
527
528 pub fn set_pause_context(&mut self, scope: ClientScope, value: u32) -> ClientResult<&mut Self> {
530 self.send(Request::SetPauseContext(scope, value))
531 }
532
533 pub fn set_notification(
535 &mut self,
536 ntype: NotificationType,
537 value: bool,
538 ) -> ClientResult<&mut Self> {
539 self.send(Request::SetNotification(ntype, value))
540 }
541
542 pub fn block_begin(&mut self) -> ClientResult<&mut Self> {
544 self.send(Request::Begin)
545 }
546
547 pub fn block_end(&mut self) -> ClientResult<&mut Self> {
549 self.send(Request::End)
550 }
551
552 pub fn set_history(&mut self, scope: ClientScope, value: bool) -> ClientResult<&mut Self> {
554 self.send(Request::SetHistory(scope, value))
555 }
556
557 pub fn history_get_clients(&mut self) -> ClientResult<&mut Self> {
559 self.send(Request::HistoryGetClients)
560 }
561
562 pub fn history_get_client_id(&mut self) -> ClientResult<&mut Self> {
564 self.send(Request::HistoryGetClientId)
565 }
566
567 pub fn history_get_last(&mut self) -> ClientResult<&mut Self> {
569 self.send(Request::HistoryGetLastMsgId)
570 }
571
572 pub fn history_get_client_messages(
574 &mut self,
575 scope: ClientScope,
576 start: u32,
577 number: u32,
578 ) -> ClientResult<&mut Self> {
579 self.send(Request::HistoryGetClientMsgs(scope, start, number))
580 }
581
582 pub fn history_get_last_message_id(&mut self) -> ClientResult<&mut Self> {
584 self.send(Request::HistoryGetLastMsgId)
585 }
586
587 pub fn history_get_message(&mut self, msg_id: MessageId) -> ClientResult<&mut Self> {
589 self.send(Request::HistoryGetMsg(msg_id))
590 }
591
592 pub fn history_get_cursor(&mut self) -> ClientResult<&mut Self> {
594 self.send(Request::HistoryCursorGet)
595 }
596
597 pub fn history_set_cursor(
599 &mut self,
600 scope: ClientScope,
601 pos: HistoryPosition,
602 ) -> ClientResult<&mut Self> {
603 self.send(Request::HistoryCursorSet(scope, pos))
604 }
605
606 pub fn history_move_cursor(&mut self, direction: CursorDirection) -> ClientResult<&mut Self> {
608 self.send(Request::HistoryCursorMove(direction))
609 }
610
611 pub fn history_speak(&mut self, msg_id: MessageId) -> ClientResult<&mut Self> {
613 self.send(Request::HistorySpeak(msg_id))
614 }
615
616 pub fn history_sort(
618 &mut self,
619 direction: SortDirection,
620 key: SortKey,
621 ) -> ClientResult<&mut Self> {
622 self.send(Request::HistorySort(direction, key))
623 }
624
625 pub fn history_set_short_message_length(&mut self, length: u32) -> ClientResult<&mut Self> {
627 self.send(Request::HistorySetShortMsgLength(length))
628 }
629
630 pub fn history_set_ordering(&mut self, ordering: Vec<Ordering>) -> ClientResult<&mut Self> {
632 self.send(Request::HistorySetMsgTypeOrdering(ordering))
633 }
634
635 pub fn history_search(
637 &mut self,
638 scope: ClientScope,
639 condition: &str,
640 ) -> ClientResult<&mut Self> {
641 self.send(Request::HistorySearch(scope, condition.to_string()))
642 }
643
644 pub fn quit(&mut self) -> ClientResult<&mut Self> {
646 self.send(Request::Quit)
647 }
648
649 fn receive_answer(&mut self, lines: &mut Vec<String>) -> ClientStatus {
651 crate::protocol::receive_answer(&mut self.input, Some(lines))
652 }
653
654 pub fn receive(&mut self) -> ClientResult<Response> {
656 const MSG_CURSOR_SET_FIRST: &str = "OK CURSOR SET FIRST";
657 let mut lines = Vec::new();
658 let status = self.receive_answer(&mut lines)?;
659 match status.code {
660 OK_LANGUAGE_SET => Ok(Response::LanguageSet),
661 OK_PRIORITY_SET => Ok(Response::PrioritySet),
662 OK_RATE_SET => Ok(Response::RateSet),
663 OK_PITCH_SET => Ok(Response::PitchSet),
664 OK_PUNCTUATION_SET => Ok(Response::PunctuationSet),
665 OK_CAP_LET_RECOGN_SET => Ok(Response::CapLetRecognSet),
666 OK_SPELLING_SET => Ok(Response::SpellingSet),
667 OK_CLIENT_NAME_SET => Ok(Response::ClientNameSet),
668 OK_VOICE_SET => Ok(Response::VoiceSet),
669 OK_STOPPED => Ok(Response::Stopped),
670 OK_PAUSED => Ok(Response::Paused),
671 OK_RESUMED => Ok(Response::Resumed),
672 OK_CANCELED => Ok(Response::Canceled),
673 OK_TABLE_SET => Ok(Response::TableSet),
674 OK_OUTPUT_MODULE_SET => Ok(Response::OutputModuleSet),
675 OK_PAUSE_CONTEXT_SET => Ok(Response::PauseContextSet),
676 OK_VOLUME_SET => Ok(Response::VolumeSet),
677 OK_SSML_MODE_SET => Ok(Response::SsmlModeSet),
678 OK_NOTIFICATION_SET => {
680 if status.message == MSG_CURSOR_SET_FIRST {
681 Ok(Response::HistoryCurSetFirst)
683 } else {
684 Ok(Response::NotificationSet)
685 }
686 }
687 OK_CUR_SET_LAST => Ok(Response::HistoryCurSetLast),
688 OK_CUR_SET_POS => Ok(Response::HistoryCurSetPos),
689 OK_PITCH_RANGE_SET => Ok(Response::PitchRangeSet),
690 OK_DEBUG_SET => Ok(Response::DebugSet),
691 OK_CUR_MOV_FOR => Ok(Response::HistoryCurMoveFor),
692 OK_CUR_MOV_BACK => Ok(Response::HistoryCurMoveBack),
693 OK_MESSAGE_QUEUED => Ok(Response::MessageQueued),
694 OK_SND_ICON_QUEUED => Ok(Response::SoundIconQueued),
695 OK_MSG_CANCELED => Ok(Response::MessageCanceled),
696 OK_RECEIVING_DATA => Ok(Response::ReceivingData),
697 OK_BYE => Ok(Response::Bye),
698 OK_CLIENTS_LIST_SENT => Ok(Response::HistoryClientListSent(parse_typed_lines::<
699 HistoryClientStatus,
700 >(&lines)?)),
701 OK_MSGS_LIST_SENT => Ok(Response::HistoryMsgsListSent(lines)),
702 OK_LAST_MSG => Ok(Response::HistoryLastMsg(parse_single_value(&lines)?)),
703 OK_CUR_POS_RET => Ok(Response::HistoryCurPosRet(parse_single_value(&lines)?)),
704 OK_TABLE_LIST_SENT => Ok(Response::TableListSent(lines)),
705 OK_CLIENT_ID_SENT => Ok(Response::HistoryClientIdSent(parse_single_integer(&lines)?)),
706 OK_MSG_TEXT_SENT => Ok(Response::MessageTextSent),
707 OK_HELP_SENT => Ok(Response::HelpSent(lines)),
708 OK_VOICES_LIST_SENT => Ok(Response::VoicesListSent(
709 parse_typed_lines::<SynthesisVoice>(&lines)?,
710 )),
711 OK_OUTPUT_MODULES_LIST_SENT => Ok(Response::OutputModulesListSent(lines)),
712 OK_GET => Ok(Response::Get(parse_single_value(&lines)?)),
713 OK_INSIDE_BLOCK => Ok(Response::InsideBlock),
714 OK_OUTSIDE_BLOCK => Ok(Response::OutsideBlock),
715 OK_NOT_IMPLEMENTED => Ok(Response::NotImplemented),
716 EVENT_INDEX_MARK => match lines.len() {
717 0..=2 => Err(ClientError::TooFewLines),
718 3 => Ok(Response::EventIndexMark(
719 parse_event_id(&lines)?,
720 lines[2].to_owned(),
721 )),
722 _ => Err(ClientError::TooManyLines),
723 },
724 EVENT_BEGIN => Ok(Response::EventBegin(parse_event_id(&lines)?)),
725 EVENT_END => Ok(Response::EventEnd(parse_event_id(&lines)?)),
726 EVENT_CANCELED => Ok(Response::EventCanceled(parse_event_id(&lines)?)),
727 EVENT_PAUSED => Ok(Response::EventPaused(parse_event_id(&lines)?)),
728 EVENT_RESUMED => Ok(Response::EventResumed(parse_event_id(&lines)?)),
729 _ => panic!("error should have been caught earlier"),
730 }
731 }
732
733 pub fn check_status(&mut self, expected_code: ReturnCode) -> ClientResult<&mut Self> {
735 crate::protocol::receive_answer(&mut self.input, None).and_then(|status| {
736 if status.code == expected_code {
737 Ok(self)
738 } else {
739 Err(ClientError::UnexpectedStatus(status.code))
740 }
741 })
742 }
743
744 pub fn receive_lines(&mut self, expected_code: ReturnCode) -> ClientResult<Vec<String>> {
746 let mut lines = Vec::new();
747 let status = self.receive_answer(&mut lines)?;
748 if status.code == expected_code {
749 Ok(lines)
750 } else {
751 Err(ClientError::UnexpectedStatus(status.code))
752 }
753 }
754
755 pub fn receive_string(&mut self, expected_code: ReturnCode) -> ClientResult<String> {
757 self.receive_lines(expected_code)
758 .and_then(|lines| parse_single_value(&lines))
759 }
760
761 pub fn receive_i8(&mut self) -> ClientResult<u8> {
763 self.receive_string(OK_GET).and_then(|s| {
764 s.parse()
765 .map_err(|_| ClientError::invalid_data("invalid signed integer"))
766 })
767 }
768
769 pub fn receive_u8(&mut self) -> ClientResult<u8> {
771 self.receive_string(OK_GET).and_then(|s| {
772 s.parse()
773 .map_err(|_| ClientError::invalid_data("invalid unsigned 8-bit integer"))
774 })
775 }
776
777 pub fn receive_cursor_pos(&mut self) -> ClientResult<u16> {
779 self.receive_string(OK_CUR_POS_RET).and_then(|s| {
780 s.parse()
781 .map_err(|_| ClientError::invalid_data("invalid unsigned 16-bit integer"))
782 })
783 }
784
785 pub fn receive_message_id(&mut self) -> ClientResult<MessageId> {
787 let mut lines = Vec::new();
788 match self.receive_answer(&mut lines)?.code {
789 OK_MESSAGE_QUEUED | OK_LAST_MSG => Ok(parse_single_integer(&lines)?),
790 _ => Err(ClientError::invalid_data("not a message id")),
791 }
792 }
793
794 pub fn receive_client_id(&mut self) -> ClientResult<ClientId> {
796 self.receive_string(OK_CLIENT_ID_SENT).and_then(|s| {
797 s.parse()
798 .map_err(|_| ClientError::invalid_data("invalid client id"))
799 })
800 }
801
802 pub fn receive_synthesis_voices(&mut self) -> ClientResult<Vec<SynthesisVoice>> {
804 self.receive_lines(OK_VOICES_LIST_SENT)
805 .and_then(|lines| parse_typed_lines::<SynthesisVoice>(&lines))
806 }
807
808 pub fn receive_event(&mut self) -> ClientResult<Event> {
810 let mut lines = Vec::new();
811 crate::protocol::receive_answer(&mut self.input, Some(&mut lines)).and_then(|status| {
812 if lines.len() < 2 {
813 Err(ClientError::unexpected_eof("event truncated"))
814 } else {
815 let message = &lines[0];
816 let client = &lines[1];
817 match status.code {
818 700 => {
819 if lines.len() != 3 {
820 Err(ClientError::unexpected_eof("index markevent truncated"))
821 } else {
822 let mark = lines[3].to_owned();
823 Ok(Event::index_mark(mark, message, client))
824 }
825 }
826 701 => Ok(Event::begin(message, client)),
827 702 => Ok(Event::end(message, client)),
828 703 => Ok(Event::cancel(message, client)),
829 704 => Ok(Event::pause(message, client)),
830 705 => Ok(Event::resume(message, client)),
831 _ => Err(ClientError::invalid_data("wrong status code for event")),
832 }
833 }
834 })
835 }
836
837 pub fn receive_history_clients(&mut self) -> ClientResult<Vec<HistoryClientStatus>> {
839 self.receive_lines(OK_CLIENTS_LIST_SENT)
840 .and_then(|lines| parse_typed_lines::<HistoryClientStatus>(&lines))
841 }
842
843 pub fn check_client_name_set(&mut self) -> ClientResult<&mut Self> {
845 self.check_status(OK_CLIENT_NAME_SET)
846 }
847
848 pub fn check_receiving_data(&mut self) -> ClientResult<&mut Self> {
850 self.check_status(OK_RECEIVING_DATA)
851 }
852
853 #[cfg(feature = "async-mio")]
855 pub fn register(
856 &mut self,
857 poll: &mio::Poll,
858 input_token: mio::Token,
859 output_token: mio::Token,
860 ) -> io::Result<()> {
861 poll.registry()
862 .register(self.input.get_mut(), input_token, mio::Interest::READABLE)?;
863 poll.registry()
864 .register(self.output.get_mut(), output_token, mio::Interest::WRITABLE)?;
865 Ok(())
866 }
867}
868
869impl<S: Read + Write + Source> Drop for Client<S> {
870 fn drop(&mut self) {
871 let _ = self.flush();
872 }
873}
874
875#[cfg(test)]
876mod test {
877
878 use super::Request;
879
880 #[test]
881 fn test_is_data() {
882 assert!(Request::SendLine("".to_owned()).is_data());
883 assert!(Request::SendLines(vec![]).is_data());
884 assert!(!Request::Speak.is_data());
885 assert!(!Request::SpeakChar('a').is_data());
886 }
887}