1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::{hash::Hash, str::FromStr};

#[derive(Debug, thiserror::Error)]
#[error("unknown JSON-LD version `{0}`")]
pub struct UnknownVersion(pub String);

/// Version number.
///
/// The only allowed value is a number with the value `1.1`.
#[derive(Clone, Copy, PartialOrd, Ord, Debug)]
pub enum Version {
	V1_1,
}

impl Version {
	pub fn into_bytes(self) -> &'static [u8] {
		match self {
			Self::V1_1 => b"1.1",
		}
	}

	pub fn into_str(self) -> &'static str {
		match self {
			Self::V1_1 => "1.1",
		}
	}

	pub fn into_json_number(self) -> &'static json_syntax::Number {
		unsafe { json_syntax::Number::new_unchecked(self.into_bytes()) }
	}

	pub fn into_json_number_buf(self) -> json_syntax::NumberBuf {
		unsafe { json_syntax::NumberBuf::new_unchecked(self.into_bytes().into()) }
	}
}

impl PartialEq for Version {
	fn eq(&self, _other: &Self) -> bool {
		true
	}
}

impl Eq for Version {}

impl Hash for Version {
	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
		self.into_str().hash(state)
	}
}

impl<'a> From<Version> for &'a json_syntax::Number {
	fn from(v: Version) -> Self {
		v.into_json_number()
	}
}

impl From<Version> for json_syntax::NumberBuf {
	fn from(v: Version) -> Self {
		v.into_json_number_buf()
	}
}

impl TryFrom<json_syntax::NumberBuf> for Version {
	type Error = UnknownVersion;

	fn try_from(value: json_syntax::NumberBuf) -> Result<Self, Self::Error> {
		if value.trimmed().as_str() == "1.1" {
			Ok(Self::V1_1)
		} else {
			Err(UnknownVersion(value.to_string()))
		}
	}
}

impl FromStr for Version {
	type Err = UnknownVersion;

	fn from_str(s: &str) -> Result<Self, Self::Err> {
		if s == "1.1" {
			Ok(Version::V1_1)
		} else {
			Err(UnknownVersion(s.to_owned()))
		}
	}
}

impl TryFrom<f32> for Version {
	type Error = UnknownVersion;

	fn try_from(value: f32) -> Result<Self, Self::Error> {
		if value == 1.1 {
			Ok(Version::V1_1)
		} else {
			Err(UnknownVersion(value.to_string()))
		}
	}
}

impl TryFrom<f64> for Version {
	type Error = UnknownVersion;

	fn try_from(value: f64) -> Result<Self, Self::Error> {
		if value == 1.1 {
			Ok(Version::V1_1)
		} else {
			Err(UnknownVersion(value.to_string()))
		}
	}
}

#[cfg(feature = "serde")]
impl serde::Serialize for Version {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: serde::Serializer,
	{
		self.into_json_number().serialize(serializer)
	}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Version {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
	where
		D: serde::Deserializer<'de>,
	{
		json_syntax::NumberBuf::deserialize(deserializer)?
			.try_into()
			.map_err(serde::de::Error::custom)
	}
}