1# io - moving bytes between streams.2#3# There are no interfaces in tau, so a reader is simply any object with a4# Read(n) that returns up to n bytes, and an empty bytes value when there is5# nothing left. A writer is any object with a Write(data) returning how many6# bytes went out. Files, network connections and buffers all have that shape,7# so they work here without knowing about each other.89bufsize = 327681011# IsReader reports whether r can be read from.12IsReader = fn(r) { type(r) == "object" && type(r.Read) == "closure" }1314# IsWriter reports whether w can be written to.15IsWriter = fn(w) { type(w) == "object" && type(w.Write) == "closure" }1617# ReadAll returns everything left in r.18ReadAll = fn(r) {19 if !IsReader(r) {20 return error("io: ReadAll wants a reader, got {type(r)}")21 }2223 out = bytes(0)24 for {25 if failed(chunk = r.Read(bufsize)) {26 return chunk27 }28 if len(chunk) == 0 {29 return out30 }31 out = out + chunk32 }33}3435# ReadFull returns exactly n bytes, or fewer if the stream ends first.36ReadFull = fn(r, n) {37 if !IsReader(r) {38 return error("io: ReadFull wants a reader, got {type(r)}")39 }4041 out = bytes(0)42 for len(out) < n {43 if failed(chunk = r.Read(n - len(out))) {44 return chunk45 }46 if len(chunk) == 0 {47 return out48 }49 out = out + chunk50 }5152 return out53}5455# Copy moves everything from src to dst and returns how many bytes it moved.56Copy = fn(dst, src) {57 if !IsWriter(dst) {58 return error("io: Copy wants a writer, got {type(dst)}")59 }60 if !IsReader(src) {61 return error("io: Copy wants a reader, got {type(src)}")62 }6364 total = 065 for {66 if failed(chunk = src.Read(bufsize)) {67 return chunk68 }69 if len(chunk) == 0 {70 return total71 }72 if failed(n = dst.Write(chunk)) {73 return n74 }75 total = total + n76 }77}7879# CopyN moves at most n bytes from src to dst.80CopyN = fn(dst, src, n) {81 if failed(data = ReadFull(src, n)) {82 return data83 }84 return dst.Write(data)85}8687# WriteString writes a string to a writer.88WriteString = fn(w, s) {89 if !IsWriter(w) {90 return error("io: WriteString wants a writer, got {type(w)}")91 }92 return w.Write(s)93}