From ff5af2689a481444645b55f0537be77a13d59aa9 Mon Sep 17 00:00:00 2001 From: Edward Amsden Date: Tue, 27 Feb 2024 13:18:18 -0600 Subject: [PATCH] add format-to-cord implementation and flog! macro --- rust/ares/src/flog.rs | 73 +++++++++++++++++++++++++++++++++++++++++++ rust/ares/src/lib.rs | 1 + 2 files changed, 74 insertions(+) create mode 100644 rust/ares/src/flog.rs diff --git a/rust/ares/src/flog.rs b/rust/ares/src/flog.rs new file mode 100644 index 0000000..11d2343 --- /dev/null +++ b/rust/ares/src/flog.rs @@ -0,0 +1,73 @@ +use crate::mem::NockStack; +use crate::noun::{Atom, IndirectAtom}; +use crate::interpreter::Context; +use std::io::{Write, Result}; +use std::fmt::Arguments; + +struct NockWriter<'s, 'b> { + stack: &'s mut NockStack, + buffer: &'b mut [u8], + indirect: IndirectAtom, + cursor: usize, //bytes +} + +const INITIAL_CAPACITY_BYTES: usize = 256; + +impl<'s, 'b> NockWriter<'s, 'b> { + unsafe fn new(stack: &'s mut NockStack) -> Self { + let (indirect, buffer) = IndirectAtom::new_raw_mut_bytes(stack, INITIAL_CAPACITY_BYTES); + NockWriter { + stack, + buffer, + indirect, + cursor: 0, + } + } + + unsafe fn finalize(mut self) -> Atom { + self.indirect.normalize_as_atom() + } + + unsafe fn expand(&mut self) { + let sz = self.buffer.len(); + let (new_indirect, new_buffer) = IndirectAtom::new_raw_mut_bytes(self.stack, sz * 2); + new_buffer[0..sz].copy_from_slice(self.buffer); + self.buffer = new_buffer; + self.indirect = new_indirect; + } +} + +impl Write for NockWriter<'_, '_> { + fn write(&mut self, buf: &[u8]) -> Result { + let sz = buf.len(); + while (self.buffer.len() - self.cursor) < sz { + unsafe { self.expand() }; + } + self.buffer[self.cursor..self.cursor + sz].copy_from_slice(buf); + self.cursor += sz; + Ok(sz) + } + + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} + +pub fn nock_fmt(context: &mut Context, fmt: Arguments<'_>) -> Result { + let mut nw = unsafe { NockWriter::new(&mut context.stack) }; + nw.write_fmt(fmt)?; + Ok(unsafe { nw.finalize() }) +} + +pub fn flog_fmt(context: &mut Context, fmt: Arguments<'_>) -> Result<()> { + let cord = nock_fmt(context, fmt)?; + context.newt.flog(&mut context.stack, cord.as_noun()); + Ok(()) +} + +#[macro_export] +macro_rules! flog { + ($ctx:expr, $($arg:tt)*) => { + $crate::flog::flog_fmt($ctx, std::format_args!($($arg)*)) + } +} diff --git a/rust/ares/src/lib.rs b/rust/ares/src/lib.rs index d6f6391..f34d51a 100644 --- a/rust/ares/src/lib.rs +++ b/rust/ares/src/lib.rs @@ -4,6 +4,7 @@ extern crate lazy_static; #[macro_use] extern crate static_assertions; pub mod guard; +pub mod flog; pub mod hamt; pub mod interpreter; pub mod jets;