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
use json::JsonValue;
use langtag::{LanguageTag, LanguageTagBuf};
use std::collections::HashSet;

pub trait AsJson {
	fn as_json(&self) -> JsonValue;
}

impl AsJson for JsonValue {
	fn as_json(&self) -> JsonValue {
		self.clone()
	}
}

impl AsJson for bool {
	fn as_json(&self) -> JsonValue {
		JsonValue::Boolean(*self)
	}
}

impl AsJson for str {
	fn as_json(&self) -> JsonValue {
		self.into()
	}
}

impl AsJson for String {
	fn as_json(&self) -> JsonValue {
		self.as_str().as_json()
	}
}

impl<'a, T: AsRef<[u8]> + ?Sized> AsJson for LanguageTag<'a, T> {
	fn as_json(&self) -> JsonValue {
		self.as_str().as_json()
	}
}

impl<T: AsRef<[u8]>> AsJson for LanguageTagBuf<T> {
	fn as_json(&self) -> JsonValue {
		self.as_str().as_json()
	}
}

impl<T: AsJson> AsJson for [T] {
	fn as_json(&self) -> JsonValue {
		let mut ary = Vec::with_capacity(self.len());
		for item in self {
			ary.push(item.as_json())
		}

		JsonValue::Array(ary)
	}
}

impl<T: AsJson> AsJson for Vec<T> {
	fn as_json(&self) -> JsonValue {
		self.as_slice().as_json()
	}
}

impl<T: AsJson> AsJson for HashSet<T> {
	fn as_json(&self) -> JsonValue {
		let mut ary = Vec::with_capacity(self.len());
		for item in self {
			ary.push(item.as_json())
		}

		JsonValue::Array(ary)
	}
}

pub fn json_ld_eq(a: &JsonValue, b: &JsonValue) -> bool {
	match (a, b) {
		(JsonValue::Array(a), JsonValue::Array(b)) if a.len() == b.len() => {
			let mut selected = Vec::with_capacity(a.len());
			selected.resize(a.len(), false);

			'a_items: for item in a {
				for i in 0..b.len() {
					if !selected[i] && json_ld_eq(&b[i], item) {
						selected[i] = true;
						continue 'a_items;
					}
				}

				return false;
			}
		}
		(JsonValue::Object(a), JsonValue::Object(b)) if a.len() == b.len() => {
			for (key, value_a) in a.iter() {
				if let Some(value_b) = b.get(key) {
					if key == "@list" {
						match (value_a, value_b) {
							(JsonValue::Array(item_a), JsonValue::Array(item_b))
								if item_a.len() == item_b.len() =>
							{
								for i in 0..item_a.len() {
									if !json_ld_eq(&item_a[i], &item_b[i]) {
										return false;
									}
								}
							}
							_ => {
								if !json_ld_eq(value_a, value_b) {
									return false;
								}
							}
						}
					} else if !json_ld_eq(value_a, value_b) {
						return false;
					}
				} else {
					return false;
				}
			}
		}
		_ => return a == b,
	}

	true
}