1#[derive(Clone)]
3pub struct Settings {
4 pub(crate) inner: crate::sys::Settings,
5}
6
7pub const COMMON_BAUD_RATES: &[u32] = &[
14 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1500000, 2000000,
15];
16
17macro_rules! delegate_impl {
19 (TryFrom<$from:ty> for $for:ty as u8) => {
20 impl TryFrom<$from> for $for {
21 type Error = TryFromError<$from>;
22
23 fn try_from(value: $from) -> Result<Self, Self::Error> {
24 let narrowed = u8::try_from(value)
25 .map_err(|_| Self::unexpected(value))?;
26 Self::try_from(narrowed)
27 .map_err(|_| Self::unexpected(value))
28 }
29 }
30 };
31}
32
33#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
40#[repr(u8)]
41pub enum CharSize {
42 Bits5 = 5,
49
50 Bits6 = 6,
57
58 Bits7 = 7,
65
66 Bits8 = 8,
73}
74
75impl CharSize {
76 const EXPECTED: &'static str = "the number 5, 6, 7 or 8";
77
78 pub fn as_u8(self) -> u8 {
80 self as u8
81 }
82
83 fn unexpected<T>(unexpected: T) -> TryFromError<T> {
85 TryFromError {
86 unexpected,
87 expected: Self::EXPECTED,
88 }
89 }
90}
91
92impl std::fmt::Display for CharSize {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 std::fmt::Display::fmt(&self.as_u8(), f)
95 }
96}
97
98impl TryFrom<u8> for CharSize {
99 type Error = TryFromError<u8>;
100
101 fn try_from(value: u8) -> Result<Self, Self::Error> {
102 match value {
103 5 => Ok(Self::Bits5),
104 6 => Ok(Self::Bits6),
105 7 => Ok(Self::Bits7),
106 8 => Ok(Self::Bits8),
107 x => Err(Self::unexpected(x)),
108 }
109 }
110}
111
112delegate_impl!(TryFrom<i8> for CharSize as u8);
113delegate_impl!(TryFrom<u16> for CharSize as u8);
114delegate_impl!(TryFrom<i16> for CharSize as u8);
115delegate_impl!(TryFrom<u32> for CharSize as u8);
116delegate_impl!(TryFrom<i32> for CharSize as u8);
117delegate_impl!(TryFrom<u64> for CharSize as u8);
118delegate_impl!(TryFrom<i64> for CharSize as u8);
119delegate_impl!(TryFrom<usize> for CharSize as u8);
120delegate_impl!(TryFrom<isize> for CharSize as u8);
121
122#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
129#[repr(u8)]
130pub enum StopBits {
131 One = 1,
138
139 Two = 2,
146}
147
148impl StopBits {
149 const EXPECTED: &'static str = "the number 1 or 2";
150
151 pub fn as_u8(self) -> u8 {
153 self as u8
154 }
155
156 fn unexpected<T>(unexpected: T) -> TryFromError<T> {
158 TryFromError {
159 unexpected,
160 expected: Self::EXPECTED,
161 }
162 }
163}
164
165impl std::fmt::Display for StopBits {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 std::fmt::Display::fmt(&self.as_u8(), f)
168 }
169}
170
171impl TryFrom<u8> for StopBits {
172 type Error = TryFromError<u8>;
173
174 fn try_from(value: u8) -> Result<Self, Self::Error> {
175 match value {
176 1 => Ok(Self::One),
177 2 => Ok(Self::Two),
178 x => Err(Self::unexpected(x)),
179 }
180 }
181}
182
183delegate_impl!(TryFrom<i8> for StopBits as u8);
184delegate_impl!(TryFrom<u16> for StopBits as u8);
185delegate_impl!(TryFrom<i16> for StopBits as u8);
186delegate_impl!(TryFrom<u32> for StopBits as u8);
187delegate_impl!(TryFrom<i32> for StopBits as u8);
188delegate_impl!(TryFrom<u64> for StopBits as u8);
189delegate_impl!(TryFrom<i64> for StopBits as u8);
190delegate_impl!(TryFrom<usize> for StopBits as u8);
191delegate_impl!(TryFrom<isize> for StopBits as u8);
192
193#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
200pub enum Parity {
201 None,
208
209 Odd,
220
221 Even,
232}
233
234impl Parity {
235 const EXPECTED: &'static str = "the string \"none\", \"odd\" or \"even\"";
236
237 pub fn as_str(self) -> &'static str {
239 match self {
240 Self::None => "none",
241 Self::Odd => "odd",
242 Self::Even => "even",
243 }
244 }
245
246 #[allow(clippy::should_implement_trait)] pub fn from_str(input: &str) -> Result<Self, TryFromError<&str>> {
249 match input {
250 "none" => Ok(Self::None),
251 "odd" => Ok(Self::Odd),
252 "even" => Ok(Self::Even),
253 unexpected => Err(TryFromError {
254 unexpected,
255 expected: Self::EXPECTED,
256 }),
257 }
258 }
259}
260
261impl std::fmt::Display for Parity {
262 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
263 f.write_str(self.as_str())
264 }
265}
266
267impl<'a> TryFrom<&'a str> for Parity {
268 type Error = TryFromError<&'a str>;
269
270 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
271 Self::from_str(value)
272 }
273}
274
275impl std::str::FromStr for Parity {
276 type Err = TryFromError<String>;
277
278 fn from_str(input: &str) -> Result<Self, Self::Err> {
279 Self::from_str(input).map_err(|e| e.convert())
280 }
281}
282
283#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
290pub enum FlowControl {
291 None,
298
299 XonXoff,
308
309 RtsCts,
318}
319
320impl FlowControl {
321 const EXPECTED: &'static str = "the string \"none\", \"xon/xoff\" or \"rts/cts\"";
322
323 pub fn as_str(self) -> &'static str {
325 match self {
326 Self::None => "none",
327 Self::XonXoff => "xon/xoff",
328 Self::RtsCts => "rts/cts",
329 }
330 }
331
332 #[allow(clippy::should_implement_trait)] pub fn from_str(input: &str) -> Result<Self, TryFromError<&str>> {
335 match input {
336 "none" => Ok(Self::None),
337 "xon/xoff" => Ok(Self::XonXoff),
338 "rts/cts" => Ok(Self::RtsCts),
339 unexpected => Err(TryFromError {
340 unexpected,
341 expected: Self::EXPECTED,
342 }),
343 }
344 }
345}
346
347impl std::fmt::Display for FlowControl {
348 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
349 f.write_str(self.as_str())
350 }
351}
352
353impl<'a> TryFrom<&'a str> for FlowControl {
354 type Error = TryFromError<&'a str>;
355
356 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
357 match value {
358 "none" => Ok(Self::None),
359 "xon/xoff" => Ok(Self::XonXoff),
360 "rts/cts" => Ok(Self::RtsCts),
361 unexpected => Err(TryFromError {
362 unexpected,
363 expected: Self::EXPECTED,
364 }),
365 }
366 }
367}
368
369impl std::str::FromStr for FlowControl {
370 type Err = TryFromError<String>;
371
372 fn from_str(input: &str) -> Result<Self, Self::Err> {
373 Self::from_str(input).map_err(|e| e.convert())
374 }
375}
376
377impl Settings {
378 pub fn set_raw(&mut self) {
386 self.inner.set_raw();
387 }
388
389 pub fn set_baud_rate(&mut self, baud_rate: u32) -> std::io::Result<()> {
395 self.inner.set_baud_rate(baud_rate)
396 }
397
398 pub fn get_baud_rate(&self) -> std::io::Result<u32> {
400 self.inner.get_baud_rate()
401 }
402
403 pub fn set_char_size(&mut self, char_size: CharSize) {
405 self.inner.set_char_size(char_size)
406 }
407
408 pub fn get_char_size(&self) -> std::io::Result<CharSize> {
410 self.inner.get_char_size()
411 }
412
413 pub fn set_stop_bits(&mut self, stop_bits: StopBits) {
415 self.inner.set_stop_bits(stop_bits)
416 }
417
418 pub fn get_stop_bits(&self) -> std::io::Result<StopBits> {
420 self.inner.get_stop_bits()
421 }
422
423 pub fn set_parity(&mut self, parity: Parity) {
425 self.inner.set_parity(parity)
426 }
427
428 pub fn get_parity(&self) -> std::io::Result<Parity> {
430 self.inner.get_parity()
431 }
432
433 pub fn set_flow_control(&mut self, flow_control: FlowControl) {
437 self.inner.set_flow_control(flow_control)
438 }
439
440 pub fn get_flow_control(&self) -> std::io::Result<FlowControl> {
442 self.inner.get_flow_control()
443 }
444
445 #[cfg(any(feature = "doc", all(unix, feature = "unix")))]
453 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "unix")))]
454 pub fn as_termios(&self) -> &crate::os::unix::RawTermios {
455 #[cfg(unix)] {
456 &self.inner.termios
457 }
458 #[cfg(not(unix))] {
459 unreachable!("this code is only enabled on Unix platforms or during documentation generation")
460 }
461 }
462
463 #[cfg(any(feature = "doc", all(unix, feature = "unix")))]
471 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "unix")))]
472 pub fn as_termios_mut(&mut self) -> &mut crate::os::unix::RawTermios {
473 #[cfg(unix)] {
474 &mut self.inner.termios
475 }
476 #[cfg(not(unix))] {
477 unreachable!("this code is only enabled on Unix platforms or during documentation generation")
478 }
479 }
480
481 #[cfg(any(feature = "doc", all(windows, feature = "windows")))]
486 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "windows")))]
487 pub fn as_raw_dbc(&self) -> &crate::os::windows::DCB {
488 #[cfg(windows)] {
489 &self.inner.dcb
490 }
491 #[cfg(not(windows))] {
492 unreachable!("this code is only enabled on Windows or during documentation generation")
493 }
494 }
495
496 #[cfg(any(feature = "doc", all(windows, feature = "windows")))]
501 #[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "windows")))]
502 pub fn as_raw_dbc_mut(&mut self) -> &mut crate::os::windows::DCB {
503 #[cfg(windows)] {
504 &mut self.inner.dcb
505 }
506 #[cfg(not(windows))] {
507 unreachable!("this code is only enabled on Windows or during documentation generation")
508 }
509 }
510}
511
512impl std::fmt::Debug for Settings {
513 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
514 f.debug_struct("Settings")
515 .field("baud_rate", &self.get_baud_rate())
516 .field("char_size", &self.get_char_size())
517 .field("stop_bits", &self.get_stop_bits())
518 .field("parity", &self.get_parity())
519 .field("flow_control", &self.get_flow_control())
520 .finish()
521 }
522}
523
524#[cfg(feature = "serde")]
525impl serde::Serialize for CharSize {
526 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
527 serializer.serialize_u8(self.as_u8())
528 }
529}
530
531#[cfg(feature = "serde")]
532impl<'de> serde::Deserialize<'de> for CharSize {
533 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
534 struct Visitor;
535 impl serde::de::Visitor<'_> for Visitor {
536 type Value = CharSize;
537
538 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
539 formatter.write_str(Self::Value::EXPECTED)
540 }
541
542 fn visit_u64<E: serde::de::Error>(self, data: u64) -> Result<Self::Value, E> {
543 Self::Value::try_from(data)
544 .map_err(|e| E::invalid_value(serde::de::Unexpected::Unsigned(e.unexpected), &e.expected))
545 }
546 }
547
548 deserializer.deserialize_u8(Visitor)
549 }
550}
551
552#[cfg(feature = "serde")]
553impl serde::Serialize for StopBits {
554 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
555 serializer.serialize_u8(self.as_u8())
556 }
557}
558
559#[cfg(feature = "serde")]
560impl<'de> serde::Deserialize<'de> for StopBits {
561 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
562 struct Visitor;
563 impl serde::de::Visitor<'_> for Visitor {
564 type Value = StopBits;
565
566 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
567 formatter.write_str(Self::Value::EXPECTED)
568 }
569
570 fn visit_u64<E: serde::de::Error>(self, data: u64) -> Result<Self::Value, E> {
571 Self::Value::try_from(data)
572 .map_err(|e| E::invalid_value(serde::de::Unexpected::Unsigned(e.unexpected), &e.expected))
573 }
574 }
575
576 deserializer.deserialize_u8(Visitor)
577 }
578}
579
580#[cfg(feature = "serde")]
581impl serde::Serialize for Parity {
582 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
583 serializer.serialize_str(self.as_str())
584 }
585}
586
587#[cfg(feature = "serde")]
588impl<'de> serde::Deserialize<'de> for Parity {
589 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
590 struct Visitor;
591 impl serde::de::Visitor<'_> for Visitor {
592 type Value = Parity;
593
594 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
595 formatter.write_str(Self::Value::EXPECTED)
596 }
597
598 fn visit_str<E: serde::de::Error>(self, data: &str) -> Result<Self::Value, E> {
599 Self::Value::try_from(data)
600 .map_err(|e| E::invalid_value(serde::de::Unexpected::Str(e.unexpected), &e.expected))
601 }
602 }
603
604 deserializer.deserialize_str(Visitor)
605 }
606}
607
608#[cfg(feature = "serde")]
609impl serde::Serialize for FlowControl {
610 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
611 serializer.serialize_str(self.as_str())
612 }
613}
614
615#[cfg(feature = "serde")]
616impl<'de> serde::Deserialize<'de> for FlowControl {
617 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
618 struct Visitor;
619 impl serde::de::Visitor<'_> for Visitor {
620 type Value = FlowControl;
621
622 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
623 formatter.write_str(Self::Value::EXPECTED)
624 }
625
626 fn visit_str<E: serde::de::Error>(self, data: &str) -> Result<Self::Value, E> {
627 Self::Value::try_from(data)
628 .map_err(|e| E::invalid_value(serde::de::Unexpected::Str(e.unexpected), &e.expected))
629 }
630 }
631
632 deserializer.deserialize_str(Visitor)
633 }
634}
635
636#[derive(Debug, Clone)]
638pub struct TryFromError<Raw> {
639 unexpected: Raw,
641
642 expected: &'static str,
644}
645
646impl<Raw> TryFromError<Raw> {
647 fn convert<U: From<Raw>>(self) -> TryFromError<U> {
648 TryFromError {
649 unexpected: self.unexpected.into(),
650 expected: self.expected,
651 }
652 }
653}
654
655impl<Raw: std::fmt::Debug> std::fmt::Display for TryFromError<Raw> {
656 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
657 write!(f, "invalid value: {:?}, expected {}", self.unexpected, self.expected)
658 }
659}
660
661impl<Raw: std::fmt::Debug> std::error::Error for TryFromError<Raw> {}