1use std::collections::HashMap;
35use std::fmt;
36use std::hash::{BuildHasherDefault, Hasher};
37
38use bumpalo::Bump;
39
40use crate::borrowed::{MapRef, ValueRef};
41use crate::value::{Map, Ref, Res, Value};
42
43pub const MAGIC: &[u8; 4] = b"YOGD";
44pub const VERSION: u8 = 1;
45
46pub const MAX_DEPTH: usize = 256;
48
49mod tag {
50 pub const NULL: u8 = 0;
51 pub const FALSE: u8 = 1;
52 pub const TRUE: u8 = 2;
53 pub const INT: u8 = 3;
54 pub const FLOAT: u8 = 4;
55 pub const STR: u8 = 5;
56 pub const LIST: u8 = 6;
57 pub const MAP: u8 = 7;
58 pub const REF: u8 = 8;
59 pub const TAG: u8 = 9;
60 pub const RES: u8 = 10;
61 pub const TEXT: u8 = 11;
62 pub const IMAGE: u8 = 12;
63 pub const COLOR: u8 = 13;
64 pub const LANG: u8 = 14;
65 pub const BYTES: u8 = 15;
66}
67
68pub fn encode(value: &Value) -> Vec<u8> {
70 let mut w = Writer::new();
71 w.value(value);
72 w.finish()
73}
74
75pub struct Writer<'v>(Encoder<'v>);
87
88impl Default for Writer<'_> {
89 fn default() -> Self {
90 Self::new()
91 }
92}
93
94impl<'v> Writer<'v> {
95 pub fn new() -> Self {
96 Writer(Encoder { body: Vec::new(), strings: HashMap::default(), table: Vec::new() })
97 }
98
99 pub fn null(&mut self) -> &mut Self {
100 self.0.body.push(tag::NULL);
101 self
102 }
103
104 pub fn bool(&mut self, b: bool) -> &mut Self {
105 self.0.body.push(if b { tag::TRUE } else { tag::FALSE });
106 self
107 }
108
109 pub fn int(&mut self, n: i64) -> &mut Self {
110 self.0.body.push(tag::INT);
111 varint(&mut self.0.body, ((n << 1) ^ (n >> 63)) as u64);
112 self
113 }
114
115 pub fn float(&mut self, f: f64) -> &mut Self {
116 self.0.body.push(tag::FLOAT);
117 self.0.body.extend_from_slice(&f.to_le_bytes());
118 self
119 }
120
121 pub fn str(&mut self, s: &'v str) -> &mut Self {
122 self.0.body.push(tag::STR);
123 self.0.string(s);
124 self
125 }
126
127 pub fn list(&mut self, len: usize) -> &mut Self {
129 self.0.body.push(tag::LIST);
130 varint(&mut self.0.body, len as u64);
131 self
132 }
133
134 pub fn map(&mut self, len: usize) -> &mut Self {
136 self.0.body.push(tag::MAP);
137 varint(&mut self.0.body, len as u64);
138 self
139 }
140
141 pub fn key(&mut self, k: &'v str) -> &mut Self {
142 self.0.string(k);
143 self
144 }
145
146 pub fn value(&mut self, v: &'v Value) -> &mut Self {
147 self.0.value(v);
148 self
149 }
150
151 pub fn finish(self) -> Vec<u8> {
153 let enc = self.0;
154 let table_len: usize = enc.table.iter().map(|s| s.len() + 2).sum();
155 let mut out = Vec::with_capacity(5 + table_len + enc.body.len() + 4);
156 out.extend_from_slice(MAGIC);
157 out.push(VERSION);
158 varint(&mut out, enc.table.len() as u64);
159 for s in &enc.table {
160 varint(&mut out, s.len() as u64);
161 out.extend_from_slice(s.as_bytes());
162 }
163 out.extend_from_slice(&enc.body);
164 out
165 }
166}
167
168struct Encoder<'v> {
169 body: Vec<u8>,
170 strings: HashMap<&'v str, u32, BuildHasherDefault<Fx>>,
171 table: Vec<&'v str>,
172}
173
174impl<'v> Encoder<'v> {
175 fn string(&mut self, s: &'v str) {
176 let next = self.table.len() as u32;
177 let i = *self.strings.entry(s).or_insert_with(|| {
178 self.table.push(s);
179 next
180 });
181 varint(&mut self.body, i as u64);
182 }
183
184 fn value(&mut self, v: &'v Value) {
185 match v {
186 Value::Null => self.body.push(tag::NULL),
187 Value::Bool(false) => self.body.push(tag::FALSE),
188 Value::Bool(true) => self.body.push(tag::TRUE),
189 Value::Int(n) => {
190 self.body.push(tag::INT);
191 varint(&mut self.body, ((n << 1) ^ (n >> 63)) as u64);
192 }
193 Value::Float(f) => {
194 self.body.push(tag::FLOAT);
195 self.body.extend_from_slice(&f.to_le_bytes());
196 }
197 Value::Str(s) => {
198 self.body.push(tag::STR);
199 self.string(s);
200 }
201 Value::List(items) => {
202 self.body.push(tag::LIST);
203 varint(&mut self.body, items.len() as u64);
204 for item in items {
205 self.value(item);
206 }
207 }
208 Value::Map(map) => {
209 self.body.push(tag::MAP);
210 varint(&mut self.body, map.len() as u64);
211 for (k, v) in map.iter() {
212 self.string(k);
213 self.value(v);
214 }
215 }
216 Value::Ref(r) | Value::Tag(r) => {
217 self.body.push(if matches!(v, Value::Ref(_)) {
218 tag::REF
219 } else {
220 tag::TAG
221 });
222 self.string(&r.kind);
223 self.string(&r.id);
224 }
225 Value::Res(r) => {
226 self.body.push(tag::RES);
227 self.string(&r.set);
228 self.string(&r.key);
229 }
230 Value::Text(s) => {
231 self.body.push(tag::TEXT);
232 self.string(s);
233 }
234 Value::Image(s) => {
235 self.body.push(tag::IMAGE);
236 self.string(s);
237 }
238 Value::Lang(s) => {
239 self.body.push(tag::LANG);
240 self.string(s);
241 }
242 Value::Color(c) => {
243 self.body.push(tag::COLOR);
244 self.body.extend_from_slice(&c.to_le_bytes());
245 }
246 Value::Bytes(b) => {
247 self.body.push(tag::BYTES);
248 varint(&mut self.body, b.len() as u64);
249 self.body.extend_from_slice(b);
250 }
251 }
252 }
253}
254
255#[derive(Default)]
257struct Fx(u64);
258
259impl Fx {
260 fn add(&mut self, word: u64) {
261 self.0 = (self.0.rotate_left(5) ^ word).wrapping_mul(0x51_7c_c1_b7_27_22_0a_95);
262 }
263}
264
265impl Hasher for Fx {
266 fn write(&mut self, bytes: &[u8]) {
267 let (words, rest) = bytes.as_chunks::<8>();
268 for w in words {
269 self.add(u64::from_le_bytes(*w));
270 }
271 if !rest.is_empty() {
272 let mut b = [0u8; 8];
273 b[..rest.len()].copy_from_slice(rest);
274 self.add(u64::from_le_bytes(b));
275 }
276 }
277
278 fn write_u8(&mut self, b: u8) {
279 self.add(b as u64);
280 }
281
282 fn finish(&self) -> u64 {
283 self.0
284 }
285}
286
287fn varint(out: &mut Vec<u8>, mut n: u64) {
288 while n >= 0x80 {
289 out.push((n as u8) | 0x80);
290 n >>= 7;
291 }
292 out.push(n as u8);
293}
294
295#[derive(Debug, Clone, PartialEq, Eq)]
297pub struct DecodeError {
298 pub message: String,
299 pub offset: usize,
300}
301
302impl fmt::Display for DecodeError {
303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 write!(f, "byte {}: {}", self.offset, self.message)
305 }
306}
307
308impl std::error::Error for DecodeError {}
309
310pub fn decode(bytes: &[u8]) -> Result<Value, DecodeError> {
312 let mut d = Decoder::open(bytes)?;
313 let v = d.value(0)?;
314 d.end()?;
315 Ok(v)
316}
317
318pub fn decode_ref<'a>(bytes: &'a [u8], arena: &'a Bump) -> Result<ValueRef<'a>, DecodeError> {
322 let mut d = Decoder::open(bytes)?;
323 let mut stack = Vec::new();
324 let v = d.value_ref(0, arena, &mut stack)?;
325 d.end()?;
326 Ok(v)
327}
328
329impl<'b> Decoder<'b> {
330 fn open(bytes: &'b [u8]) -> Result<Self, DecodeError> {
332 let mut d = Decoder {
333 b: bytes,
334 i: 0,
335 strings: Vec::new(),
336 keys: Vec::new(),
337 };
338 if !bytes.starts_with(MAGIC) {
339 return Err(d.error("not Yog Data (no `YOGD` header)"));
340 }
341 d.i = 4;
342 let version = d.byte()?;
343 if version != VERSION {
344 return Err(d.error(format!(
345 "Yog Data version {version}, this reads version {VERSION}"
346 )));
347 }
348 let count = d.count(1)?;
349 d.strings.reserve(count);
350 for _ in 0..count {
351 let len = d.count(1)?;
352 let start = d.i;
353 let s = std::str::from_utf8(&bytes[start..start + len]).map_err(|_| DecodeError {
354 message: "a string isn't UTF-8".into(),
355 offset: start,
356 })?;
357 d.strings.push(s);
358 d.i += len;
359 }
360 Ok(d)
361 }
362
363 fn end(&self) -> Result<(), DecodeError> {
364 if self.i != self.b.len() {
365 return Err(self.error("bytes after the value"));
366 }
367 Ok(())
368 }
369}
370
371struct Decoder<'b> {
372 b: &'b [u8],
373 i: usize,
374 strings: Vec<&'b str>,
375 keys: Vec<Option<std::sync::Arc<str>>>,
377}
378
379impl<'b> Decoder<'b> {
380 fn error(&self, message: impl Into<String>) -> DecodeError {
381 DecodeError {
382 message: message.into(),
383 offset: self.i,
384 }
385 }
386
387 fn byte(&mut self) -> Result<u8, DecodeError> {
388 let b = *self
389 .b
390 .get(self.i)
391 .ok_or_else(|| self.error("unexpected end"))?;
392 self.i += 1;
393 Ok(b)
394 }
395
396 fn varint(&mut self) -> Result<u64, DecodeError> {
397 let mut n = 0u64;
398 for shift in (0..64).step_by(7) {
399 let b = self.byte()?;
400 n |= ((b & 0x7F) as u64) << shift;
401 if b & 0x80 == 0 {
402 return Ok(n);
403 }
404 }
405 Err(self.error("varint longer than 64 bits"))
406 }
407
408 fn count(&mut self, min: usize) -> Result<usize, DecodeError> {
410 let n = self.varint()?;
411 let left = self.b.len() - self.i;
412 if n > (left / min.max(1)) as u64 {
413 return Err(self.error(format!("length {n} past the end ({left} bytes left)")));
414 }
415 Ok(n as usize)
416 }
417
418 fn fixed<const N: usize>(&mut self) -> Result<[u8; N], DecodeError> {
419 let bytes = self
420 .b
421 .get(self.i..self.i + N)
422 .ok_or_else(|| self.error("unexpected end"))?;
423 self.i += N;
424 Ok(bytes.try_into().unwrap())
425 }
426
427 fn bytes(&mut self) -> Result<&'b [u8], DecodeError> {
429 let len = usize::try_from(self.varint()?).map_err(|_| self.error("a length beyond memory"))?;
430 let end = self.i.checked_add(len).filter(|&e| e <= self.b.len()).ok_or_else(|| self.error("bytes past the end"))?;
431 let out = &self.b[self.i..end];
432 self.i = end;
433 Ok(out)
434 }
435
436 fn string(&mut self) -> Result<&'b str, DecodeError> {
437 let i = self.varint()?;
438 self.strings
439 .get(i as usize)
440 .copied()
441 .ok_or_else(|| self.error(format!("string {i} isn't in the table")))
442 }
443
444 fn key(&mut self) -> Result<std::sync::Arc<str>, DecodeError> {
446 let i = self.varint()? as usize;
447 if let Some(Some(k)) = self.keys.get(i) {
448 return Ok(k.clone());
449 }
450 let s = *self.strings.get(i).ok_or_else(|| self.error(format!("string {i} isn't in the table")))?;
451 let k: std::sync::Arc<str> = s.into();
452 if self.keys.len() <= i {
453 self.keys.resize(self.strings.len(), None);
454 }
455 self.keys[i] = Some(k.clone());
456 Ok(k)
457 }
458
459 fn value_ref<'a>(&mut self, depth: usize, arena: &'a Bump, stack: &mut Vec<ValueRef<'a>>) -> Result<ValueRef<'a>, DecodeError>
462 where
463 'b: 'a,
464 {
465 if depth > MAX_DEPTH {
466 return Err(self.error(format!("nested deeper than {MAX_DEPTH} levels")));
467 }
468 Ok(match self.byte()? {
469 tag::NULL => ValueRef::Null,
470 tag::FALSE => ValueRef::Bool(false),
471 tag::TRUE => ValueRef::Bool(true),
472 tag::INT => {
473 let z = self.varint()?;
474 ValueRef::Int(((z >> 1) as i64) ^ -((z & 1) as i64))
475 }
476 tag::FLOAT => ValueRef::Float(f64::from_le_bytes(self.fixed()?)),
477 tag::STR => ValueRef::Str(self.string()?),
478 tag::LIST => {
479 let n = self.count(1)?;
480 let start = stack.len();
481 for _ in 0..n {
482 let v = self.value_ref(depth + 1, arena, stack)?;
483 stack.push(v);
484 }
485 let items = arena.alloc_slice_copy(&stack[start..]);
486 stack.truncate(start);
487 ValueRef::List(items)
488 }
489 tag::MAP => {
490 let n = self.count(2)?;
491 let mut entries = bumpalo::collections::Vec::with_capacity_in(n, arena);
492 for _ in 0..n {
493 let k = self.string()?;
494 entries.push((k, self.value_ref(depth + 1, arena, stack)?));
495 }
496 ValueRef::Map(MapRef(entries.into_bump_slice()))
497 }
498 t @ (tag::REF | tag::TAG) => {
499 let (kind, id) = (self.string()?, self.string()?);
500 if t == tag::REF { ValueRef::Ref { kind, id } } else { ValueRef::Tag { kind, id } }
501 }
502 tag::RES => ValueRef::Res { set: self.string()?, key: self.string()? },
503 tag::TEXT => ValueRef::Text(self.string()?),
504 tag::IMAGE => ValueRef::Image(self.string()?),
505 tag::COLOR => ValueRef::Color(u32::from_le_bytes(self.fixed()?)),
506 tag::LANG => ValueRef::Lang(self.string()?),
507 tag::BYTES => ValueRef::Bytes(self.bytes()?),
508 t => {
509 self.i -= 1;
510 return Err(self.error(format!("unknown tag {t}")));
511 }
512 })
513 }
514
515 fn value(&mut self, depth: usize) -> Result<Value, DecodeError> {
516 if depth > MAX_DEPTH {
517 return Err(self.error(format!("nested deeper than {MAX_DEPTH} levels")));
518 }
519 Ok(match self.byte()? {
520 tag::NULL => Value::Null,
521 tag::FALSE => Value::Bool(false),
522 tag::TRUE => Value::Bool(true),
523 tag::INT => {
524 let z = self.varint()?;
525 Value::Int(((z >> 1) as i64) ^ -((z & 1) as i64))
526 }
527 tag::FLOAT => Value::Float(f64::from_le_bytes(self.fixed()?)),
528 tag::STR => Value::Str(self.string()?.to_string()),
529 tag::LIST => {
530 let n = self.count(1)?;
531 let mut items = Vec::with_capacity(n);
532 for _ in 0..n {
533 items.push(self.value(depth + 1)?);
534 }
535 Value::List(items)
536 }
537 tag::MAP => {
538 let n = self.count(2)?;
539 let mut map = Map::with_capacity(n);
540 for _ in 0..n {
541 let k = self.key()?;
542 map.push_unchecked(k, self.value(depth + 1)?);
543 }
544 Value::Map(map)
545 }
546 t @ (tag::REF | tag::TAG) => {
547 let r = Ref {
548 kind: self.string()?.to_string(),
549 id: self.string()?.to_string(),
550 };
551 if t == tag::REF {
552 Value::Ref(r)
553 } else {
554 Value::Tag(r)
555 }
556 }
557 tag::RES => Value::Res(Res {
558 set: self.string()?.to_string(),
559 key: self.string()?.to_string(),
560 }),
561 tag::TEXT => Value::Text(self.string()?.to_string()),
562 tag::IMAGE => Value::Image(self.string()?.to_string()),
563 tag::COLOR => Value::Color(u32::from_le_bytes(self.fixed()?)),
564 tag::LANG => Value::Lang(self.string()?.to_string()),
565 tag::BYTES => Value::Bytes(self.bytes()?.to_vec()),
566 t => {
567 self.i -= 1;
568 return Err(self.error(format!("unknown tag {t}")));
569 }
570 })
571 }
572}
573
574#[cfg(test)]
575mod tests {
576 use super::*;
577
578 fn sample() -> Value {
579 let mut m = Map::new();
580 m.insert("name", Value::Str("Ruby".into()));
581 m.insert(
582 "n",
583 Value::List(vec![
584 Value::Int(0),
585 Value::Int(-1),
586 Value::Int(i64::MAX),
587 Value::Int(i64::MIN),
588 Value::Float(0.5),
589 Value::Null,
590 Value::Bool(true),
591 Value::Bool(false),
592 ]),
593 );
594 m.insert("item", Value::Ref(Ref::new("item", "minecraft:stick")));
595 m.insert("tag", Value::Tag(Ref::new("item", "minecraft:planks")));
596 m.insert(
597 "title",
598 Value::Res(Res {
599 set: "Strings".into(),
600 key: "title".into(),
601 }),
602 );
603 m.insert("text", Value::Text("{b|hi}".into()));
604 m.insert("icon", Value::Image("sprite:x".into()));
605 m.insert("color", Value::Color(0x80FF0000));
606 m.insert("lang", Value::Lang("gui.done".into()));
607 m.insert("again", Value::Str("Ruby".into()));
608 Value::Map(m)
609 }
610
611 #[test]
612 fn bytes_round_trip_in_both_forms() {
613 let v = Value::Bytes(vec![0, 1, 2, 255]);
614 assert_eq!(decode(&encode(&v)).unwrap(), v);
615 let text = crate::text::to_string(&v);
616 assert_eq!(text, "\"@bytes:AAEC/w==\"");
617 assert_eq!(crate::typed::classify("@bytes:AAEC/w==").unwrap(), v);
618 assert!(decode(&[b'Y', b'O', b'G', b'D', VERSION, 0, tag::BYTES, 9]).is_err(), "a length past the end");
619 }
620
621 #[test]
622 fn round_trips_every_type() {
623 let v = sample();
624 let bytes = encode(&v);
625 assert_eq!(decode(&bytes).unwrap(), v);
626 assert_eq!(bytes.windows(4).filter(|w| w == b"Ruby").count(), 1);
628 }
629
630 #[test]
631 fn the_borrowed_decode_reads_the_same_without_copying() {
632 let v = sample();
633 let bytes = encode(&v);
634 let arena = Bump::new();
635 let r = decode_ref(&bytes, &arena).unwrap();
636 assert_eq!(r.to_value(), v);
637 assert_eq!(r, v.borrow(&arena), "borrowing a Value gives the same");
638 let span = bytes.as_ptr_range();
640 let mut strings = Vec::new();
641 fn walk<'a>(v: &ValueRef<'a>, out: &mut Vec<&'a str>) {
642 match v {
643 ValueRef::Str(s) | ValueRef::Text(s) | ValueRef::Image(s) | ValueRef::Lang(s) => out.push(s),
644 ValueRef::List(l) => l.iter().for_each(|x| walk(x, out)),
645 ValueRef::Map(m) => m.iter().for_each(|(k, x)| {
646 out.push(k);
647 walk(x, out)
648 }),
649 _ => {}
650 }
651 }
652 walk(&r, &mut strings);
653 assert!(!strings.is_empty() && strings.iter().all(|s| span.contains(&s.as_ptr())));
654 for len in 0..bytes.len() {
656 assert!(decode_ref(&bytes[..len], &arena).is_err(), "truncated at {len}");
657 }
658 }
659
660 #[test]
661 fn malformed_bytes_are_errors() {
662 let bytes = encode(&sample());
663 for len in 0..bytes.len() {
665 assert!(decode(&bytes[..len]).is_err(), "truncated at {len}");
666 }
667 let mut extra = bytes.clone();
668 extra.push(0);
669 assert!(
670 decode(&extra)
671 .unwrap_err()
672 .message
673 .contains("after the value")
674 );
675 assert!(
676 decode(b"YOGD\x02\x00\x00")
677 .unwrap_err()
678 .message
679 .contains("version 2")
680 );
681 assert!(
682 decode(b"YOGD\x01\x00\x63")
683 .unwrap_err()
684 .message
685 .contains("unknown tag")
686 );
687 assert!(
688 decode(b"YOGD\x01\x00\x05\x00")
689 .unwrap_err()
690 .message
691 .contains("isn't in the table")
692 );
693 assert!(
695 decode(b"YOGD\x01\x00\x06\xff\xff\xff\xff\x0f")
696 .unwrap_err()
697 .message
698 .contains("past the end")
699 );
700 let deep: Vec<u8> = b"YOGD\x01\x00"
701 .iter()
702 .copied()
703 .chain(std::iter::repeat_n([6u8, 1], 300).flatten())
704 .chain([0])
705 .collect();
706 assert!(decode(&deep).unwrap_err().message.contains("nested deeper"));
707 }
708}