xsd_types/lexical/
base64_binary.rs

1use crate::lexical::lexical_form;
2
3use std::borrow::{Borrow, ToOwned};
4use std::cmp::Ordering;
5use std::fmt;
6use std::hash::{Hash, Hasher};
7
8lexical_form! {
9	/// Base 64 string.
10	///
11	/// See: <https://www.w3.org/TR/xmlschema-2/#base64Binary>
12	ty: Base64Binary,
13
14	/// Owned base 64 string.
15	///
16	/// See: <https://www.w3.org/TR/xmlschema-2/#base64Binary>
17	buffer: Base64BinaryBuf,
18
19	/// Creates a new base 64 string from a string.
20	///
21	/// If the input string is ot a [valid XSD base 64 string](https://www.w3.org/TR/xmlschema-2/#base64Binary),
22	/// an [`InvalidBase64Binary`] error is returned.
23	new,
24
25	/// Creates a new base 64 string from a string without checking it.
26	///
27	/// # Safety
28	///
29	/// The input string must be a [valid XSD base 64 string](https://www.w3.org/TR/xmlschema-2/#base64Binary).
30	new_unchecked,
31
32	value: crate::Base64BinaryBuf,
33	error: InvalidBase64Binary,
34	as_ref: as_base_64_binary,
35	parent_forms: {}
36}
37
38impl Base64Binary {
39	#[inline(always)]
40	fn as_canonical_str(&self) -> &str {
41		self.as_str()
42	}
43
44	#[inline(always)]
45	pub fn value(&self) -> crate::Base64BinaryBuf {
46		crate::Base64BinaryBuf::decode(self.as_bytes()).unwrap()
47	}
48}
49
50impl PartialEq for Base64Binary {
51	fn eq(&self, other: &Self) -> bool {
52		self.as_canonical_str() == other.as_canonical_str()
53	}
54}
55
56impl Eq for Base64Binary {}
57
58impl Hash for Base64Binary {
59	fn hash<H: Hasher>(&self, h: &mut H) {
60		self.as_canonical_str().hash(h)
61	}
62}
63
64impl Ord for Base64Binary {
65	fn cmp(&self, other: &Self) -> Ordering {
66		self.as_canonical_str().cmp(other.as_canonical_str())
67	}
68}
69
70impl PartialOrd for Base64Binary {
71	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
72		Some(self.cmp(other))
73	}
74}
75
76impl Default for Base64BinaryBuf {
77	fn default() -> Self {
78		unsafe { Self::new_unchecked(Vec::new()) }
79	}
80}
81
82impl PartialOrd for Base64BinaryBuf {
83	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
84		Some(self.cmp(other))
85	}
86}
87
88impl Ord for Base64BinaryBuf {
89	fn cmp(&self, other: &Self) -> Ordering {
90		self.as_base_64_binary().cmp(other.as_base_64_binary())
91	}
92}
93
94fn check_bytes(s: &[u8]) -> bool {
95	check(s.iter().copied())
96}
97
98fn check<C: Iterator<Item = u8>>(mut chars: C) -> bool {
99	enum State {
100		Data,
101		Padding,
102	}
103
104	let mut state = State::Data;
105
106	loop {
107		state = match state {
108			State::Data => match chars.next() {
109				Some(b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'+' | b'/') => State::Data,
110				Some(b'=') => State::Padding,
111				None => break true,
112				_ => break false,
113			},
114			State::Padding => match chars.next() {
115				Some(b'=') => State::Padding,
116				None => break true,
117				_ => break false,
118			},
119		}
120	}
121}