Skip to main content

luaur_bytecode/methods/
bytecode_builder_write_line_info.rs

1use crate::functions::log_2::log2;
2use crate::functions::write_byte::writeByte;
3use crate::functions::write_int::writeInt;
4use crate::records::bytecode_builder::BytecodeBuilder;
5use alloc::string::String;
6use alloc::vec::Vec;
7use core::cmp;
8use luaur_common::macros::luau_assert::LUAU_ASSERT;
9
10impl BytecodeBuilder {
11    pub fn write_line_info(&self, ss: &mut String) {
12        LUAU_ASSERT!(!self.lines.is_empty());
13
14        let mut span = 1 << 24;
15
16        let mut offset = 0;
17        while offset < self.lines.len() {
18            let mut next = offset;
19            let mut min = self.lines[offset];
20            let mut max = self.lines[offset];
21
22            while next < self.lines.len() && next < offset + span {
23                min = cmp::min(min, self.lines[next]);
24                max = cmp::max(max, self.lines[next]);
25
26                if max - min > 255 {
27                    break;
28                }
29                next += 1;
30            }
31
32            if next < self.lines.len() && next - offset < span {
33                span = 1 << log2((next - offset) as i32);
34            } else {
35                offset += span;
36            }
37        }
38
39        let mut baseline_one = 0;
40        let mut baseline_scratch = Vec::new();
41        let baseline_size = (self.lines.len() - 1) / span + 1;
42
43        if baseline_size > 1 {
44            baseline_scratch.resize(baseline_size, 0);
45        }
46
47        let baseline = if baseline_size > 1 {
48            &mut baseline_scratch
49        } else {
50            core::slice::from_mut(&mut baseline_one)
51        };
52
53        for offset in (0..self.lines.len()).step_by(span) {
54            let mut next = offset;
55            let mut min = self.lines[offset];
56
57            while next < self.lines.len() && next < offset + span {
58                min = cmp::min(min, self.lines[next]);
59                next += 1;
60            }
61
62            baseline[offset / span] = min;
63        }
64
65        let logspan = log2(span as i32);
66        writeByte(ss, logspan as u8);
67
68        let mut last_offset = 0u8;
69        for i in 0..self.lines.len() {
70            let delta = self.lines[i] - baseline[i >> logspan];
71            LUAU_ASSERT!(delta >= 0 && delta <= 255);
72
73            writeByte(ss, (delta as u8).wrapping_sub(last_offset));
74            last_offset = delta as u8;
75        }
76
77        let mut last_line = 0;
78        for i in 0..baseline_size {
79            writeInt(ss, baseline[i] - last_line);
80            last_line = baseline[i];
81        }
82    }
83}