123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- const std = @import("std");
- const mem = std.mem;
- const fmt = std.fmt;
- const debug = std.debug;
- // read n bytes or return err
- fn readExactly(reader: anytype, buffer: []u8) !void{
- var have: usize = 0;
- while(have < buffer.len){
- const amt = try reader.read(buffer[have..]);
- if(amt == 0){ return error.EndOfStream; }
- have += amt;
- }
- }
- pub fn main() !void{
- const stdin = std.io.getStdIn().reader();
- const stdout = std.io.getStdOut().writer();
-
- var buffer: [64]u8 = [_]u8{0} ** 64;
- var len_bytes_buf: [2]u8 = [_]u8{0} ** 2;
- var reply_buffer: [64]u8 = [_]u8{0} ** 64;
-
- while(true){
- // read msg length (2 bytes, big-endian)
- readExactly(stdin, &len_bytes_buf) catch |err|{
- if(err == error.EndOfStream){ break; }
- return err;
- };
-
- const msg_len = @as(u16, len_bytes_buf[0]) << 8 | len_bytes_buf[1]; // convert to u16, big-endian
-
- //std.debug.print("Full buffer: ", .{});
- //for(buffer[0..msg_len]) |b|{
- // std.debug.print("{c}", .{b});
- //}
- //std.debug.print("\n", .{});
-
- if(msg_len == 0 or msg_len > buffer.len){
- try stdout.writeAll(&[2]u8{ 0, 0 });
- continue;
- }
-
- readExactly(stdin, buffer[0..msg_len]) catch |err|{ // read msg
- if(err == error.EndOfStream){ break; }
- return err;
- };
- //debug.print("RECV: '{s}'\n", .{buffer[0..msg_len]});
-
- var fbs = std.io.fixedBufferStream(&reply_buffer);
- var writer = fbs.writer();
-
-
- if(mem.eql(u8, buffer[0..msg_len], "hello")){
- try writer.writeAll("Hello world!");
-
- }else if(mem.startsWith(u8, buffer[0..msg_len], "factorial ")){
- const prefix_len = "factorial ".len;
- const n_str = buffer[prefix_len..msg_len];
- //std.debug.print("n_str = '{s}' ({} chars)\n", .{ n_str, n_str.len });
-
- const n = fmt.parseInt(isize, n_str, 10) catch {
- //std.debug.print("error:PARSE ERROR for '{s}'\n", .{n_str});
- try writer.writeAll("error:badarg");
- //try writer.writeAll("0");
- try sendResponse(stdout, fbs.getWritten());
- continue;
- };
-
- if(n < 0){
- //try writer.writeAll("error:badarg");
- //std.debug.print("n < 0 -> badarg\n", .{});
- //try writer.writeAll("0");
- try writer.writeAll("error:badarg: n < 0");
- }else if(n > 34){
- //std.debug.print("n > 34 -> too large\n", .{});
- //try writer.writeAll("0");
- try writer.writeAll("error:input too large, max is 34");
- }else{
- var result: u128 = 1;
- var i = @as(u128, @intCast(n));
- while (i > 1) : (i -= 1) result *= i;
- //std.debug.print("factorial({d}) = {d}\n", .{n, result});
- try fmt.formatInt(result, 10, .lower, .{}, writer);
- }
-
- }else{
- try writer.writeAll("error:unknown command");
- }
-
- try sendResponse(stdout, fbs.getWritten());
- }
- }
- fn sendResponse(writer: anytype, response: []const u8) !void{
- const len: u16 = @intCast(response.len);
-
- //std.debug.print("SEND: len={d} (0x{X:0>4}) data='{s}'\n", .{ len, len, response });
-
- try writer.writeByte(@intCast((len >> 8) & 0xFF)); // high byte
- try writer.writeByte(@intCast(len & 0xFF)); // low byte
- try writer.writeAll(response);
- }
|