plotnik_bytecode/bytecode/
nav.rs1#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
7pub enum Nav {
8 #[default]
11 Epsilon,
12 Stay,
14 StayExact,
16 Next,
17 NextSkip,
18 NextExact,
19 Down,
20 DownSkip,
21 DownExact,
22 Up(u8),
23 UpSkipTrivia(u8),
24 UpExact(u8),
25}
26
27impl Nav {
28 pub fn from_byte(b: u8) -> Self {
34 let mode = b >> 6;
35 let payload = b & 0x3F;
36
37 match mode {
38 0b00 => match payload {
39 0 => Self::Epsilon,
40 1 => Self::Stay,
41 2 => Self::StayExact,
42 3 => Self::Next,
43 4 => Self::NextSkip,
44 5 => Self::NextExact,
45 6 => Self::Down,
46 7 => Self::DownSkip,
47 8 => Self::DownExact,
48 _ => panic!("invalid nav standard: {payload}"),
49 },
50 0b01 => {
51 assert!(payload >= 1, "invalid nav up level: {payload}");
52 Self::Up(payload)
53 }
54 0b10 => {
55 assert!(payload >= 1, "invalid nav up_skip_trivia level: {payload}");
56 Self::UpSkipTrivia(payload)
57 }
58 0b11 => {
59 assert!(payload >= 1, "invalid nav up_exact level: {payload}");
60 Self::UpExact(payload)
61 }
62 _ => unreachable!(),
63 }
64 }
65
66 pub fn to_byte(self) -> u8 {
68 match self {
69 Self::Epsilon => 0,
70 Self::Stay => 1,
71 Self::StayExact => 2,
72 Self::Next => 3,
73 Self::NextSkip => 4,
74 Self::NextExact => 5,
75 Self::Down => 6,
76 Self::DownSkip => 7,
77 Self::DownExact => 8,
78 Self::Up(n) => {
79 assert!((1..=63).contains(&n), "Up level overflow: {n} > 63");
80 0b01_000000 | n
81 }
82 Self::UpSkipTrivia(n) => {
83 assert!(
84 (1..=63).contains(&n),
85 "UpSkipTrivia level overflow: {n} > 63"
86 );
87 0b10_000000 | n
88 }
89 Self::UpExact(n) => {
90 assert!((1..=63).contains(&n), "UpExact level overflow: {n} > 63");
91 0b11_000000 | n
92 }
93 }
94 }
95
96 pub fn to_exact(self) -> Self {
102 match self {
103 Self::Epsilon => Self::Epsilon, Self::Down | Self::DownSkip => Self::DownExact,
105 Self::Next | Self::NextSkip => Self::NextExact,
106 Self::Stay => Self::StayExact,
107 Self::Up(n) | Self::UpSkipTrivia(n) => Self::UpExact(n),
108 Self::DownExact | Self::NextExact | Self::StayExact | Self::UpExact(_) => self,
110 }
111 }
112}