json_api/value/fields/
key.rs1use std::borrow::Borrow;
2use std::fmt::{self, Display, Formatter};
3use std::ops::Deref;
4use std::str::FromStr;
5
6use serde::de::{self, Deserialize, Deserializer, Visitor};
7use serde::ser::{Serialize, Serializer};
8
9use error::Error;
10use sealed::Sealed;
11use value::Stringify;
12
13#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
40pub struct Key(String);
41
42impl Key {
43 #[doc(hidden)]
44 #[inline]
45 pub fn from_raw(value: String) -> Self {
46 Key(value)
47 }
48}
49
50impl AsRef<[u8]> for Key {
51 fn as_ref(&self) -> &[u8] {
52 self.as_bytes()
53 }
54}
55
56impl AsRef<str> for Key {
57 fn as_ref(&self) -> &str {
58 self
59 }
60}
61
62impl Borrow<str> for Key {
63 fn borrow(&self) -> &str {
64 self
65 }
66}
67
68impl Deref for Key {
69 type Target = str;
70
71 fn deref(&self) -> &Self::Target {
72 self.0.as_str()
73 }
74}
75
76impl Display for Key {
77 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
78 f.write_str(self)
79 }
80}
81
82impl From<Key> for String {
83 fn from(key: Key) -> Self {
84 let Key(value) = key;
85 value
86 }
87}
88
89impl FromStr for Key {
90 type Err = Error;
91
92 fn from_str(source: &str) -> Result<Key, Self::Err> {
93 if source.is_empty() {
94 bail!("cannot be blank");
95 }
96
97 let mut dest = String::with_capacity(source.len() + 10);
101 let mut chars = source.chars().peekable();
102
103 while let Some(value) = chars.next() {
104 match value {
105 '\u{002e}' |
106 '\u{002f}' |
107 '\u{0040}' |
108 '\u{0060}' |
109 '\u{0000}'...'\u{001f}' |
110 '\u{0021}'...'\u{0029}' |
111 '\u{002a}'...'\u{002c}' |
112 '\u{003a}'...'\u{003f}' |
113 '\u{005b}'...'\u{005e}' |
114 '\u{007b}'...'\u{007f}' => {
115 bail!("reserved '{}'", value);
116 }
117 '_' | '-' | ' ' if dest.is_empty() => {
118 bail!("cannot start with '{}'", value);
119 }
120 '_' | '-' | ' ' => match chars.peek() {
121 Some(&'-') | Some(&'_') | Some(&' ') | Some(&'A'...'Z') => {
122 continue;
123 }
124 Some(_) => {
125 dest.push('-');
126 }
127 None => {
128 bail!("cannot end with '{}'", value);
129 }
130 },
131 'A'...'Z' if dest.ends_with('-') => {
132 dest.push(as_lowercase(value));
133 }
134 'A'...'Z' => {
135 dest.push('-');
136 dest.push(as_lowercase(value));
137 }
138 _ => {
139 dest.push(value);
140 }
141 }
142 }
143
144 Ok(Key(dest))
145 }
146}
147
148impl PartialEq<String> for Key {
149 fn eq(&self, rhs: &String) -> bool {
150 &self.0 == rhs
151 }
152}
153
154impl PartialEq<str> for Key {
155 fn eq(&self, rhs: &str) -> bool {
156 &**self == rhs
157 }
158}
159
160impl<'a> PartialEq<&'a str> for Key {
161 fn eq(&self, rhs: &&str) -> bool {
162 &**self == *rhs
163 }
164}
165
166impl<'de> Deserialize<'de> for Key {
167 fn deserialize<D>(deserializer: D) -> Result<Key, D::Error>
168 where
169 D: Deserializer<'de>,
170 {
171 struct KeyVisitor;
172
173 impl<'de> Visitor<'de> for KeyVisitor {
174 type Value = Key;
175
176 fn expecting(&self, f: &mut Formatter) -> fmt::Result {
177 f.write_str("a valid json api member name")
178 }
179
180 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
181 where
182 E: de::Error,
183 {
184 value.parse().map_err(de::Error::custom)
185 }
186 }
187
188 deserializer.deserialize_str(KeyVisitor)
189 }
190}
191
192impl Serialize for Key {
193 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
194 where
195 S: Serializer,
196 {
197 serializer.serialize_str(self)
198 }
199}
200
201impl Sealed for Key {}
202
203impl Stringify for Key {
204 fn to_bytes(&self) -> Vec<u8> {
205 self.as_bytes().to_vec()
206 }
207}
208
209#[inline]
210fn as_lowercase(value: char) -> char {
211 (value as u8 + 32) as char
212}