logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Status-update-March-2022.md (5048B)


  1. ---
  2. title: Status update, March 2022
  3. date: 2022-03-15
  4. ---
  5. Greetings! The weather is starting to warm up again, eh? I'm a bit disappointed
  6. that we didn't get any snow this winter. Yadda yadda insert intro text here.
  7. Let's get down to brass tacks. What's new this month?
  8. I mainly focused on the programming language this month. I started writing a
  9. kernel, which you can see a screenshot of below. This screenshot shows a
  10. simulated page fault, demonstrating that we have a working interrupt handler,
  11. and also shows something mildly interesting: backtraces. I need to incorporate
  12. this approach into the standard library as well, so that we can dump useful
  13. stack traces on assertion failures and such. I understand that someone is
  14. working on DWARF support as well, so perhaps we'll soon be able to translate
  15. function name + offset into a file name and line number.
  16. ![A redacted screenshot of a kernel showing a simulated page fault](https://l.sr.ht/LHZ2.png)
  17. I also started working on a PNG decoder this weekend, which at the time of
  18. writing can successfully decode 77 of the 161 PNG test vectors. I am quite
  19. pleased with how the code turned out here: this library is a good demonstration
  20. of the strengths of the language. It has simple code which presents a
  21. comprehensive interface for the file format, has a strong user-directed memory
  22. management model, takes good advantage of features like slices, and makes good
  23. use of standard library features like compress::zlib and the I/O abstraction. I
  24. will supplement this later with a higher level image API which handles things
  25. like pixel format conversions and abstracting away format-specific details.
  26. <details>
  27. <summary>Expand for a sample from image::png</summary>
  28. ```hare
  29. use bufio;
  30. use bytes;
  31. use compress::zlib;
  32. use errors;
  33. use io;
  34. export type idat_reader = struct {
  35. st: io::stream,
  36. src: *chunk_reader,
  37. inflate: zlib::reader,
  38. decoder: *decoder,
  39. };
  40. // Returns a new IDAT reader for a [[chunk_reader]], from which raw pixel data
  41. // may be read via [[io::read]]. The user must prepare a [[decoder]] object
  42. // along with a working buffer to store the decoder state. For information about
  43. // preparing a suitable decoder, see [[newdecoder]].
  44. export fn new_idat_reader(
  45. cr: *chunk_reader,
  46. decoder: *decoder,
  47. ) (idat_reader | io::error) = {
  48. assert(cr.ctype == IDAT, "Attempted to create IDAT reader for non-IDAT chunk");
  49. return idat_reader {
  50. st = io::stream {
  51. reader = &idat_read,
  52. ...
  53. },
  54. src = cr,
  55. inflate = zlib::decompress(cr)?,
  56. decoder = decoder,
  57. };
  58. };
  59. fn idat_read(
  60. st: *io::stream,
  61. buf: []u8,
  62. ) (size | io::EOF | io::error) = {
  63. let ir = st: *idat_reader;
  64. assert(ir.st.reader == &idat_read);
  65. let dec = ir.decoder;
  66. if (dec.buffered != 0) {
  67. return decoder_copy(dec, buf);
  68. };
  69. if (dec.filter is void) {
  70. const ft = match (bufio::scanbyte(&ir.inflate)) {
  71. case io::EOF =>
  72. return idat_finish(ir);
  73. case let b: u8 =>
  74. yield b: filter;
  75. };
  76. if (ft > filter::PAETH) {
  77. return errors::invalid;
  78. };
  79. dec.filter = ft;
  80. };
  81. // Read one scanline
  82. for (dec.read < len(dec.cr)) {
  83. match (io::read(&ir.inflate, dec.cr[dec.read..])?) {
  84. case io::EOF =>
  85. // TODO: The rest of the scanline could be in the next
  86. // IDAT chunk. However, if there is a partially read
  87. // scanline in the decoder and no IDAT chunk in the
  88. // remainder of the file, we should probably raise an
  89. // error.
  90. return idat_finish(ir);
  91. case let n: size =>
  92. dec.read += n;
  93. };
  94. };
  95. applyfilter(dec);
  96. dec.read = 0;
  97. dec.buffered = len(dec.cr);
  98. return decoder_copy(dec, buf);
  99. };
  100. fn idat_finish(ir: *idat_reader) (io::EOF | io::error) = {
  101. // Verify checksum
  102. if (io::copy(io::empty, ir.src)? != 0) {
  103. // Extra data following zlib stream
  104. return errors::invalid;
  105. };
  106. return io::EOF;
  107. };
  108. @test fn idat_reader() void = {
  109. const src = bufio::fixed(no_filtering, io::mode::READ);
  110. const read = newreader(&src) as reader;
  111. let chunk = nextchunk(&read) as chunk_reader;
  112. const ihdr = new_ihdr_reader(&chunk);
  113. const ihdr = ihdr_read(&ihdr)!;
  114. let pixbuf: []u8 = alloc([0...], decoder_bufsiz(&ihdr));
  115. defer free(pixbuf);
  116. let decoder = newdecoder(&ihdr, pixbuf);
  117. for (true) {
  118. chunk = nextchunk(&read) as chunk_reader;
  119. if (chunk_reader_type(&chunk) == IDAT) {
  120. break;
  121. };
  122. io::copy(io::empty, &chunk)!;
  123. };
  124. const idat = new_idat_reader(&chunk, &decoder)!;
  125. const pixels = io::drain(&idat)!;
  126. defer free(pixels);
  127. assert(bytes::equal(pixels, no_filtering_data));
  128. };
  129. ```
  130. </details>
  131. In SourceHut news, I completed our migration to Alpine 3.15 this month after a
  132. brief outage, including an upgrade to our database server, which is upgraded on
  133. a less frequent cadance than the others. Thanks to Adnan's work, we've also
  134. landed many GraphQL improvements, mainly refactorings and other like
  135. improvements, setting the stage for the next series of roll-outs. I plan on
  136. transitioning back from focusing on the language to focusing on SourceHut for
  137. the coming month, and I expect to see some good progress here.
  138. That's all I have to share for today. Until next time!