Browse Source

Add an extra optional `^int` parameter to most io read/write calls allowing for simplified `or_return` use with incrementing byte usage

gingerBill 4 years ago
parent
commit
8e2a0be804
3 changed files with 268 additions and 225 deletions
  1. 67 21
      core/io/io.odin
  2. 77 77
      core/io/util.odin
  3. 124 127
      core/reflect/types.odin

+ 67 - 21
core/io/io.odin

@@ -139,16 +139,24 @@ destroy :: proc(s: Stream) -> Error {
 	return .Empty
 }
 
-read :: proc(s: Reader, p: []byte) -> (n: int, err: Error) {
+read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
 	if s.stream_vtable != nil && s.impl_read != nil {
-		return s->impl_read(p)
+		n, err = s->impl_read(p)
+		if n_read != nil {
+			n_read^ += n
+		}
+		return
 	}
 	return 0, .Empty
 }
 
-write :: proc(s: Writer, p: []byte) -> (n: int, err: Error) {
+write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) {
 	if s.stream_vtable != nil && s.impl_write != nil {
-		return s->impl_write(p)
+		n, err = s->impl_write(p)
+		if n_written != nil {
+			n_written^ += n
+		}
+		return
 	}
 	return 0, .Empty
 }
@@ -207,12 +215,16 @@ size :: proc(s: Stream) -> i64 {
 
 
 
-read_at :: proc(r: Reader_At, p: []byte, offset: i64) -> (n: int, err: Error) {
+read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
 	if r.stream_vtable == nil {
 		return 0, .Empty
 	}
 	if r.impl_read_at != nil {
-		return r->impl_read_at(p, offset)
+		n, err = r->impl_read_at(p, offset)
+		if n_read != nil {
+			n_read^ += n
+		}
+		return
 	}
 	if r.impl_seek == nil || r.impl_read == nil {
 		return 0, .Empty
@@ -225,6 +237,9 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64) -> (n: int, err: Error) {
 	}
 
 	n, err = r->impl_read(p)
+	if n_read != nil {
+		n_read^ += n
+	}
 	_, err1 := r->impl_seek(curr_offset, .Start)
 	if err1 != nil && err == nil {
 		err = err1
@@ -233,12 +248,16 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64) -> (n: int, err: Error) {
 
 }
 
-write_at :: proc(w: Writer_At, p: []byte, offset: i64) -> (n: int, err: Error) {
+write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
 	if w.stream_vtable == nil {
 		return 0, .Empty
 	}
 	if w.impl_write_at != nil {
-		return w->impl_write_at(p, offset)
+		n, err = w->impl_write_at(p, offset)
+		if n_written != nil {
+			n_written^ += n
+		}
+		return
 	}
 	if w.impl_seek == nil || w.impl_write == nil {
 		return 0, .Empty
@@ -251,6 +270,9 @@ write_at :: proc(w: Writer_At, p: []byte, offset: i64) -> (n: int, err: Error) {
 	}
 
 	n, err = w->impl_write(p)
+	if n_written != nil {
+		n_written^ += n
+	}
 	_, err1 := w->impl_seek(curr_offset, .Start)
 	if err1 != nil && err == nil {
 		err = err1
@@ -278,7 +300,7 @@ read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) {
 }
 
 
-read_byte :: proc(r: Byte_Reader) -> (byte, Error) {
+read_byte :: proc(r: Byte_Reader, n_read: ^int = nil) -> (byte, Error) {
 	if r.stream_vtable == nil {
 		return 0, .Empty
 	}
@@ -291,6 +313,9 @@ read_byte :: proc(r: Byte_Reader) -> (byte, Error) {
 
 	b: [1]byte
 	_, err := r->impl_read(b[:])
+	if err == nil && n_read != nil {
+		n_read^ += 1
+	}
 	return b[0], err
 }
 
@@ -299,16 +324,16 @@ write_byte :: proc{
 	write_byte_to_writer,
 }
 
-write_byte_to_byte_writer :: proc(w: Byte_Writer, c: byte) -> Error {
-	return _write_byte(w, c)
+write_byte_to_byte_writer :: proc(w: Byte_Writer, c: byte, n_written: ^int = nil) -> Error {
+	return _write_byte(w, c, n_written)
 }
 
-write_byte_to_writer :: proc(w: Writer, c: byte) -> Error {
-	return _write_byte(auto_cast w, c)
+write_byte_to_writer :: proc(w: Writer, c: byte, n_written: ^int = nil) -> Error {
+	return _write_byte(auto_cast w, c, n_written)
 }
 
 @(private)
-_write_byte :: proc(w: Byte_Writer, c: byte) -> Error {
+_write_byte :: proc(w: Byte_Writer, c: byte, n_written: ^int = nil) -> Error {
 	if w.stream_vtable == nil {
 		return .Empty
 	}
@@ -321,15 +346,22 @@ _write_byte :: proc(w: Byte_Writer, c: byte) -> Error {
 
 	b := [1]byte{c}
 	_, err := w->impl_write(b[:])
+	if err == nil && n_written != nil {
+		n_written^ += 1
+	}
 	return err
 }
 
-read_rune :: proc(br: Rune_Reader) -> (ch: rune, size: int, err: Error) {
+read_rune :: proc(br: Rune_Reader, n_read: ^int = nil) -> (ch: rune, size: int, err: Error) {
 	if br.stream_vtable == nil {
 		return 0, 0, .Empty
 	}
 	if br.impl_read_rune != nil {
-		return br->impl_read_rune()
+		ch, size, err = br->impl_read_rune()
+		if n_read != nil {
+			n_read^ += size
+		}
+		return
 	}
 	if br.impl_read == nil {
 		return 0, 0, .Empty
@@ -337,6 +369,7 @@ read_rune :: proc(br: Rune_Reader) -> (ch: rune, size: int, err: Error) {
 
 	b: [utf8.UTF_MAX]byte
 	_, err = br->impl_read(b[:1])
+	
 
 	s0 := b[0]
 	ch = rune(s0)
@@ -344,6 +377,9 @@ read_rune :: proc(br: Rune_Reader) -> (ch: rune, size: int, err: Error) {
 	if err != nil {
 		return
 	}
+	if n_read != nil {
+		n_read^ += 1
+	}
 	if ch < utf8.RUNE_SELF {
 		return
 	}
@@ -356,6 +392,9 @@ read_rune :: proc(br: Rune_Reader) -> (ch: rune, size: int, err: Error) {
 	sz := int(x&7)
 	n: int
 	n, err = br->impl_read(b[1:sz])
+	if n_read != nil {
+		n_read^ += n
+	}
 	if err != nil || n+1 < sz {
 		ch = utf8.RUNE_ERROR
 		return
@@ -379,24 +418,31 @@ unread_rune :: proc(s: Rune_Scanner) -> Error {
 }
 
 
-write_string :: proc(s: Writer, str: string) -> (n: int, err: Error) {
-	return write(s, transmute([]byte)str)
+write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) {
+	return write(s, transmute([]byte)str, n_written)
 }
 
-write_rune :: proc(s: Writer, r: rune) -> (size: int, err: Error) {
+write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
 	if s.stream_vtable != nil && s.impl_write_rune != nil {
-		return s->impl_write_rune(r)
+		size, err = s->impl_write_rune(r)
+		if n_written != nil {
+			n_written^ += size
+		}
+		return
 	}
 
 	if r < utf8.RUNE_SELF {
 		err = write_byte(s, byte(r))
 		if err == nil {
 			size = 1
+			if n_written != nil {
+				n_written^ += size
+			}
 		}
 		return
 	}
 	buf, w := utf8.encode_rune(r)
-	return write(s, buf[:w])
+	return write(s, buf[:w], n_written)
 }
 
 

+ 77 - 77
core/io/util.odin

@@ -3,49 +3,49 @@ package io
 import "core:strconv"
 import "core:unicode/utf8"
 
-read_ptr :: proc(r: Reader, p: rawptr, byte_size: int) -> (n: int, err: Error) {
-	return read(r, ([^]byte)(p)[:byte_size])
+read_ptr :: proc(r: Reader, p: rawptr, byte_size: int, n_read: ^int = nil) -> (n: int, err: Error) {
+	return read(r, ([^]byte)(p)[:byte_size], n_read)
 }
 
-write_ptr :: proc(w: Writer, p: rawptr, byte_size: int) -> (n: int, err: Error) {
-	return write(w, ([^]byte)(p)[:byte_size])
+write_ptr :: proc(w: Writer, p: rawptr, byte_size: int, n_written: ^int = nil) -> (n: int, err: Error) {
+	return write(w, ([^]byte)(p)[:byte_size], n_written)
 }
 
-read_ptr_at :: proc(r: Reader_At, p: rawptr, byte_size: int, offset: i64) -> (n: int, err: Error) {
-	return read_at(r, ([^]byte)(p)[:byte_size], offset)
+read_ptr_at :: proc(r: Reader_At, p: rawptr, byte_size: int, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
+	return read_at(r, ([^]byte)(p)[:byte_size], offset, n_read)
 }
 
-write_ptr_at :: proc(w: Writer_At, p: rawptr, byte_size: int, offset: i64) -> (n: int, err: Error) {
-	return write_at(w, ([^]byte)(p)[:byte_size], offset)
+write_ptr_at :: proc(w: Writer_At, p: rawptr, byte_size: int, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
+	return write_at(w, ([^]byte)(p)[:byte_size], offset, n_written)
 }
 
-write_u64 :: proc(w: Writer, i: u64, base: int = 10) -> (n: int, err: Error) {
+write_u64 :: proc(w: Writer, i: u64, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
 	buf: [32]byte
 	s := strconv.append_bits(buf[:], i, base, false, 64, strconv.digits, nil)
-	return write_string(w, s)
+	return write_string(w, s, n_written)
 }
-write_i64 :: proc(w: Writer, i: i64, base: int = 10) -> (n: int, err: Error) {
+write_i64 :: proc(w: Writer, i: i64, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
 	buf: [32]byte
 	s := strconv.append_bits(buf[:], u64(i), base, true, 64, strconv.digits, nil)
-	return write_string(w, s)
+	return write_string(w, s, n_written)
 }
 
-write_uint :: proc(w: Writer, i: uint, base: int = 10) -> (n: int, err: Error) {
-	return write_u64(w, u64(i), base)
+write_uint :: proc(w: Writer, i: uint, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
+	return write_u64(w, u64(i), base, n_written)
 }
-write_int :: proc(w: Writer, i: int, base: int = 10) -> (n: int, err: Error) {
-	return write_i64(w, i64(i), base)
+write_int :: proc(w: Writer, i: int, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
+	return write_i64(w, i64(i), base, n_written)
 }
 
-write_u128 :: proc(w: Writer, i: u128, base: int = 10) -> (n: int, err: Error) {
+write_u128 :: proc(w: Writer, i: u128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
 	buf: [32]byte
 	s := strconv.append_bits_128(buf[:], i, base, false, 128, strconv.digits, nil)
-	return write_string(w, s)
+	return write_string(w, s, n_written)
 }
-write_i128 :: proc(w: Writer, i: i128, base: int = 10) -> (n: int, err: Error) {
+write_i128 :: proc(w: Writer, i: i128, base: int = 10, n_written: ^int = nil) -> (n: int, err: Error) {
 	buf: [32]byte
 	s := strconv.append_bits_128(buf[:], u128(i), base, true, 128, strconv.digits, nil)
-	return write_string(w, s)
+	return write_string(w, s, n_written)
 }
 
 
@@ -54,57 +54,51 @@ write_i128 :: proc(w: Writer, i: i128, base: int = 10) -> (n: int, err: Error) {
 @(private="file")
 DIGITS_LOWER := "0123456789abcdefx"
 
-@(private="file")
-n_write_byte :: proc(w: Writer, b: byte, bytes_processed: ^int) -> Error {
-	err := write_byte(w, b)
-	if err == nil {
-		bytes_processed^ += 1
-	}
-	return err
-}
-
 n_wrapper :: proc(n: int, err: Error, bytes_processed: ^int) -> Error {
 	bytes_processed^ += n
 	return err
 }
 
 
-write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true) -> (n: int, err: Error) {
+write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true, n_written: ^int = nil) -> (n: int, err: Error) {
+	defer if n_written != nil {
+		n_written^ += n
+	}
 	if write_quote {
-		n_write_byte(w, '\'', &n) or_return
+		write_byte(w, '\'', &n) or_return
 	}
 	switch r {
-	case '\a': n_wrapper(write_string(w, `\a"`), &n) or_return
-	case '\b': n_wrapper(write_string(w, `\b"`), &n) or_return
-	case '\e': n_wrapper(write_string(w, `\e"`), &n) or_return
-	case '\f': n_wrapper(write_string(w, `\f"`), &n) or_return
-	case '\n': n_wrapper(write_string(w, `\n"`), &n) or_return
-	case '\r': n_wrapper(write_string(w, `\r"`), &n) or_return
-	case '\t': n_wrapper(write_string(w, `\t"`), &n) or_return
-	case '\v': n_wrapper(write_string(w, `\v"`), &n) or_return
+	case '\a': write_string(w, `\a"`, &n) or_return
+	case '\b': write_string(w, `\b"`, &n) or_return
+	case '\e': write_string(w, `\e"`, &n) or_return
+	case '\f': write_string(w, `\f"`, &n) or_return
+	case '\n': write_string(w, `\n"`, &n) or_return
+	case '\r': write_string(w, `\r"`, &n) or_return
+	case '\t': write_string(w, `\t"`, &n) or_return
+	case '\v': write_string(w, `\v"`, &n) or_return
 	case:
 		if r < 32 {
-			n_wrapper(write_string(w, `\x`), &n) or_return
+			write_string(w, `\x`, &n) or_return
 			
 			buf: [2]byte
 			s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil)
 			switch len(s) {
-			case 0: n_wrapper(write_string(w, "00"), &n) or_return
-			case 1: n_write_byte(w, '0', &n)             or_return
-			case 2: n_wrapper(write_string(w, s), &n)    or_return
+			case 0: write_string(w, "00", &n) or_return
+			case 1: write_byte(w, '0', &n)             or_return
+			case 2: write_string(w, s, &n)    or_return
 			}
 		} else {
-			n_wrapper(write_rune(w, r), &n) or_return
+			write_rune(w, r, &n) or_return
 		}
 
 	}
 	if write_quote {
-		n_write_byte(w, '\'', &n) or_return
+		write_byte(w, '\'', &n) or_return
 	}
 	return
 }
 
-write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false) -> (n: int, err: Error) {
+write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false, n_written: ^int = nil) -> (n: int, err: Error) {
 	is_printable :: proc(r: rune) -> bool {
 		if r <= 0xff {
 			switch r {
@@ -118,66 +112,72 @@ write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false)
 		// TODO(bill): A proper unicode library will be needed!
 		return false
 	}
+	defer if n_written != nil {
+		n_written^ += n
+	}
 	
 	if html_safe {
 		switch r {
 		case '<', '>', '&':
-			n_write_byte(w, '\\', &n) or_return
-			n_write_byte(w, 'u', &n)  or_return
+			write_byte(w, '\\', &n) or_return
+			write_byte(w, 'u', &n)  or_return
 			for s := 12; s >= 0; s -= 4 {
-				n_write_byte(w, DIGITS_LOWER[r>>uint(s) & 0xf], &n) or_return
+				write_byte(w, DIGITS_LOWER[r>>uint(s) & 0xf], &n) or_return
 			}
 			return
 		}
 	}
 
 	if r == rune(quote) || r == '\\' {
-		n_write_byte(w, '\\', &n)    or_return
-		n_write_byte(w, byte(r), &n) or_return
+		write_byte(w, '\\', &n)    or_return
+		write_byte(w, byte(r), &n) or_return
 		return
 	} else if is_printable(r) {
-		n_wrapper(write_encoded_rune(w, r, false), &n) or_return
+		write_encoded_rune(w, r, false, &n) or_return
 		return
 	}
 	switch r {
-	case '\a': n_wrapper(write_string(w, `\a`), &n) or_return
-	case '\b': n_wrapper(write_string(w, `\b`), &n) or_return
-	case '\e': n_wrapper(write_string(w, `\e`), &n) or_return
-	case '\f': n_wrapper(write_string(w, `\f`), &n) or_return
-	case '\n': n_wrapper(write_string(w, `\n`), &n) or_return
-	case '\r': n_wrapper(write_string(w, `\r`), &n) or_return
-	case '\t': n_wrapper(write_string(w, `\t`), &n) or_return
-	case '\v': n_wrapper(write_string(w, `\v`), &n) or_return
+	case '\a': write_string(w, `\a`, &n) or_return
+	case '\b': write_string(w, `\b`, &n) or_return
+	case '\e': write_string(w, `\e`, &n) or_return
+	case '\f': write_string(w, `\f`, &n) or_return
+	case '\n': write_string(w, `\n`, &n) or_return
+	case '\r': write_string(w, `\r`, &n) or_return
+	case '\t': write_string(w, `\t`, &n) or_return
+	case '\v': write_string(w, `\v`, &n) or_return
 	case:
 		switch c := r; {
 		case c < ' ':
-			n_write_byte(w, '\\', &n)                      or_return
-			n_write_byte(w, 'x', &n)                       or_return
-			n_write_byte(w, DIGITS_LOWER[byte(c)>>4], &n)  or_return
-			n_write_byte(w, DIGITS_LOWER[byte(c)&0xf], &n) or_return
+			write_byte(w, '\\', &n)                      or_return
+			write_byte(w, 'x', &n)                       or_return
+			write_byte(w, DIGITS_LOWER[byte(c)>>4], &n)  or_return
+			write_byte(w, DIGITS_LOWER[byte(c)&0xf], &n) or_return
 
 		case c > utf8.MAX_RUNE:
 			c = 0xfffd
 			fallthrough
 		case c < 0x10000:
-			n_write_byte(w, '\\', &n) or_return
-			n_write_byte(w, 'u', &n)  or_return
+			write_byte(w, '\\', &n) or_return
+			write_byte(w, 'u', &n)  or_return
 			for s := 12; s >= 0; s -= 4 {
-				n_write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
+				write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
 			}
 		case:
-			n_write_byte(w, '\\', &n) or_return
-			n_write_byte(w, 'U', &n)  or_return
+			write_byte(w, '\\', &n) or_return
+			write_byte(w, 'U', &n)  or_return
 			for s := 28; s >= 0; s -= 4 {
-				n_write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
+				write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
 			}
 		}
 	}
 	return
 }
 
-write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"') -> (n: int, err: Error) {
-	n_write_byte(w, quote, &n) or_return
+write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written: ^int = nil) -> (n: int, err: Error) {
+	defer if n_written != nil {
+		n_written^ += n
+	}
+	write_byte(w, quote, &n) or_return
 	for width, s := 0, str; len(s) > 0; s = s[width:] {
 		r := rune(s[0])
 		width = 1
@@ -185,17 +185,17 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"') -> (n: in
 			r, width = utf8.decode_rune_in_string(s)
 		}
 		if width == 1 && r == utf8.RUNE_ERROR {
-			n_write_byte(w, '\\', &n)                   or_return
-			n_write_byte(w, 'x', &n)                    or_return
-			n_write_byte(w, DIGITS_LOWER[s[0]>>4], &n)  or_return
-			n_write_byte(w, DIGITS_LOWER[s[0]&0xf], &n) or_return
+			write_byte(w, '\\', &n)                   or_return
+			write_byte(w, 'x', &n)                    or_return
+			write_byte(w, DIGITS_LOWER[s[0]>>4], &n)  or_return
+			write_byte(w, DIGITS_LOWER[s[0]&0xf], &n) or_return
 			continue
 		}
 
 		n_wrapper(write_escaped_rune(w, r, quote), &n) or_return
 
 	}
-	n_write_byte(w, quote, &n) or_return
+	write_byte(w, quote, &n) or_return
 	return
 }
 

+ 124 - 127
core/reflect/types.odin

@@ -349,244 +349,241 @@ write_type_builder :: proc(buf: ^strings.Builder, ti: ^Type_Info) -> int {
 	n, _ := write_type_writer(strings.to_writer(buf), ti)
 	return n
 }
-write_type_writer :: proc(w: io.Writer, ti: ^Type_Info) -> (n: int, err: io.Error) {
-	if ti == nil {
-		return io.write_string(w, "nil")
+write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -> (n: int, err: io.Error) {
+	defer if n_written != nil {
+		n_written^ += n
 	}
-
-	_n1 :: proc(err: io.Error, n: ^int) -> io.Error { 
-		n^ += 1 if err == nil else 0 
-		return err
+	if ti == nil {
+		io.write_string(w, "nil", &n) or_return
+		return
 	}
-	_n2 :: io.n_wrapper
-	_n :: proc{_n1, _n2}
-
+	
 	switch info in ti.variant {
 	case Type_Info_Named:
-		return io.write_string(w, info.name)
+		io.write_string(w, info.name, &n) or_return
 	case Type_Info_Integer:
 		switch ti.id {
-		case int:     return io.write_string(w, "int")
-		case uint:    return io.write_string(w, "uint")
-		case uintptr: return io.write_string(w, "uintptr")
+		case int:     io.write_string(w, "int",     &n) or_return
+		case uint:    io.write_string(w, "uint",    &n) or_return
+		case uintptr: io.write_string(w, "uintptr", &n) or_return
 		case:
-			_n(io.write_byte(w, 'i' if info.signed else 'u'), &n) or_return
-			_n(io.write_i64(w, i64(8*ti.size), 10),           &n) or_return
+			io.write_byte(w, 'i' if info.signed else 'u', &n) or_return
+			io.write_i64(w, i64(8*ti.size), 10,           &n) or_return
 			switch info.endianness {
 			case .Platform: // Okay
-			case .Little: _n(io.write_string(w, "le"), &n) or_return
-			case .Big:    _n(io.write_string(w, "be"), &n) or_return
+			case .Little: io.write_string(w, "le", &n) or_return
+			case .Big:    io.write_string(w, "be", &n) or_return
 			}
 		}
 	case Type_Info_Rune:
-		_n(io.write_string(w, "rune"), &n) or_return
+		io.write_string(w, "rune", &n) or_return
 	case Type_Info_Float:
-		_n(io.write_byte(w, 'f'), &n)               or_return
-		_n(io.write_i64(w, i64(8*ti.size), 10), &n) or_return
+		io.write_byte(w, 'f', &n)               or_return
+		io.write_i64(w, i64(8*ti.size), 10, &n) or_return
 		switch info.endianness {
 		case .Platform: // Okay
-		case .Little: _n(io.write_string(w, "le"), &n) or_return
-		case .Big:    _n(io.write_string(w, "be"), &n) or_return
+		case .Little: io.write_string(w, "le", &n) or_return
+		case .Big:    io.write_string(w, "be", &n) or_return
 		}
 	case Type_Info_Complex:
-		_n(io.write_string(w, "complex"), &n)       or_return
-		_n(io.write_i64(w, i64(8*ti.size), 10), &n) or_return
+		io.write_string(w, "complex", &n)       or_return
+		io.write_i64(w, i64(8*ti.size), 10, &n) or_return
 	case Type_Info_Quaternion:
-		_n(io.write_string(w, "quaternion"), &n)    or_return
-		_n(io.write_i64(w, i64(8*ti.size), 10), &n) or_return
+		io.write_string(w, "quaternion", &n)    or_return
+		io.write_i64(w, i64(8*ti.size), 10, &n) or_return
 	case Type_Info_String:
 		if info.is_cstring {
-			_n(io.write_string(w, "cstring"), &n) or_return
+			io.write_string(w, "cstring", &n) or_return
 		} else {
-			_n(io.write_string(w, "string"), &n)  or_return
+			io.write_string(w, "string", &n)  or_return
 		}
 	case Type_Info_Boolean:
 		switch ti.id {
-		case bool: _n(io.write_string(w, "bool"), &n) or_return
+		case bool: io.write_string(w, "bool", &n) or_return
 		case:
-			_n(io.write_byte(w, 'b'), &n)               or_return
-			_n(io.write_i64(w, i64(8*ti.size), 10), &n) or_return
+			io.write_byte(w, 'b', &n)               or_return
+			io.write_i64(w, i64(8*ti.size), 10, &n) or_return
 		}
 	case Type_Info_Any:
-		_n(io.write_string(w, "any"), &n) or_return
+		io.write_string(w, "any", &n) or_return
 
 	case Type_Info_Type_Id:
-		_n(io.write_string(w, "typeid"), &n) or_return
+		io.write_string(w, "typeid", &n) or_return
 
 	case Type_Info_Pointer:
 		if info.elem == nil {
-			return io.write_string(w, "rawptr")
+			io.write_string(w, "rawptr", &n) or_return
 		} else {
-			_n(io.write_string(w, "^"), &n) or_return
-			return write_type(w, info.elem)
+			io.write_string(w, "^", &n) or_return
+			write_type(w, info.elem, &n) or_return
 		}
 	case Type_Info_Multi_Pointer:
-		_n(io.write_string(w, "[^]"), &n) or_return
-		return write_type(w, info.elem)
+		io.write_string(w, "[^]", &n) or_return
+		write_type(w, info.elem, &n) or_return
 	case Type_Info_Procedure:
-		_n(io.write_string(w, "proc"), &n) or_return
+		io.write_string(w, "proc", &n) or_return
 		if info.params == nil {
-			_n(io.write_string(w, "()"), &n) or_return
+			io.write_string(w, "()", &n) or_return
 		} else {
 			t := info.params.variant.(Type_Info_Tuple)
-			_n(io.write_string(w, "("), &n) or_return
+			io.write_string(w, "(", &n) or_return
 			for t, i in t.types {
 				if i > 0 {
-					_n(io.write_string(w, ", "), &n) or_return
+					io.write_string(w, ", ", &n) or_return
 				}
-				_n(write_type(w, t), &n) or_return
+				write_type(w, t, &n) or_return
 			}
-			_n(io.write_string(w, ")"), &n) or_return
+			io.write_string(w, ")", &n) or_return
 		}
 		if info.results != nil {
-			_n(io.write_string(w, " -> "), &n)  or_return
-			_n(write_type(w, info.results), &n) or_return
+			io.write_string(w, " -> ", &n)  or_return
+			write_type(w, info.results, &n) or_return
 		}
 	case Type_Info_Tuple:
 		count := len(info.names)
 		if count != 1 { 
-			_n(io.write_string(w, "("), &n) or_return 
+			io.write_string(w, "(", &n) or_return 
 		}
 		for name, i in info.names {
-			if i > 0 { _n(io.write_string(w, ", "), &n) or_return }
+			if i > 0 { io.write_string(w, ", ", &n) or_return }
 
 			t := info.types[i]
 
 			if len(name) > 0 {
-				_n(io.write_string(w, name), &n) or_return
-				_n(io.write_string(w, ": "), &n) or_return
+				io.write_string(w, name, &n) or_return
+				io.write_string(w, ": ", &n) or_return
 			}
-			_n(write_type(w, t), &n) or_return
+			write_type(w, t, &n) or_return
 		}
 		if count != 1 { 
-			_n(io.write_string(w, ")"), &n) or_return 
+			io.write_string(w, ")", &n) or_return 
 		}
 
 	case Type_Info_Array:
-		_n(io.write_string(w, "["),              &n) or_return
-		_n(io.write_i64(w, i64(info.count), 10), &n) or_return
-		_n(io.write_string(w, "]"),              &n) or_return
-		_n(write_type(w, info.elem),             &n) or_return
+		io.write_string(w, "[",              &n) or_return
+		io.write_i64(w, i64(info.count), 10, &n) or_return
+		io.write_string(w, "]",              &n) or_return
+		write_type(w, info.elem,             &n) or_return
 
 	case Type_Info_Enumerated_Array:
-		_n(io.write_string(w, "["),   &n) or_return
-		_n(write_type(w, info.index), &n) or_return
-		_n(io.write_string(w, "]"),   &n) or_return
-		_n(write_type(w, info.elem),  &n) or_return
+		io.write_string(w, "[",   &n) or_return
+		write_type(w, info.index, &n) or_return
+		io.write_string(w, "]",   &n) or_return
+		write_type(w, info.elem,  &n) or_return
 
 	case Type_Info_Dynamic_Array:
-		_n(io.write_string(w, "[dynamic]"), &n) or_return
-		_n(write_type(w, info.elem),        &n) or_return
+		io.write_string(w, "[dynamic]", &n) or_return
+		write_type(w, info.elem,        &n) or_return
 	case Type_Info_Slice:
-		_n(io.write_string(w, "[]"), &n) or_return
-		_n(write_type(w, info.elem), &n) or_return
+		io.write_string(w, "[]", &n) or_return
+		write_type(w, info.elem, &n) or_return
 
 	case Type_Info_Map:
-		_n(io.write_string(w, "map["), &n) or_return
-		_n(write_type(w, info.key),    &n) or_return
-		_n(io.write_byte(w, ']'),      &n) or_return
-		_n(write_type(w, info.value),  &n) or_return
+		io.write_string(w, "map[", &n) or_return
+		write_type(w, info.key,    &n) or_return
+		io.write_byte(w, ']',      &n) or_return
+		write_type(w, info.value,  &n) or_return
 
 	case Type_Info_Struct:
 		switch info.soa_kind {
 		case .None: // Ignore
 		case .Fixed:
-			_n(io.write_string(w, "#soa["),        &n) or_return
-			_n(io.write_i64(w, i64(info.soa_len)), &n) or_return
-			_n(io.write_byte(w, ']'),              &n) or_return
-			_n(write_type(w, info.soa_base_type),  &n) or_return
+			io.write_string(w, "#soa[",           &n) or_return
+			io.write_i64(w, i64(info.soa_len), 10 &n) or_return
+			io.write_byte(w, ']',                 &n) or_return
+			write_type(w, info.soa_base_type,     &n) or_return
 			return
 		case .Slice:
-			_n(io.write_string(w, "#soa[]"),      &n) or_return
-			_n(write_type(w, info.soa_base_type), &n) or_return
+			io.write_string(w, "#soa[]",      &n) or_return
+			write_type(w, info.soa_base_type, &n) or_return
 			return
 		case .Dynamic:
-			_n(io.write_string(w, "#soa[dynamic]"), &n) or_return
-			_n(write_type(w, info.soa_base_type),   &n) or_return
+			io.write_string(w, "#soa[dynamic]", &n) or_return
+			write_type(w, info.soa_base_type,   &n) or_return
 			return
 		}
 
-		_n(io.write_string(w, "struct "), &n) or_return
-		if info.is_packed    { _n(io.write_string(w, "#packed "),    &n) or_return }
-		if info.is_raw_union { _n(io.write_string(w, "#raw_union "), &n) or_return }
+		io.write_string(w, "struct ", &n) or_return
+		if info.is_packed    { io.write_string(w, "#packed ",    &n) or_return }
+		if info.is_raw_union { io.write_string(w, "#raw_union ", &n) or_return }
 		if info.custom_align {
-			_n(io.write_string(w, "#align "),      &n) or_return
-			_n(io.write_i64(w, i64(ti.align), 10), &n) or_return
-			_n(io.write_byte(w, ' '),              &n) or_return
+			io.write_string(w, "#align ",      &n) or_return
+			io.write_i64(w, i64(ti.align), 10, &n) or_return
+			io.write_byte(w, ' ',              &n) or_return
 		}
-		_n(io.write_byte(w, '{'), &n) or_return
+		io.write_byte(w, '{', &n) or_return
 		for name, i in info.names {
-			if i > 0 { _n(io.write_string(w, ", "), &n) or_return }
-			_n(io.write_string(w, name),     &n) or_return
-			_n(io.write_string(w, ": "),     &n) or_return
-			_n(write_type(w, info.types[i]), &n) or_return
+			if i > 0 { io.write_string(w, ", ", &n) or_return }
+			io.write_string(w, name,     &n) or_return
+			io.write_string(w, ": ",     &n) or_return
+			write_type(w, info.types[i], &n) or_return
 		}
-		_n(io.write_byte(w, '}'), &n) or_return
+		io.write_byte(w, '}', &n) or_return
 
 	case Type_Info_Union:
-		_n(io.write_string(w, "union "), &n) or_return
+		io.write_string(w, "union ", &n) or_return
 		if info.maybe {
-			_n(io.write_string(w, "#maybe "), &n) or_return
+			io.write_string(w, "#maybe ", &n) or_return
 		}
 		if info.custom_align {
-			_n(io.write_string(w, "#align "),      &n) or_return
-			_n(io.write_i64(w, i64(ti.align), 10), &n) or_return
-			_n(io.write_byte(w, ' '),              &n) or_return
+			io.write_string(w, "#align ",      &n) or_return
+			io.write_i64(w, i64(ti.align), 10, &n) or_return
+			io.write_byte(w, ' ',              &n) or_return
 		}
-		_n(io.write_byte(w, '{'), &n) or_return
+		io.write_byte(w, '{', &n) or_return
 		for variant, i in info.variants {
-			if i > 0 { _n(io.write_string(w, ", "), &n) or_return }
-			_n(write_type(w, variant), &n) or_return
+			if i > 0 { io.write_string(w, ", ", &n) or_return }
+			write_type(w, variant, &n) or_return
 		}
-		_n(io.write_byte(w, '}'), &n) or_return
+		io.write_byte(w, '}', &n) or_return
 
 	case Type_Info_Enum:
-		_n(io.write_string(w, "enum "), &n) or_return
-		_n(write_type(w, info.base), &n) or_return
-		_n(io.write_string(w, " {"), &n) or_return
+		io.write_string(w, "enum ", &n) or_return
+		write_type(w, info.base, &n) or_return
+		io.write_string(w, " {", &n) or_return
 		for name, i in info.names {
-			if i > 0 { _n(io.write_string(w, ", "), &n) or_return }
-			_n(io.write_string(w, name), &n) or_return
+			if i > 0 { io.write_string(w, ", ", &n) or_return }
+			io.write_string(w, name, &n) or_return
 		}
-		_n(io.write_byte(w, '}'), &n) or_return
+		io.write_byte(w, '}', &n) or_return
 
 	case Type_Info_Bit_Set:
-		_n(io.write_string(w, "bit_set["), &n) or_return
+		io.write_string(w, "bit_set[", &n) or_return
 		switch {
 		case is_enum(info.elem):
-			_n(write_type(w, info.elem), &n) or_return
+			write_type(w, info.elem, &n) or_return
 		case is_rune(info.elem):
-			_n(io.write_encoded_rune(w, rune(info.lower)), &n) or_return
-			_n(io.write_string(w, ".."),                   &n) or_return
-			_n(io.write_encoded_rune(w, rune(info.upper)), &n) or_return
+			io.write_encoded_rune(w, rune(info.lower), true, &n) or_return
+			io.write_string(w, "..",                         &n) or_return
+			io.write_encoded_rune(w, rune(info.upper), true, &n) or_return
 		case:
-			_n(io.write_i64(w, info.lower, 10), &n) or_return
-			_n(io.write_string(w, ".."),        &n) or_return
-			_n(io.write_i64(w, info.upper, 10), &n) or_return
+			io.write_i64(w, info.lower, 10, &n) or_return
+			io.write_string(w, "..",        &n) or_return
+			io.write_i64(w, info.upper, 10, &n) or_return
 		}
 		if info.underlying != nil {
-			_n(io.write_string(w, "; "),       &n) or_return
-			_n(write_type(w, info.underlying), &n) or_return
+			io.write_string(w, "; ",       &n) or_return
+			write_type(w, info.underlying, &n) or_return
 		}
-		_n(io.write_byte(w, ']'), &n) or_return
+		io.write_byte(w, ']', &n) or_return
 
 	case Type_Info_Simd_Vector:
-		_n(io.write_string(w, "#simd["),     &n) or_return
-		_n(io.write_i64(w, i64(info.count)), &n) or_return
-		_n(io.write_byte(w, ']'),            &n) or_return
-		_n(write_type(w, info.elem),         &n) or_return
+		io.write_string(w, "#simd[",         &n) or_return
+		io.write_i64(w, i64(info.count), 10, &n) or_return
+		io.write_byte(w, ']',                &n) or_return
+		write_type(w, info.elem,             &n) or_return
 
 	case Type_Info_Relative_Pointer:
-		_n(io.write_string(w, "#relative("), &n) or_return
-		_n(write_type(w, info.base_integer), &n) or_return
-		_n(io.write_string(w, ") "),         &n) or_return
-		_n(write_type(w, info.pointer),      &n) or_return
+		io.write_string(w, "#relative(", &n) or_return
+		write_type(w, info.base_integer, &n) or_return
+		io.write_string(w, ") ",         &n) or_return
+		write_type(w, info.pointer,      &n) or_return
 
 	case Type_Info_Relative_Slice:
-		_n(io.write_string(w, "#relative("), &n) or_return
-		_n(write_type(w, info.base_integer), &n) or_return
-		_n(io.write_string(w, ") "),         &n) or_return
-		_n(write_type(w, info.slice),        &n) or_return
+		io.write_string(w, "#relative(", &n) or_return
+		write_type(w, info.base_integer, &n) or_return
+		io.write_string(w, ") ",         &n) or_return
+		write_type(w, info.slice,        &n) or_return
 	}
 
 	return