json-ld-syntax 0.12.1

A JSON-LD context processing implementation
Documentation
use crate::{
	context::InvalidContext, Container, ContainerKind, Direction, LenientLanguageTagBuf, Nullable,
};
use iref::IriRefBuf;
use locspan::Meta;

pub trait TryFromJson<M>: Sized {
	type Error;

	fn try_from_json(
		value: Meta<json_syntax::Value<M>, M>,
	) -> Result<Meta<Self, M>, Meta<Self::Error, M>>;
}

pub trait TryFromStrippedJson<M>: Sized {
	fn try_from_stripped_json(value: json_syntax::Value<M>) -> Result<Self, InvalidContext>;
}

impl<M> crate::TryFromJson<M> for bool {
	type Error = crate::Unexpected;

	fn try_from_json(
		Meta(value, meta): Meta<json_syntax::Value<M>, M>,
	) -> Result<Meta<Self, M>, Meta<Self::Error, M>> {
		match value {
			json_syntax::Value::Boolean(b) => Ok(Meta(b, meta)),
			unexpected => Err(Meta(
				crate::Unexpected(unexpected.kind(), &[json_syntax::Kind::Boolean]),
				meta,
			)),
		}
	}
}

impl<M> TryFromStrippedJson<M> for IriRefBuf {
	fn try_from_stripped_json(value: json_syntax::Value<M>) -> Result<Self, InvalidContext> {
		match value {
			json_syntax::Value::String(s) => match IriRefBuf::from_string(s.into_string()) {
				Ok(iri_ref) => Ok(iri_ref),
				Err((e, _)) => Err(InvalidContext::InvalidIriRef(e)),
			},
			unexpected => Err(InvalidContext::Unexpected(
				unexpected.kind(),
				&[json_syntax::Kind::String],
			)),
		}
	}
}

impl<M> TryFromJson<M> for IriRefBuf {
	type Error = InvalidContext;

	fn try_from_json(
		Meta(value, meta): Meta<json_syntax::Value<M>, M>,
	) -> Result<Meta<Self, M>, Meta<InvalidContext, M>> {
		match value {
			json_syntax::Value::String(s) => match IriRefBuf::from_string(s.into_string()) {
				Ok(iri_ref) => Ok(Meta(iri_ref, meta)),
				Err((e, _)) => Err(Meta(InvalidContext::InvalidIriRef(e), meta)),
			},
			unexpected => Err(Meta(
				InvalidContext::Unexpected(unexpected.kind(), &[json_syntax::Kind::String]),
				meta,
			)),
		}
	}
}

impl<M> TryFromStrippedJson<M> for LenientLanguageTagBuf {
	fn try_from_stripped_json(value: json_syntax::Value<M>) -> Result<Self, InvalidContext> {
		match value {
			json_syntax::Value::String(s) => {
				let (lang, _) = LenientLanguageTagBuf::new(s.into_string());
				Ok(lang)
			}
			unexpected => Err(InvalidContext::Unexpected(
				unexpected.kind(),
				&[json_syntax::Kind::String],
			)),
		}
	}
}

impl<M> TryFromStrippedJson<M> for Direction {
	fn try_from_stripped_json(value: json_syntax::Value<M>) -> Result<Self, InvalidContext> {
		match value {
			json_syntax::Value::String(s) => match Direction::try_from(s.as_str()) {
				Ok(d) => Ok(d),
				Err(_) => Err(InvalidContext::InvalidDirection),
			},
			unexpected => Err(InvalidContext::Unexpected(
				unexpected.kind(),
				&[json_syntax::Kind::String],
			)),
		}
	}
}

impl<M, T: TryFromStrippedJson<M>> TryFromJson<M> for Nullable<T> {
	type Error = InvalidContext;

	fn try_from_json(
		Meta(value, meta): Meta<json_syntax::Value<M>, M>,
	) -> Result<Meta<Self, M>, Meta<InvalidContext, M>> {
		match value {
			json_syntax::Value::Null => Ok(Meta(Self::Null, meta)),
			some => match T::try_from_stripped_json(some) {
				Ok(some) => Ok(Meta(Self::Some(some), meta)),
				Err(e) => Err(Meta(e, meta)),
			},
		}
	}
}

impl<M> TryFromJson<M> for Container<M> {
	type Error = InvalidContext;

	fn try_from_json(
		value: Meta<json_syntax::Value<M>, M>,
	) -> Result<Meta<Self, M>, Meta<InvalidContext, M>> {
		match value {
			Meta(json_syntax::Value::Array(a), meta) => {
				let mut container = Vec::new();

				for item in a {
					container.push(ContainerKind::try_from_json(item)?)
				}

				Ok(Meta(Self::Many(container), meta))
			}
			other => ContainerKind::try_from_json(other).map(Meta::cast),
		}
	}
}

impl<M> TryFromJson<M> for ContainerKind {
	type Error = InvalidContext;

	fn try_from_json(
		Meta(value, meta): Meta<json_syntax::Value<M>, M>,
	) -> Result<Meta<Self, M>, Meta<InvalidContext, M>> {
		match value {
			json_syntax::Value::String(s) => match ContainerKind::try_from(s.as_str()) {
				Ok(t) => Ok(Meta(t, meta)),
				Err(_) => Err(Meta(InvalidContext::InvalidTermDefinition, meta)),
			},
			unexpected => Err(Meta(
				InvalidContext::Unexpected(unexpected.kind(), &[json_syntax::Kind::String]),
				meta,
			)),
		}
	}
}