dbus_message_parser/value/
member.rs1use crate::value::MAXIMUM_NAME_LENGTH;
2use std::cmp::{Eq, PartialEq};
3use std::convert::{From, TryFrom};
4use std::fmt::{Display, Formatter, Result as FmtResult};
5use thiserror::Error;
6
7enum Input {
8 AlphabeticAndUnderscore,
10 Digit,
12}
13
14impl TryFrom<u8> for Input {
15 type Error = MemberError;
16
17 fn try_from(c: u8) -> Result<Self, Self::Error> {
18 if c.is_ascii_alphabetic() || c == b'_' {
19 Ok(Input::AlphabeticAndUnderscore)
20 } else if c.is_ascii_digit() {
21 Ok(Input::Digit)
22 } else {
23 Err(MemberError::InvalidChar(c))
24 }
25 }
26}
27
28fn check(member: &[u8]) -> Result<(), MemberError> {
32 let member_len = member.len();
33 if MAXIMUM_NAME_LENGTH < member_len {
34 return Err(MemberError::ExceedMaximum(member_len));
35 }
36
37 let mut member_iter = member.iter();
38 match member_iter.next() {
39 Some(c) => {
40 if let Input::Digit = Input::try_from(*c)? {
41 return Err(MemberError::BeginDigit);
42 }
43 }
44 None => return Err(MemberError::Empty),
45 }
46
47 for c in member_iter {
48 Input::try_from(*c)?;
49 }
50 Ok(())
51}
52
53#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
57pub struct Member(String);
58
59#[derive(Debug, PartialEq, Eq, Error)]
61pub enum MemberError {
62 #[error("Member must not be empty")]
63 Empty,
64 #[error("Member must not begin with a digit")]
65 BeginDigit,
66 #[error("Member must not exceed the maximum length: {MAXIMUM_NAME_LENGTH} < {0}")]
67 ExceedMaximum(usize),
68 #[error("Member contians an invalid char: {0}")]
69 InvalidChar(u8),
70}
71
72impl From<Member> for String {
73 fn from(member: Member) -> Self {
74 member.0
75 }
76}
77
78impl TryFrom<String> for Member {
79 type Error = MemberError;
80
81 fn try_from(member: String) -> Result<Self, Self::Error> {
82 check(member.as_bytes())?;
83 Ok(Member(member))
84 }
85}
86
87impl TryFrom<&str> for Member {
88 type Error = MemberError;
89
90 fn try_from(member: &str) -> Result<Self, Self::Error> {
91 check(member.as_bytes())?;
92 Ok(Member(member.to_owned()))
93 }
94}
95
96impl TryFrom<&[u8]> for Member {
97 type Error = MemberError;
98
99 fn try_from(member: &[u8]) -> Result<Self, Self::Error> {
100 check(member)?;
101 let member = member.to_vec();
102 unsafe { Ok(Member(String::from_utf8_unchecked(member))) }
105 }
106}
107
108impl Display for Member {
109 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
110 write!(f, "{}", self.0)
111 }
112}
113
114impl AsRef<str> for Member {
115 fn as_ref(&self) -> &str {
116 &self.0
117 }
118}
119
120impl PartialEq<str> for Member {
121 fn eq(&self, other: &str) -> bool {
122 self.0 == other
123 }
124}