json_ld_core/
print.rs

1use json_syntax::print::{
2	pre_compute_array_size, pre_compute_object_size, print_array, print_object,
3	printed_string_size, string_literal, PrecomputeSize, PrecomputeSizeWithContext,
4	PrintWithContext, PrintWithSize, PrintWithSizeAndContext, Size,
5};
6pub use json_syntax::print::{Options, Print, Printed};
7
8use crate::{object, ExpandedDocument, Id, Indexed, Object};
9use contextual::WithContext;
10use rdf_types::vocabulary::{IriVocabulary, Vocabulary};
11
12pub trait PrintWithSizeAndVocabulary<V> {
13	fn fmt_with_size_and(
14		&self,
15		vocabulary: &V,
16		f: &mut std::fmt::Formatter,
17		options: &Options,
18		indent: usize,
19		sizes: &[Size],
20		index: &mut usize,
21	) -> std::fmt::Result;
22}
23
24impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
25	for ExpandedDocument<T, B>
26{
27	fn contextual_pre_compute_size(
28		&self,
29		vocabulary: &N,
30		options: &Options,
31		sizes: &mut Vec<Size>,
32	) -> Size {
33		pre_compute_array_size(
34			self.objects().iter().map(|o| o.with(vocabulary)),
35			options,
36			sizes,
37		)
38	}
39}
40
41impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithContext<N> for ExpandedDocument<T, B> {
42	fn contextual_fmt_with(
43		&self,
44		vocabulary: &N,
45		f: &mut std::fmt::Formatter,
46		options: &Options,
47		indent: usize,
48	) -> std::fmt::Result {
49		let mut sizes = Vec::with_capacity(self.count(|i| i.is_json_array() || i.is_json_object()));
50		self.contextual_pre_compute_size(vocabulary, options, &mut sizes);
51		let mut index = 0;
52		self.contextual_fmt_with_size(vocabulary, f, options, indent, &sizes, &mut index)
53	}
54}
55
56impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithContext<N> for object::Node<T, B> {
57	fn contextual_fmt_with(
58		&self,
59		vocabulary: &N,
60		f: &mut std::fmt::Formatter,
61		options: &Options,
62		indent: usize,
63	) -> std::fmt::Result {
64		let mut sizes = Vec::with_capacity(self.count(|i| i.is_json_array() || i.is_json_object()));
65		self.contextual_pre_compute_size(vocabulary, options, &mut sizes);
66		let mut index = 0;
67		self.contextual_fmt_with_size(vocabulary, f, options, indent, &sizes, &mut index)
68	}
69}
70
71impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
72	for ExpandedDocument<T, B>
73{
74	fn contextual_fmt_with_size(
75		&self,
76		vocabulary: &N,
77		f: &mut std::fmt::Formatter,
78		options: &Options,
79		indent: usize,
80		sizes: &[Size],
81		index: &mut usize,
82	) -> std::fmt::Result {
83		print_array(
84			self.objects().iter().map(|o| o.with(vocabulary)),
85			f,
86			options,
87			indent,
88			sizes,
89			index,
90		)
91	}
92}
93
94impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N> for Id<T, B> {
95	fn contextual_pre_compute_size(
96		&self,
97		vocabulary: &N,
98		_options: &Options,
99		_sizes: &mut Vec<Size>,
100	) -> Size {
101		Size::Width(printed_string_size(self.with(vocabulary).as_str()))
102	}
103}
104
105impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithContext<N> for Id<T, B> {
106	fn contextual_fmt_with(
107		&self,
108		vocabulary: &N,
109		f: &mut std::fmt::Formatter,
110		_options: &Options,
111		_indent: usize,
112	) -> std::fmt::Result {
113		string_literal(self.with(vocabulary).as_str(), f)
114	}
115}
116
117impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N> for Id<T, B> {
118	fn contextual_fmt_with_size(
119		&self,
120		vocabulary: &N,
121		f: &mut std::fmt::Formatter,
122		_options: &Options,
123		_indent: usize,
124		_sizes: &[Size],
125		_index: &mut usize,
126	) -> std::fmt::Result {
127		string_literal(self.with(vocabulary).as_str(), f)
128	}
129}
130
131impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
132	for Indexed<Object<T, B>>
133{
134	fn contextual_pre_compute_size(
135		&self,
136		vocabulary: &N,
137		options: &Options,
138		sizes: &mut Vec<Size>,
139	) -> Size {
140		pre_compute_object_size(
141			self.entries().map(|e| {
142				let (k, v) = e.into_key_value();
143				(k.into_with(vocabulary).into_str(), v.into_with(vocabulary))
144			}),
145			options,
146			sizes,
147		)
148	}
149}
150
151impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
152	for Indexed<Object<T, B>>
153{
154	fn contextual_fmt_with_size(
155		&self,
156		vocabulary: &N,
157		f: &mut std::fmt::Formatter,
158		options: &Options,
159		indent: usize,
160		sizes: &[Size],
161		index: &mut usize,
162	) -> std::fmt::Result {
163		print_object(
164			self.entries().map(|e| {
165				let (k, v) = e.into_key_value();
166				(k.into_with(vocabulary).into_str(), v.into_with(vocabulary))
167			}),
168			f,
169			options,
170			indent,
171			sizes,
172			index,
173		)
174	}
175}
176
177impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
178	for object::IndexedEntryValueRef<'a, T, B>
179{
180	fn contextual_pre_compute_size(
181		&self,
182		vocabulary: &N,
183		options: &Options,
184		sizes: &mut Vec<Size>,
185	) -> Size {
186		match self {
187			object::IndexedEntryValueRef::Index(s) => Size::Width(printed_string_size(s)),
188			object::IndexedEntryValueRef::Object(e) => {
189				e.into_with(vocabulary).pre_compute_size(options, sizes)
190			}
191		}
192	}
193}
194
195impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
196	for object::IndexedEntryValueRef<'a, T, B>
197{
198	fn contextual_fmt_with_size(
199		&self,
200		vocabulary: &N,
201		f: &mut std::fmt::Formatter,
202		options: &Options,
203		indent: usize,
204		sizes: &[Size],
205		index: &mut usize,
206	) -> std::fmt::Result {
207		match self {
208			object::IndexedEntryValueRef::Index(s) => string_literal(s, f),
209			object::IndexedEntryValueRef::Object(e) => e
210				.into_with(vocabulary)
211				.fmt_with_size(f, options, indent, sizes, index),
212		}
213	}
214}
215
216impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
217	for object::EntryValueRef<'a, T, B>
218{
219	fn contextual_pre_compute_size(
220		&self,
221		vocabulary: &N,
222		options: &Options,
223		sizes: &mut Vec<Size>,
224	) -> Size {
225		match self {
226			object::EntryValueRef::Value(v) => {
227				v.into_with(vocabulary).pre_compute_size(options, sizes)
228			}
229			object::EntryValueRef::List(l) => {
230				pre_compute_array_size(l.iter().map(|i| i.with(vocabulary)), options, sizes)
231			}
232			object::EntryValueRef::Node(n) => {
233				n.into_with(vocabulary).pre_compute_size(options, sizes)
234			}
235		}
236	}
237}
238
239impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
240	for object::EntryValueRef<'a, T, B>
241{
242	fn contextual_fmt_with_size(
243		&self,
244		vocabulary: &N,
245		f: &mut std::fmt::Formatter,
246		options: &Options,
247		indent: usize,
248		sizes: &[Size],
249		index: &mut usize,
250	) -> std::fmt::Result {
251		match self {
252			object::EntryValueRef::Value(v) => v
253				.into_with(vocabulary)
254				.fmt_with_size(f, options, indent, sizes, index),
255			object::EntryValueRef::List(l) => print_array(
256				l.iter().map(|i| i.with(vocabulary)),
257				f,
258				options,
259				indent,
260				sizes,
261				index,
262			),
263			object::EntryValueRef::Node(n) => n
264				.into_with(vocabulary)
265				.fmt_with_size(f, options, indent, sizes, index),
266		}
267	}
268}
269
270impl<'a, T, N: IriVocabulary<Iri = T>> PrecomputeSizeWithContext<N>
271	for object::value::EntryRef<'a, T>
272{
273	fn contextual_pre_compute_size(
274		&self,
275		vocabulary: &N,
276		options: &Options,
277		sizes: &mut Vec<Size>,
278	) -> Size {
279		match self {
280			object::value::EntryRef::Value(v) => v.pre_compute_size(options, sizes),
281			object::value::EntryRef::Type(t) => {
282				t.into_with(vocabulary).pre_compute_size(options, sizes)
283			}
284			object::value::EntryRef::Language(l) => l.pre_compute_size(options, sizes),
285			object::value::EntryRef::Direction(d) => d.pre_compute_size(options, sizes),
286		}
287	}
288}
289
290impl<'a, T, N: IriVocabulary<Iri = T>> PrintWithSizeAndContext<N>
291	for object::value::EntryRef<'a, T>
292{
293	fn contextual_fmt_with_size(
294		&self,
295		vocabulary: &N,
296		f: &mut std::fmt::Formatter,
297		options: &Options,
298		indent: usize,
299		sizes: &[Size],
300		index: &mut usize,
301	) -> std::fmt::Result {
302		match self {
303			object::value::EntryRef::Value(v) => v.fmt_with_size(f, options, indent, sizes, index),
304			object::value::EntryRef::Type(t) => {
305				t.into_with(vocabulary).fmt_with(f, options, indent)
306			}
307			object::value::EntryRef::Language(l) => l.fmt_with(f, options, indent),
308			object::value::EntryRef::Direction(d) => d.fmt_with(f, options, indent),
309		}
310	}
311}
312
313impl<'a, T, N: IriVocabulary<Iri = T>> PrecomputeSizeWithContext<N>
314	for object::value::TypeRef<'a, T>
315{
316	fn contextual_pre_compute_size(
317		&self,
318		vocabulary: &N,
319		_options: &Options,
320		_sizes: &mut Vec<Size>,
321	) -> Size {
322		match self {
323			object::value::TypeRef::Id(id) => {
324				Size::Width(printed_string_size(vocabulary.iri(id).unwrap().as_str()))
325			}
326			object::value::TypeRef::Json => Size::Width(printed_string_size("@json")),
327		}
328	}
329}
330
331impl<'a, T, N: IriVocabulary<Iri = T>> PrintWithContext<N> for object::value::TypeRef<'a, T> {
332	fn contextual_fmt_with(
333		&self,
334		vocabulary: &N,
335		f: &mut std::fmt::Formatter,
336		_options: &Options,
337		_indent: usize,
338	) -> std::fmt::Result {
339		match self {
340			object::value::TypeRef::Id(id) => {
341				string_literal(vocabulary.iri(id).unwrap().as_str(), f)
342			}
343			object::value::TypeRef::Json => string_literal("@json", f),
344		}
345	}
346}
347
348impl<'a> PrecomputeSize for object::value::ValueEntryRef<'a> {
349	fn pre_compute_size(&self, options: &Options, sizes: &mut Vec<Size>) -> Size {
350		match self {
351			Self::Literal(l) => l.pre_compute_size(options, sizes),
352			Self::LangString(s) => Size::Width(printed_string_size(s)),
353			Self::Json(j) => j.pre_compute_size(options, sizes),
354		}
355	}
356}
357
358impl<'a> PrintWithSize for object::value::ValueEntryRef<'a> {
359	fn fmt_with_size(
360		&self,
361		f: &mut std::fmt::Formatter,
362		options: &Options,
363		indent: usize,
364		sizes: &[Size],
365		index: &mut usize,
366	) -> std::fmt::Result {
367		match self {
368			Self::Literal(l) => l.fmt_with(f, options, indent),
369			Self::LangString(s) => string_literal(s, f),
370			Self::Json(j) => j.fmt_with_size(f, options, indent, sizes, index),
371		}
372	}
373}
374
375impl PrecomputeSize for object::value::Literal {
376	fn pre_compute_size(&self, options: &Options, sizes: &mut Vec<Size>) -> Size {
377		match self {
378			Self::Null => Size::Width(4),
379			Self::Boolean(b) => b.pre_compute_size(options, sizes),
380			Self::Number(n) => Size::Width(n.as_str().len()),
381			Self::String(s) => Size::Width(printed_string_size(s)),
382		}
383	}
384}
385
386impl Print for object::value::Literal {
387	fn fmt_with(
388		&self,
389		f: &mut std::fmt::Formatter,
390		options: &Options,
391		indent: usize,
392	) -> std::fmt::Result {
393		match self {
394			Self::Null => write!(f, "null"),
395			Self::Boolean(b) => b.fmt_with(f, options, indent),
396			Self::Number(n) => std::fmt::Display::fmt(n, f),
397			Self::String(s) => string_literal(s, f),
398		}
399	}
400}
401
402impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
403	for object::Node<T, B>
404{
405	fn contextual_pre_compute_size(
406		&self,
407		vocabulary: &N,
408		options: &Options,
409		sizes: &mut Vec<Size>,
410	) -> Size {
411		pre_compute_object_size(
412			self.entries().map(|e| {
413				let (k, v) = e.into_key_value();
414				(k.into_with(vocabulary).into_str(), v.into_with(vocabulary))
415			}),
416			options,
417			sizes,
418		)
419	}
420}
421
422impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N> for object::Node<T, B> {
423	fn contextual_fmt_with_size(
424		&self,
425		vocabulary: &N,
426		f: &mut std::fmt::Formatter,
427		options: &Options,
428		indent: usize,
429		sizes: &[Size],
430		index: &mut usize,
431	) -> std::fmt::Result {
432		print_object(
433			self.entries().map(|e| {
434				let (k, v) = e.into_key_value();
435				(k.into_with(vocabulary).into_str(), v.into_with(vocabulary))
436			}),
437			f,
438			options,
439			indent,
440			sizes,
441			index,
442		)
443	}
444}
445
446impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
447	for Indexed<object::Node<T, B>>
448{
449	fn contextual_pre_compute_size(
450		&self,
451		vocabulary: &N,
452		options: &Options,
453		sizes: &mut Vec<Size>,
454	) -> Size {
455		pre_compute_object_size(
456			self.entries().map(|e| {
457				let (k, v) = e.into_key_value();
458				(k.into_with(vocabulary).into_str(), v.into_with(vocabulary))
459			}),
460			options,
461			sizes,
462		)
463	}
464}
465
466impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
467	for Indexed<object::Node<T, B>>
468{
469	fn contextual_fmt_with_size(
470		&self,
471		vocabulary: &N,
472		f: &mut std::fmt::Formatter,
473		options: &Options,
474		indent: usize,
475		sizes: &[Size],
476		index: &mut usize,
477	) -> std::fmt::Result {
478		print_object(
479			self.entries().map(|e| {
480				let (k, v) = e.into_key_value();
481				(k.into_with(vocabulary).into_str(), v.into_with(vocabulary))
482			}),
483			f,
484			options,
485			indent,
486			sizes,
487			index,
488		)
489	}
490}
491
492impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
493	for object::node::IndexedEntryValueRef<'a, T, B>
494{
495	fn contextual_pre_compute_size(
496		&self,
497		vocabulary: &N,
498		options: &Options,
499		sizes: &mut Vec<Size>,
500	) -> Size {
501		match self {
502			object::node::IndexedEntryValueRef::Index(s) => Size::Width(printed_string_size(s)),
503			object::node::IndexedEntryValueRef::Node(e) => {
504				e.into_with(vocabulary).pre_compute_size(options, sizes)
505			}
506		}
507	}
508}
509
510impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
511	for object::node::IndexedEntryValueRef<'a, T, B>
512{
513	fn contextual_fmt_with_size(
514		&self,
515		vocabulary: &N,
516		f: &mut std::fmt::Formatter,
517		options: &Options,
518		indent: usize,
519		sizes: &[Size],
520		index: &mut usize,
521	) -> std::fmt::Result {
522		match self {
523			object::node::IndexedEntryValueRef::Index(s) => string_literal(s, f),
524			object::node::IndexedEntryValueRef::Node(e) => e
525				.into_with(vocabulary)
526				.fmt_with_size(f, options, indent, sizes, index),
527		}
528	}
529}
530
531impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
532	for object::node::EntryValueRef<'a, T, B>
533{
534	fn contextual_pre_compute_size(
535		&self,
536		vocabulary: &N,
537		options: &Options,
538		sizes: &mut Vec<Size>,
539	) -> Size {
540		match *self {
541			object::node::EntryValueRef::Id(v) => {
542				v.contextual_pre_compute_size(vocabulary, options, sizes)
543			}
544			object::node::EntryValueRef::Type(v) => {
545				pre_compute_array_size(v.iter().map(|i| i.with(vocabulary)), options, sizes)
546			}
547			object::node::EntryValueRef::Graph(v) => {
548				pre_compute_array_size(v.iter().map(|i| i.with(vocabulary)), options, sizes)
549				// v.contextual_pre_compute_size(vocabulary, options, sizes)
550			}
551			object::node::EntryValueRef::Included(v) => {
552				pre_compute_array_size(v.iter().map(|i| i.with(vocabulary)), options, sizes)
553				// v.contextual_pre_compute_size(vocabulary, options, sizes)
554			}
555			object::node::EntryValueRef::Reverse(v) => {
556				v.contextual_pre_compute_size(vocabulary, options, sizes)
557			}
558			object::node::EntryValueRef::Property(v) => {
559				pre_compute_array_size(v.iter().map(|i| i.with(vocabulary)), options, sizes)
560			}
561		}
562	}
563}
564
565impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
566	for object::node::EntryValueRef<'a, T, B>
567{
568	fn contextual_fmt_with_size(
569		&self,
570		vocabulary: &N,
571		f: &mut std::fmt::Formatter,
572		options: &Options,
573		indent: usize,
574		sizes: &[Size],
575		index: &mut usize,
576	) -> std::fmt::Result {
577		match self {
578			object::node::EntryValueRef::Id(v) => v.with(vocabulary).fmt_with(f, options, indent),
579			object::node::EntryValueRef::Type(v) => print_array(
580				v.iter().map(|i| i.with(vocabulary)),
581				f,
582				options,
583				indent,
584				sizes,
585				index,
586			),
587			object::node::EntryValueRef::Graph(v) => {
588				// v.contextual_fmt_with_size(vocabulary, f, options, indent, sizes, index)
589				print_array(
590					v.iter().map(|i| i.with(vocabulary)),
591					f,
592					options,
593					indent,
594					sizes,
595					index,
596				)
597			}
598			object::node::EntryValueRef::Included(v) => {
599				// v.contextual_fmt_with_size(vocabulary, f, options, indent, sizes, index)
600				print_array(
601					v.iter().map(|i| i.with(vocabulary)),
602					f,
603					options,
604					indent,
605					sizes,
606					index,
607				)
608			}
609			object::node::EntryValueRef::Reverse(v) => {
610				v.contextual_fmt_with_size(vocabulary, f, options, indent, sizes, index)
611			}
612			object::node::EntryValueRef::Property(v) => print_array(
613				v.iter().map(|i| i.with(vocabulary)),
614				f,
615				options,
616				indent,
617				sizes,
618				index,
619			),
620		}
621	}
622}
623
624impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrecomputeSizeWithContext<N>
625	for object::node::ReverseProperties<T, B>
626{
627	fn contextual_pre_compute_size(
628		&self,
629		vocabulary: &N,
630		options: &Options,
631		sizes: &mut Vec<Size>,
632	) -> Size {
633		pre_compute_object_size(
634			self.iter()
635				.map(|(k, v)| (k.into_with(vocabulary).as_str(), v.into_with(vocabulary))),
636			options,
637			sizes,
638		)
639	}
640}
641
642impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> PrintWithSizeAndContext<N>
643	for object::node::ReverseProperties<T, B>
644{
645	fn contextual_fmt_with_size(
646		&self,
647		vocabulary: &N,
648		f: &mut std::fmt::Formatter,
649		options: &Options,
650		indent: usize,
651		sizes: &[Size],
652		index: &mut usize,
653	) -> std::fmt::Result {
654		print_object(
655			self.iter()
656				.map(|(k, v)| (k.into_with(vocabulary).as_str(), v.into_with(vocabulary))),
657			f,
658			options,
659			indent,
660			sizes,
661			index,
662		)
663	}
664}