use bytes; use errors; use fmt; use fs; use io; use os; use strings; use drawing; use drawing::{pos,CHUNKSIZE}; // caller should free return value fn filename_from_world_pos(pos: pos) str = fmt::asprintf("./c.{}.{}.ppm",pos.0,pos.1); fn save_world(state: *server_state) (void | fs::error) = { for (const pic &.. state.pictures) { const filename = filename_from_world_pos(pic.world_pos); fmt::printfln("\t-> {}",filename)!; defer free(filename); const mode = fs::mode::USER_RW | fs::mode::GROUP_RW; const file = os::create(filename, mode)?; defer io::close(file): void; fmt::fprintf(file, "P6\n{} {}\n{}\n", pic.w, pic.h, 255)?; let buf: []u8 = alloc([0...],3*pic.w*pic.h); defer free(buf); for (let i = 0z; i < pic.w * pic.h; i += 1) { const px = pic.d[i]; buf[3*i ] = ((px>>16)&0xff): u8; buf[3*i+1] = ((px>>8) &0xff): u8; buf[3*i+2] = ((px) &0xff): u8; }; io::writeall(file, buf)?; }; }; fn new_picture(world_pos: pos) drawing::picture = { let picture_buf: []u32 = alloc([0xffffff...], CHUNKSIZE*CHUNKSIZE); return drawing::picture { w = CHUNKSIZE, h = CHUNKSIZE, d = picture_buf: *[*]u32, world_pos = world_pos, }; }; type bad_header = !void; // loads the chunk at the given position from the filesystem, // or, if no file is found, creates a fresh new chunk fn load_picture_from_file(world_pos: pos) (drawing::picture | fs::error | bad_header) = { const filename = filename_from_world_pos(world_pos); defer free(filename); const file = match (os::open(filename)) { case let f: io::file => yield f; case errors::noentry => return new_picture(world_pos); case let e: fs::error => return e; }; fmt::printfln("reading from {}",filename)!; defer { fmt::printfln("closing {}",filename)!; match (io::close(file)) { case let err: io::error => fmt::println("error",io::strerror(err))!; case => yield; }; }; const header = fmt::asprintf("P6\n{} {}\n{}\n",CHUNKSIZE,CHUNKSIZE,255); defer free(header); const header_bytes = strings::toutf8(header); let header_buf: []u8 = alloc([0...],len(header_bytes)); defer free(header_buf); io::readall(file, header_buf)?; if (!bytes::equal(header_buf, header_bytes)) return bad_header; let file_buf: []u8 = alloc([0...], 3*CHUNKSIZE*CHUNKSIZE); defer free(file_buf); io::readall(file, file_buf)?; let picture_buf: []u32 = alloc([0...], CHUNKSIZE*CHUNKSIZE); for (let i = 0z; i < len(picture_buf); i += 1) { picture_buf[i] = (file_buf[3*i]:u32<<16) |(file_buf[3*i+1]:u32<<8) |(file_buf[3*i+2]:u32); }; return drawing::picture { w = CHUNKSIZE, h = CHUNKSIZE, d = picture_buf: *[*]u32, world_pos = world_pos, }; };