local type InputStream = record str: string offset: number refill: function(): string new: function(InputStream): InputStream new: function(InputStream, function(): string): InputStream setRefill: function(InputStream, function(): string) readCurrentCharacter: function(): string advanceOffset: function(): string end local istream_mt = {__index = InputStream} function InputStream:_manageBuffer() if not self.str then self.str = self.refill() self.offset = 1 end if self.offset > #self.str + 1 then self.str = self.refill() self.offset = 1 end end -- constructors function InputStream:new(): InputStream return setmetatable( { string = "", offset = 1 } as InputStream, istream_mt) end function InputStream:new(refill: function(): string): InputStream local mt = setmetatable( { string = "", offset = 1 } as InputStream, istream_mt) mt:setRefill(refill) return mt end -- setters/getters function InputStream:setRefill(func: function(): string) self.refill = func end -- function InputStream:readCurrentCharacter(): string self:_manageBuffer() return self.str:sub(self.offset, self.offset) end function InputStream:advanceOffset(): string self.offset = self.offset + 1 self:_manageBuffer() return self.str:sub(self.offset, self.offset) end return InputStream