leb.rs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. pub fn write_leb_i32(buf: &mut Vec<u8>, mut v: i32) {
  2. // Super complex stuff. See the following:
  3. // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer
  4. // http://llvm.org/doxygen/LEB128_8h_source.html#l00048
  5. let mut more = true;
  6. let negative = v < 0;
  7. let size = 32;
  8. while more {
  9. let mut byte = (v & 0b1111111) as u8; // get last 7 bits
  10. v >>= 7; // shift them away from the value
  11. if negative {
  12. v |= (!0 as i32) << (size - 7); // extend sign
  13. }
  14. let sign_bit = byte & (1 << 6);
  15. if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) {
  16. more = false;
  17. }
  18. else {
  19. byte |= 0b10000000; // turn on MSB
  20. }
  21. buf.push(byte);
  22. }
  23. }
  24. pub fn write_leb_u32(buf: &mut Vec<u8>, mut v: u32) {
  25. loop {
  26. let mut byte = v as u8 & 0b01111111; // get last 7 bits
  27. v >>= 7; // shift them away from the value
  28. if v != 0 {
  29. byte |= 0b10000000; // turn on MSB
  30. }
  31. buf.push(byte);
  32. if v == 0 {
  33. break;
  34. }
  35. }
  36. }
  37. pub fn write_fixed_leb16_at_idx(vec: &mut Vec<u8>, idx: usize, x: u16) {
  38. dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb
  39. vec[idx] = ((x & 0b1111111) | 0b10000000) as u8;
  40. vec[idx + 1] = (x >> 7) as u8;
  41. }
  42. pub fn write_fixed_leb32_at_idx(vec: &mut Vec<u8>, idx: usize, x: u32) {
  43. dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb
  44. vec[idx] = (x & 0b1111111) as u8 | 0b10000000;
  45. vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000;
  46. vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000;
  47. vec[idx + 3] = (x >> 21 & 0b1111111) as u8;
  48. }